@font-face{font-family:Disp;src:url(display.woff2) format("woff2-variations"),url(display.woff2) format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:Text;src:url(text.woff2) format("woff2-variations"),url(text.woff2) format("woff2");font-weight:400 700;font-stretch:75% 100%;font-display:swap}
:root{--ink:#14122b;--paper:#fbf4e6;--muted:#55506a;--acc:#f6b21b;--on:#14122b;--gut:clamp(18px,4.4vw,72px)}
*{box-sizing:border-box;margin:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;background:var(--ink);overflow-x:clip}
body{font:400 clamp(16px,1.1vw,18px)/1.55 Text,system-ui,sans-serif;color:var(--ink);background:var(--ink);overflow-x:clip;transition:background-color .4s}
ul,ol{list-style:none;padding:0}
a{color:inherit}
h1,h2,h3,h4{font-weight:inherit;font-size:inherit}
#room{position:fixed;inset:0;overflow:hidden;background:#35c6d4;visibility:hidden;pointer-events:none}
#room img{position:absolute;left:0;top:0;max-width:none;transform-origin:0 0;display:block}
.nogl #room{display:none}
#world{position:fixed;inset:0;width:100%;height:100vh;height:100lvh;display:block}
/* No intro: the world fades in over 0.4 s once its first frame is drawn. Without script, or if it never draws, it shows at once. */
.js:not(.live):not(.static) #world{opacity:0}
#world{transition:opacity .4s}
.nogl #world{display:none}
#panes,#acts{position:fixed;inset:0;width:100%;height:100vh;height:100lvh;display:block;pointer-events:none;opacity:0;visibility:hidden}
.nogl #panes,.nogl #acts{display:none}
.grain{position:fixed;inset:0;pointer-events:none;opacity:.05;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E")}
main,.top,.rail,.dock{position:relative;z-index:2}
:focus-visible{outline:3px solid var(--ink);outline-offset:3px;box-shadow:0 0 0 3px var(--paper);border-radius:3px}
.skip{position:fixed;left:12px;top:12px;z-index:30;background:var(--paper);padding:12px 16px;transform:translateY(-200%)}
.skip:focus{transform:none}

/* Header + controls */
.top{position:fixed;left:0;right:0;top:0;display:flex;justify-content:space-between;align-items:center;padding:14px var(--gut);z-index:10;pointer-events:none}
.top a{pointer-events:auto}
.mark{display:inline-flex;gap:9px;align-items:center;min-height:44px;padding:0 14px 0 10px;background:var(--paper);font:800 19px/1 Disp,sans-serif;letter-spacing:.03em;text-transform:uppercase;text-decoration:none}
.ministar{width:20px;height:20px;fill:var(--ink)}
.top-r{display:flex;gap:8px}
.pill{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:44px;min-width:44px;padding:0 18px;border:0;font:800 18px/1 Disp,sans-serif;letter-spacing:.05em;text-transform:uppercase;text-decoration:none;cursor:pointer;color:var(--ink);background:var(--paper);transition:transform .25s cubic-bezier(.2,.8,.2,1),background-color .2s,color .2s}
.pill:hover{transform:translateY(-2px)}
.pill.ghost{background:var(--paper)}
.pill.solid{background:var(--ink);color:var(--paper)}
.pill.line{box-shadow:inset 0 0 0 2px var(--ink);background:transparent}
.pill.line:hover{background:var(--ink);color:var(--paper)}
.dock{position:fixed;right:clamp(12px,var(--gut),72px);bottom:max(14px,env(safe-area-inset-bottom));display:flex;gap:8px;z-index:9}
.go{background:var(--ink);color:var(--paper);box-shadow:0 8px 24px #14122b40}
.go i{width:12px;height:12px;background:var(--acc);clip-path:polygon(0 0,100% 50%,0 100%);transform:rotate(90deg);animation:nudge 1.8s ease-in-out infinite}
.go.last i{transform:rotate(-90deg);animation:none}
@keyframes nudge{50%{translate:0 3px}}
.round{padding:0;width:44px}
.round svg{width:14px;height:14px;fill:currentColor}
.round .i-r{display:none}.round[aria-pressed=true] .i-r{display:block}.round[aria-pressed=true] .i-p{display:none}
.rail{position:fixed;right:clamp(10px,1.4vw,22px);top:50%;transform:translateY(-50%);z-index:8}
.rail a{display:flex;justify-content:flex-end;align-items:center;gap:8px;height:24px;min-width:34px;text-decoration:none}
.rail a::after{content:"";width:13px;height:6px;background:var(--paper);box-shadow:0 0 0 1.5px var(--ink);transition:width .25s}
.rail a[aria-current]::after{width:28px;background:var(--ink);box-shadow:0 0 0 1.5px var(--paper)}
.rail span{position:absolute;right:42px;opacity:0;pointer-events:none;background:var(--paper);padding:2px 8px;font:800 15px/1.2 Disp,sans-serif;letter-spacing:.05em;text-transform:uppercase;white-space:nowrap}
.rail a:hover span,.rail a:focus-visible span{opacity:1}

/* Paper strips carry every headline: opaque, so contrast holds over any frame */
.strip{display:block;width:fit-content;background:var(--paper);color:var(--ink);padding:.05em .16em .02em;rotate:-.7deg;transition:clip-path .75s cubic-bezier(.7,0,.15,1)}
.strip>span{display:block;transition:transform .85s cubic-bezier(.2,.8,.2,1)}
.strip{max-width:100%}
.strip.s1{rotate:.5deg;margin-left:.8em;margin-top:-.03em;max-width:calc(100% - .8em)}
.strip.s2{rotate:-.4deg;margin-left:1.5em;margin-top:-.03em;max-width:calc(100% - 1.5em)}
.js:not(.static) .big:not(.in) .strip{clip-path:inset(0 100% 0 0)}
.js:not(.static) .big:not(.in) .strip>span{transform:translateX(-.4em)}
.big .strip{clip-path:inset(0 -2% 0 0)}
.s1{transition-delay:.12s}.s2{transition-delay:.24s}.sub .strip{transition-delay:.3s}.kicker .strip{transition-delay:0s}
.big,.huge{font-family:Disp,Impact,sans-serif;font-weight:900;text-transform:uppercase;line-height:.98;letter-spacing:.002em}
.big{font-size:clamp(48px,6.4vw,104px);filter:drop-shadow(5px 7px 0 #14122b24)}
.huge{font-size:clamp(64px,min(7.6vw,14vh),136px);line-height:.92;filter:drop-shadow(7px 9px 0 #14122b26)}
.kicker,.sub{font:800 clamp(18px,1.7vw,27px)/1.1 Disp,sans-serif;letter-spacing:.05em;text-transform:uppercase;margin-bottom:12px}
.sub{margin:14px 0 0}
.sub .strip{background:var(--ink);color:var(--paper)}
.lead{margin-top:16px;max-width:30em;background:var(--paper);padding:14px 18px;font-size:clamp(16px,1.25vw,20px);line-height:1.4;transition:opacity .6s .5s,translate .6s .5s}
.lead .read{display:flex;width:fit-content;margin-top:12px}

/* Cards */
.card,.sheet{background:var(--paper);color:var(--ink)}
.card{padding:20px 22px 22px;max-width:30em;box-shadow:6px 8px 0 #14122b2e;transition:opacity .6s,translate .7s cubic-bezier(.2,.8,.2,1)}
.js:not(.static) .card:not(.in){opacity:0;translate:0 26px}
.card p+p{margin-top:.55em}
.card h3,.job h3{font:800 21px/1.15 Disp,sans-serif;letter-spacing:.03em;text-transform:uppercase;margin-top:.8em}
.card .who+h3{margin-top:.5em}
.card h3+p{margin-top:.15em}
.tag{display:flex;flex-wrap:wrap;gap:10px;align-items:center;font:800 18px/1.1 Disp,sans-serif;letter-spacing:.06em;text-transform:uppercase;margin-bottom:3px}
.tag-n{background:var(--acc);color:var(--on);padding:3px 8px 2px}
.who{font-size:.875em;color:var(--muted)}
.card .does{margin-top:.55em;font-size:clamp(17px,1.3vw,21px);line-height:1.45;color:var(--ink)}
.job{margin-top:14px;padding-top:12px;border-top:2px dashed #14122b4d}
.job h3{margin-top:0}
.when{font-weight:600;font-size:.875em}
.org{color:var(--muted);font-size:.92em}
.st1{--acc:#f6b21b;--on:#14122b}.st2{--acc:#2447d8;--on:#fff}.st3{--acc:#f2701d;--on:#14122b}.st4{--acc:#0a7359;--on:#fff}.st5{--acc:#a9c86a;--on:#14122b}.st6{--acc:#4a2fa8;--on:#fff}.st7{--acc:#1fb5c4;--on:#14122b}.st8{--acc:#b4482a;--on:#fff}
.dossier,.usine{--acc:#14122b;--on:#fbf4e6}

/* Layout: phone first, natural flow */
section{position:relative}
.hero .stage{min-height:100svh;padding:calc(58px + 5svh) 16px 130px;display:flex;flex-direction:column;justify-content:flex-start}
.station{padding:13svh 16px 42svh}
.station .big{margin-bottom:44svh}
.station .card{margin-left:auto;margin-right:auto}
.usine{min-height:260svh;padding:0}
.usine .stage{position:sticky;top:0;height:100svh;padding:72px 16px 88px;display:flex;flex-direction:column;justify-content:space-between}
.station.usine .stage{justify-content:flex-end;gap:14px}
.usine .stage{opacity:calc(1 - var(--out,0))}
.usine .big{margin:0}
.usine .card{order:-1;margin:0;max-width:none;opacity:var(--card,0);translate:0 calc((1 - var(--card,0)) * 20px)}
.dossier{padding:40svh 12px}
.finale{padding:62svh 16px 90px}
.finale .stage{max-width:36em;margin:0 auto}
.finale .big{margin-bottom:18px}
.finale .card{max-width:none}
.cta{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.foot{position:relative;margin:30px auto 56px;max-width:36em;background:var(--paper);padding:6px 12px;font-size:.875em;width:fit-content}

.sheet{max-width:1080px;margin:0 auto;padding:32px 22px 36px 42px;--hole:radial-gradient(circle 7px at 16px 50%,#0000 96%,#000) 0 0/100% 44px;-webkit-mask:var(--hole);mask:var(--hole);transition:opacity .7s,translate .8s cubic-bezier(.2,.8,.2,1)}
.js:not(.static) .sheet:not(.in){opacity:0;translate:0 40px}
.sheet .big{margin:8px 0 10px;filter:none}
.inky .strip{background:var(--ink);color:var(--paper)}
.intro{font-size:1.1em;max-width:32em}
.rows{margin-top:18px;border-top:3px solid var(--ink)}
.row{padding:14px 0;border-bottom:1px solid #14122b40}
.row-h{display:flex;flex-wrap:wrap;gap:0 16px;justify-content:space-between;align-items:baseline}
.row h3{font:800 clamp(22px,2.1vw,30px)/1.1 Disp,sans-serif;letter-spacing:.02em;text-transform:uppercase}
.cols-h{font:800 26px/1.1 Disp,sans-serif;letter-spacing:.04em;text-transform:uppercase;margin-top:30px}
.cols-h+.rows{margin-top:8px}
.crates{display:grid;gap:14px;margin-top:20px}
.crate{background:var(--ink);color:var(--paper);padding:20px 22px 22px;transition:transform .3s cubic-bezier(.2,.8,.2,1)}
.crate:hover{transform:translateY(-4px) rotate(-.4deg)}
.crate h3{font:900 clamp(46px,5vw,76px)/1 Disp,sans-serif;text-transform:uppercase}
.crate h3+p{margin-top:8px}
.crate .org{color:#d8d2e6;margin-top:6px}
.link{display:inline-flex;align-items:center;min-height:44px;font-weight:600;color:#ffcb45;text-underline-offset:3px}
.crate :focus-visible{outline-color:var(--paper);box-shadow:none}
.tools{display:grid;gap:0;margin-top:18px;border-top:3px solid var(--ink)}
.tools div{padding:12px 0;border-bottom:1px solid #14122b40}
.tools dt{font:800 22px/1.1 Disp,sans-serif;letter-spacing:.03em;text-transform:uppercase}
.two{display:grid;gap:0 40px}
.plain{margin-top:8px}
.plain li{padding:6px 0;border-bottom:1px solid #14122b40}

@media (min-width:760px){
  .crates{grid-template-columns:1fr 1fr}
  .tools{grid-template-columns:1fr 1fr;column-gap:40px}
  .two{grid-template-columns:1.3fr 1fr}
  .sheet{padding:48px 56px 52px 68px}
  .dossier{padding-inline:clamp(20px,6vw,90px)}
}
/* Desktop: sticky stage, card on one side, world on the other */
@media (min-width:960px) and (min-height:720px){
  .hero{min-height:150vh}
  .hero .stage{position:sticky;top:0;height:100vh;min-height:0;padding:0 var(--gut) 76px;justify-content:flex-end}
  /* The name block is held to the left by its size, never by a box narrower than the text: the paper strip always hugs the full name. */
  .hero .huge .strip{max-width:none;white-space:nowrap}
  .hero .huge .strip.s1{max-width:none}
  .hero .lead{max-width:22em}
  /* Pinned stages hold: pin = section height minus 100vh, so a station's text stays up while its beat plays. */
  .station{padding:0}
  .station:not(.story-stage){min-height:200vh}
  .station.st5:not(.story-stage){min-height:260vh}
  /* The four film pages: the pinned part is stretched, the last 100vh (the exit) keeps its old mapping (warpScene in story.mjs). */
  .story-stage{min-height:220vh}
  .story-stage.ia{min-height:260vh}
  .story-stage.ingenieur{min-height:400vh}
  .station.usine{min-height:320vh}
  .station .stage{position:sticky;top:0;height:100vh;padding:calc(76px + 2vh) calc(var(--gut) + 30px) 84px var(--gut);display:flex;flex-direction:column;justify-content:space-between;align-items:flex-start}
  .station.side-r .stage{align-items:flex-end;padding-left:calc(var(--gut) + 30px);padding-right:calc(var(--gut) + 40px)}
  .station.side-r .big{display:flex;flex-direction:column;align-items:flex-end}
  .station.side-r .strip.s1{margin-left:0;margin-right:.8em}
  .station.side-r .strip.s2{margin-left:0;margin-right:1.5em}
  .station .big{margin:0}
  .station .card{margin:0;width:min(30em,38vw)}
  .big{font-size:clamp(60px,min(6.2vw,13vh),112px)}
  .dossier{padding-top:70vh;padding-bottom:50vh}
  .finale{min-height:200vh;padding:100vh var(--gut) 60px;display:flex;flex-direction:column;justify-content:flex-end}
  .finale .stage{max-width:min(33em,40vw);width:100%;margin:0;display:block}
  .finale .big{margin:0 0 16px}
  .foot{margin:14px 0 70px}
}
@media (max-width:959px){ .rail{display:none} }
@media (max-width:959px),(max-height:719px){
  .huge{font-size:min(18.2vw,15vh)}
  .huge .strip.s1{margin-left:.2em;max-width:calc(100% - .2em)}
}
@media (max-width:520px){
  .big{font-size:clamp(40px,12.4vw,52px)}
  .go{width:44px;padding:0}.go span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
  .mark{font-size:17px}
  .pill{font-size:17px;padding:0 14px}
}
/* The raw preference still calms the page without JavaScript; an explicit opt-in (.motion-on) overrides it. */
@media (prefers-reduced-motion:reduce){
  html:not(.motion-on){scroll-behavior:auto}
  html:not(.motion-on) *,html:not(.motion-on) *::before,html:not(.motion-on) *::after{animation:none!important;transition:none!important}
  .js:not(.motion-on) .strip,.js:not(.motion-on) .strip>span{clip-path:none!important;transform:none!important}
  .js:not(.motion-on) .card,.js:not(.motion-on) .sheet,.js:not(.motion-on) .lead{opacity:1!important;translate:none!important}
}

/* S2: explicit scene layout; the full phone composition follows in S6. */
.story-stage{--acc:#14122b;--on:#fbf4e6;padding:0}
.story-stage.usine{min-height:260svh}
.story-stage .stage{position:sticky;top:0;min-height:100svh;padding:72px 16px 88px;display:flex;flex-direction:column;justify-content:space-between;gap:20px}
.story-stage .big{margin:0}
.story-stage .card{margin:0}
/* Section heights live only in the three layout blocks below (desktop, phone, short windows), so source order cannot hide them. */
.experience-entry{margin:2.5em 0}
.experience-entry p{margin:.8em 0}
.nogl .usine .card{opacity:1;translate:none}
@media(min-width:960px){
  .station.usine{min-height:320vh}
  .finale{min-height:200vh}
}

/* S6: phone recomposition. Strips under the header, world in the middle, short card above the dock.
   The pinned layout needs a tall enough viewport (PIN_PHONE / PIN_DESK in story.mjs, kept in step by a test).
   Shorter windows, such as a phone turned sideways, flow normally and stay opaque. */
@media (max-width:959px){
  .dock{transition:opacity .25s,visibility .25s}
  /* Reading and Contact: only the next arrow goes. Pause and the motion button stay reachable because ambient motion keeps running there. */
  #next{transition:opacity .25s,visibility .25s}
  .reading #next,.endcap #next{opacity:0;visibility:hidden}
  .finale .stage{margin-right:52px;max-width:calc(100% - 52px)}
  .finale .foot{margin-right:52px}
  .reading .top{background:linear-gradient(#14122bf0 62%,#14122b00)}
  .dossier{padding-top:84px;padding-bottom:30svh}
}
@media (max-width:959px) and (min-height:600px){
  .station{padding:0}
  .station:not(.story-stage){min-height:170svh}
  .station.st5:not(.story-stage){min-height:220svh}
  .story-stage{min-height:190svh}
  .story-stage.ia{min-height:230svh}
  .story-stage.ingenieur{min-height:340svh}
  .story-stage.usine{min-height:260svh}
  .station:not(.usine) .stage{position:sticky;top:0;height:100svh;min-height:0;padding:calc(78px + env(safe-area-inset-top,0px)) max(16px,env(safe-area-inset-right,0px)) calc(84px + env(safe-area-inset-bottom,0px)) max(16px,env(safe-area-inset-left,0px));display:flex;flex-direction:column;justify-content:space-between;gap:12px}
  .station:not(.usine) .big{margin:0;font-size:clamp(40px,12.4vw,52px)}
  .station:not(.usine) .strip>span{text-wrap:balance}
  .station:not(.usine) .card{margin:0;max-width:none;padding:14px 16px 16px;font-size:15px;line-height:1.45}
  .station:not(.usine) .card .does{font-size:16.5px;line-height:1.4}
  .station:not(.usine) .tag{font-size:17px}
  .story-stage .card p+p{margin-top:.4em}
  .story-stage.ia .card{padding:11px 14px 13px;font-size:13.5px;line-height:1.34}
  .story-stage.ia .card p+p{margin-top:.2em}
  .usine .big{opacity:var(--strips,1)}
}
@media (max-width:959px) and (max-height:599px),(min-width:960px) and (max-height:719px){
  .station{padding:0}
  .station:not(.usine),.story-stage:not(.usine){min-height:100svh}
  .station:not(.usine) .stage{position:static;height:auto;min-height:0;padding:calc(78px + env(safe-area-inset-top,0px)) max(16px,env(safe-area-inset-right,0px)) 84px max(16px,env(safe-area-inset-left,0px));display:flex;flex-direction:column;justify-content:flex-start;gap:16px;opacity:1}
  .station:not(.usine) .big{margin:0}
  .station:not(.usine) .card{margin:0}
}

/* Pinned stages fade as they slide off or in, so strips never sit half hidden under the top bar. */
@media (max-width:959px) and (min-height:600px),(min-width:960px) and (min-height:720px){
  .hero .stage,.station:not(.usine) .stage{opacity:calc(1 - var(--fade,0))}
}

/* S7A: shared flat rendering and the poster slot filled by part B. */
.nogl #panes{display:block}
#posters{display:none;position:fixed;inset:0;overflow:hidden;pointer-events:none}
#posters div{position:absolute;inset:0;opacity:0;transition:opacity .35s}
#posters svg{position:absolute;left:50%;bottom:0;translate:-50% 0;width:max(100vw,min(160vh,1100px));height:auto;aspect-ratio:1440/900}
/* Portrait: show the engineer's whole herd (x 240..1200 of 1440) and lift it clear of the card. */
@media (max-aspect-ratio:1/1){#posters [data-p=ingenieur] svg{width:150vw;bottom:30svh}}
[data-poster=finance] #posters [data-p=finance],[data-poster=terminal] #posters [data-p=terminal],[data-poster=ia] #posters [data-p=ia],[data-poster=ingenieur] #posters [data-p=ingenieur]{opacity:1}
.nogl #posters{display:block}
.nogl body{transition:none}
.calm{scroll-behavior:auto}
.calm *, .calm *::before, .calm *::after{animation:none!important;transition:none!important}
.calm .hero .stage,.calm .station:not(.usine) .stage{opacity:1}
.calm .usine .big,.calm .story-stage .big{opacity:1}
/* Film pages: card lines show as the film reaches them. Only under .acts (set by script) on a page that has a painter, so print and no-JS show everything. */
.acts .film .ln{opacity:0;transition:opacity .25s}
.acts .film .ln.on{opacity:1}
.calm .film .ln{opacity:1!important}
/* The card box itself waits for the first line, so an empty paper box never shows (film pages only, set by script). */
.acts .film.cardhold .card{opacity:0;pointer-events:none}
.calm .film .card{opacity:1!important}
.story-stage.ia .big,.story-stage.ingenieur .big{opacity:var(--strips,1)}
/* Motion pass: the reduced-motion opt-in, and drifting posters on the flat path. */
#motion{display:none}
.calm #motion{display:inline-flex}
.paused *,.paused *::before,.paused *::after{animation-play-state:paused!important}
@keyframes pdrift{0%{transform:translate3d(-1.2%,0,0) scale(1)}100%{transform:translate3d(1.2%,-.8%,0) scale(1.035)}}
@keyframes pbob{0%{transform:translateY(0)}100%{transform:translateY(-9px)}}
@keyframes pbob2{0%{transform:translateY(0)}100%{transform:translateY(7px)}}
.nogl #posters svg{animation:pdrift 9s ease-in-out infinite alternate;transform-origin:50% 100%}
.nogl #posters svg>*{animation:pbob 3.2s ease-in-out infinite alternate}
.nogl #posters svg>*:nth-child(2n){animation-name:pbob2;animation-duration:4.1s}
.nogl #posters svg>*:nth-child(3n){animation-duration:2.6s;animation-delay:-1s}
/* The paper sheets are punched: the holes roll like film so dossier scenes are never still. Stepped, so repaints stay few. */
@keyframes holes{to{-webkit-mask-position:0 44px;mask-position:0 44px}}
.sheet{animation:holes 2.4s steps(11) infinite}

/* Print: the film's hidden lines and headlines always print, whatever the scroll or script state. */
@media print{
  .acts .film .ln{opacity:1!important;transition:none}
  .acts .film.cardhold .card{opacity:1!important}
  .story-stage .big,.story-stage.ia .big,.story-stage.ingenieur .big{opacity:1!important;--strips:1}
  .hero .stage,.station .stage{opacity:1!important}
  .js:not(.static) .card:not(.in),.usine .card{opacity:1!important;translate:none!important;transition:none!important}
  .js:not(.static) .big:not(.in) .strip{clip-path:none!important}
  .js:not(.static) .big:not(.in) .strip>span{transform:none!important}
  #acts,#panes{display:none!important}
}
