/* c210 — in keeping with the book: warm gouache, not a black terminal.
   Palette lifted off the plates; Georgia to read, a typewriter face for the
   signal, which is what build_mission.py sets the facsimile in.

   ⚠ IT HAS TO FIT EVERY SCREEN A CHILD MIGHT HAVE — iPhone, iPad, Samsung,
   laptop, desktop. So nothing is a fixed width that could overflow: the six
   wheels SHARE the plate's width (flex:1 1 0; min-width:0), type and spacing
   scale with clamp(), 100dvh not 100vh because mobile chrome moves, touch
   targets are 44px+, and overflow-x is pinned shut as a backstop.

   ⚠ AND IT IS FOR A NINE YEAR OLD, so it moves. Every beat is animated, and
   every animation is switched off under prefers-reduced-motion at the foot. */
:root{
  --paper:#e7dcc4; --paper-deep:#d6c7a7;
  --ink:#2d2a26; --red:#9e2b22; --brick:#8c4a32;
  --brass:#b8912f; --brass-hi:#efd98a; --brass-lo:#6d5415;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; overflow-x:hidden; background:#1f1b16; color:var(--ink);
  font:clamp(15px,1rem + .25vw,18px)/1.65 Georgia,"Times New Roman",serif;
}

/* ================= 0 & 1: the park, and the drop ================= */
.stage{position:relative; height:100dvh; overflow:hidden; transition:height .9s ease}
.park{position:absolute; inset:0}
.park-img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform:scale(1); transition:transform 1.5s cubic-bezier(.4,0,.2,1), filter 1.5s;
}
/* "walking over to it": the park comes at you and softens, the case grows */
.found .park-img{transform:scale(1.5); filter:saturate(.92) brightness(.82) blur(2px)}

.case-hit{
  position:absolute; left:var(--x,50%); top:var(--y,32%);
  transform:translate(-50%,-50%) scale(var(--s,.115));
  transform-origin:50% 50%;
  background:none; border:0; padding:0; cursor:pointer; line-height:0;
  -webkit-tap-highlight-color:transparent;
  transition:left 1.5s cubic-bezier(.4,0,.2,1), top 1.5s cubic-bezier(.4,0,.2,1),
             transform 1.5s cubic-bezier(.4,0,.2,1);
}
/* the art is supplied full size and shrunk, so growing it only un-shrinks:
   no soft pixels when it fills the width */
.case-img{width:min(88vw,760px); height:auto; display:block;
  filter:drop-shadow(0 8px 18px rgba(0,0,0,.45))}

/* a generous target: a nine year old is tapping a thing in a tree */
.case-hit::after{content:""; position:absolute; inset:-60% -60%; border-radius:50%}
.case-hit:focus-visible{outline:3px solid #efd98a; outline-offset:14px; border-radius:8px}

.dropping .case-hit{animation:fall 5.2s cubic-bezier(.33,.1,.5,1) forwards}
@keyframes fall{
  0%  {top:-18%; transform:translate(-50%,-50%) scale(.115) rotate(-3deg)}
  25% {transform:translate(-50%,-50%) scale(.115) rotate(3.5deg)}
  50% {transform:translate(-50%,-50%) scale(.115) rotate(-3deg)}
  75% {transform:translate(-50%,-50%) scale(.115) rotate(2deg)}
  92% {top:var(--y,32%); transform:translate(-50%,-50%) scale(.115) rotate(-1deg)}
  100%{top:var(--y,32%); transform:translate(-50%,-50%) scale(.115) rotate(0)}
}
/* the hunt, made forgiving */
.glow .case-img{animation:glow 1.9s ease-in-out infinite}
.glow-2 .case-img{animation-duration:1.1s}
@keyframes glow{
  0%,100%{filter:drop-shadow(0 8px 18px rgba(0,0,0,.45))}
  50%    {filter:drop-shadow(0 0 22px rgba(239,217,138,.95)) drop-shadow(0 8px 18px rgba(0,0,0,.45))}
}
.found .case-hit{left:50%; top:50%; --s:1; animation:none}
.arrived .stage, body:has(.arrived) .stage{height:54dvh}
.stage.arrived{height:54dvh}

.hud{
  position:absolute; left:0; right:0; bottom:0; padding:18px clamp(12px,4vw,28px) clamp(16px,4vh,30px);
  text-align:center; color:#efe4cb; pointer-events:none;
  background:linear-gradient(transparent,rgba(20,16,12,.82));
  transition:opacity .8s;
}
.arrived .hud{opacity:0}
.hud .ms{margin:0 0 .3em; color:#e8928a; font-family:"Courier New",monospace;
  font-weight:700; letter-spacing:clamp(.18em,1.2vw,.42em); font-size:clamp(13px,3.6vw,17px)}
.hud .hint{margin:0; font-size:clamp(14px,3.8vw,18px); font-style:italic;
  text-shadow:0 1px 4px rgba(0,0,0,.8)}

/* ================= 3: the lock ================= */
.sheet{
  max-width:720px; margin:clamp(14px,4vh,54px) auto;
  padding:clamp(18px,4.5vw,38px) clamp(14px,4vw,34px) clamp(16px,3vw,26px);
  background:var(--paper); border-radius:2px;
  box-shadow:0 2px 0 rgba(0,0,0,.06) inset, 0 18px 50px rgba(0,0,0,.55);
  opacity:0; transform:translateY(26px); transition:opacity .8s ease, transform .8s ease;
}
.sheet.in{opacity:1; transform:none}

.signal{text-align:center; font-family:"Courier New",Courier,monospace}
.signal .ms{margin:0; color:var(--red); font-weight:700;
  letter-spacing:clamp(.18em,1.2vw,.42em); font-size:clamp(15px,4.4vw,19px)}
.signal hr{border:0; border-top:2px solid var(--ink); margin:6px 0 2px}
.signal .addr{margin:.4em 0 0; font-size:clamp(11px,3vw,13px); letter-spacing:.08em}

h1{font-size:clamp(21px,5.6vw,28px); text-align:center; margin:1.2em 0 .2em; font-weight:400}
h2{font-size:clamp(14px,3.6vw,17px); letter-spacing:.14em; text-transform:uppercase;
   font-family:"Courier New",Courier,monospace; color:var(--brick);
   border-bottom:1px solid var(--paper-deep); padding-bottom:4px; margin:2em 0 .5em}
.lede{text-align:center; font-style:italic; color:#6a6256}
.instruct{text-align:center; max-width:30em; margin:1.4em auto}

.lock{margin:1.6em 0 .4em; text-align:center}
.plate{
  display:flex; gap:clamp(3px,1.4vw,10px);
  width:100%; max-width:380px; margin:0 auto;
  padding:clamp(9px,2.6vw,16px) clamp(8px,2.4vw,18px) clamp(6px,1.8vw,10px);
  background:linear-gradient(#8e8577,#6f6759 60%,#5b5447); border-radius:4px;
  box-shadow:inset 0 2px 5px rgba(0,0,0,.55), 0 2px 0 rgba(255,255,255,.12);
}
.plate.refuse{animation:refuse .5s}
@keyframes refuse{
  0%,100%{transform:translateX(0)} 15%{transform:translateX(-7px)}
  35%{transform:translateX(6px)} 55%{transform:translateX(-4px)} 75%{transform:translateX(3px)}
}
/* THE FIT: each wheel takes an equal share of whatever width there is */
.dial{flex:1 1 0; min-width:0; display:flex; flex-direction:column; align-items:stretch; gap:3px}
.drum{
  width:100%; height:clamp(44px,13vw,60px);   /* 44px floor = a finger */
  display:grid; place-items:center; overflow:hidden;
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.20) 0 1px, rgba(255,255,255,.10) 1px 3px),
    linear-gradient(var(--brass-hi), var(--brass) 42%, var(--brass-lo));
  border-radius:3px; cursor:ns-resize; touch-action:none;
  box-shadow:inset 0 3px 6px rgba(255,255,255,.45), inset 0 -5px 9px rgba(0,0,0,.5),
             0 1px 2px rgba(0,0,0,.4);
}
.drum:focus-visible{outline:2px solid var(--red); outline-offset:2px}
.digit{font:700 clamp(20px,6.4vw,30px)/1 Georgia,serif; color:#2a2109;
  text-shadow:0 1px 0 rgba(255,255,255,.4); display:block}
.drum.turn-up .digit{animation:tup .14s ease-out}
.drum.turn-down .digit{animation:tdn .14s ease-out}
@keyframes tup{from{transform:translateY(60%); opacity:.2} to{transform:none; opacity:1}}
@keyframes tdn{from{transform:translateY(-60%); opacity:.2} to{transform:none; opacity:1}}

.nudge{
  width:100%; height:clamp(26px,7vw,30px); border:0; cursor:pointer; color:#efe4cb;
  background:linear-gradient(#5f5849,#423d33); border-radius:2px;
  font-size:clamp(9px,2.4vw,11px); line-height:1; padding:0;
  -webkit-tap-highlight-color:transparent;
}
.nudge:hover{background:linear-gradient(#6f6757,#4b463a)}
.nudge:active{background:#3a352c; transform:translateY(1px)}
.letter{font:italic clamp(10px,2.6vw,12px) Georgia,serif; color:#d8ceb6; opacity:.85; text-align:center}

.lever{
  display:block; margin:clamp(16px,4vw,22px) auto 0;
  padding:clamp(11px,3vw,13px) clamp(26px,9vw,40px); min-height:48px; cursor:pointer;
  font:700 clamp(13px,3.6vw,15px)/1 "Courier New",monospace;
  letter-spacing:clamp(.18em,1.2vw,.3em); color:#2a2109;
  background:linear-gradient(var(--brass-hi), var(--brass) 45%, var(--brass-lo));
  border:0; border-radius:3px;
  box-shadow:inset 0 2px 4px rgba(255,255,255,.5), 0 4px 0 #4a3a0e, 0 6px 12px rgba(0,0,0,.45);
}
.lever:active{transform:translateY(3px); box-shadow:inset 0 2px 4px rgba(255,255,255,.4), 0 1px 0 #4a3a0e}
.lever:disabled{opacity:.6; cursor:wait}
.shut{margin:1.4em auto 0; max-width:30em; text-align:center; color:var(--red); font-style:italic; min-height:1.4em}

.contents{opacity:0; transform:translateY(14px); transition:opacity .9s ease, transform .9s ease}
.contents.in{opacity:1; transform:none}
.contents section{margin-bottom:1.4em}
.todo{font-family:"Courier New",monospace; font-size:clamp(11px,3vw,13px); letter-spacing:.18em;
  color:#8a8172; border:1px dashed var(--paper-deep); padding:14px; text-align:center}

.footnote{text-align:center; margin-top:2.4em}
.relock{
  font:italic clamp(13px,3.4vw,15px) Georgia,serif; color:var(--brick);
  background:none; border:1px solid var(--paper-deep); border-radius:3px;
  padding:10px 18px; min-height:44px; cursor:pointer;
}
.relock:hover{background:#ddd0b3}
footer{margin-top:2.6em; padding-top:12px; border-top:1px solid var(--paper-deep);
  text-align:center; font-size:clamp(11px,3vw,12.5px); color:#8a8172; font-style:italic}

/* a phone held sideways: wide but very short */
@media (max-height:460px) and (orientation:landscape){
  .stage{height:100dvh} .stage.arrived{height:62dvh}
  .sheet{margin:8px auto} .instruct{margin:.8em auto}
}
@media (min-width:1500px){ .sheet{max-width:780px} }

/* no movement for anyone who has asked for none */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important; transition:none !important}
  .found .park-img{transform:none; filter:none}
}

/* ================= the silk, and hiding it =================
   Norman, 21/10/2026: "Their first job is to hide the parachute, then they can
   open it." So the canopy is its OWN piece of artwork, above the case, and it
   gathers and goes while the case stays put. */
.rig{display:block; position:relative}
.para{
  display:block; width:100%; height:auto; margin:0 auto -4%;
  transform-origin:50% 90%;
  transition:transform 1s cubic-bezier(.4,0,.2,1), opacity .9s ease;
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.35));
}
/* on the way down it is full and round; landed, it slumps over the branches */
.landed .para{transform:scale(.92) rotate(-4deg) skewX(-3deg)}
/* gathered in: bundled small and tucked against the case */
.gathered .para{transform:translateY(16%) scale(.30) rotate(-14deg)}
/* and pushed under the hedge, bottom left, gone */
.stowed .para{transform:translate(-120%,70%) scale(.16) rotate(-40deg); opacity:0}

/* the hiding place, lit up only when it is wanted */
.park::after{
  content:""; position:absolute; left:6%; bottom:7%;
  width:clamp(70px,18vw,150px); height:clamp(44px,11vw,90px);
  border-radius:50% 50% 42% 42%;
  background:radial-gradient(ellipse at 50% 60%, rgba(239,217,138,.55), rgba(239,217,138,0) 70%);
  opacity:0; transition:opacity .6s; pointer-events:none;
}
.showspot .park::after{opacity:1; animation:spotPulse 1.5s ease-in-out infinite}
@keyframes spotPulse{0%,100%{opacity:.45} 50%{opacity:1}}

.job{text-align:center; margin:1.4em 0 0}

/* ================= the aeroplanes =================
   Norman, 21/10/2026: the Swordfish brings it ("that's the torpedo carrying
   plane and it's unusual to see it over land"), and German Heinkels come over
   if the child dawdles. The Heinkels are PRESSURE, never punishment: nothing is
   lost, nothing ends, and they fade away the moment the silk is hidden. */
.plane{
  position:absolute; height:auto; pointer-events:none; opacity:0;
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.3));
}

/* the Swordfish: low, slow, left to right, and it lets go at mid-screen */
.swordfish{top:16%; width:clamp(150px,30vw,340px)}
.flyby .swordfish{animation:sortie 8.6s linear forwards}
@keyframes sortie{
  0%  {left:-34%; opacity:0; transform:rotate(1.5deg)}
  8%  {opacity:1}
  40% {transform:rotate(-1deg)}
  88% {opacity:1}
  100%{left:108%; opacity:0; transform:rotate(1deg)}
}

/* the Heinkels: high, in a loose vic, right to left and unhurried, which is
   what made them frightening */
.raid{position:absolute; inset:0; pointer-events:none}
.heinkel{width:clamp(74px,15vw,170px); opacity:0}
.h1{top:7%}  .h2{top:12%}  .h3{top:9.5%}
.raiding .heinkel{animation:bombers 17s linear infinite}
.raiding .h2{animation-delay:1.6s}
.raiding .h3{animation-delay:3.1s}
.raiding-hard .heinkel{animation-duration:11s}
@keyframes bombers{
  0%  {left:106%; opacity:0}
  10% {opacity:.85}
  90% {opacity:.85}
  100%{left:-26%; opacity:0}
}
/* the light goes when they are overhead, the way it does under cloud */
.raiding .park-img{filter:saturate(.84) brightness(.9)}
.raiding-hard .park-img{filter:saturate(.72) brightness(.78)}
.raiding .hud .hint{color:#f0c9a4}
.raiding-hard .hud .ms{animation:alarm 1.4s ease-in-out infinite}
@keyframes alarm{0%,100%{opacity:1} 50%{opacity:.45}}
/* walking over to it still wins over any raid tinting */
.found .park-img{transform:scale(1.5); filter:saturate(.92) brightness(.82) blur(2px)}
