/* ============================================================
   THE MACHINE'S MOTION — the approved spec (board 2t), and nothing else.

   Motion is reserved for the three moments the machine acts in the real
   world. Every other transition in this app is silent and immediate.

     1 · slot guidance  — a teal breath around the mouth, 900ms ease-in-out,
                          chevrons stepping toward it. Runs until the verdict.
     2 · dispense       — the bank pops out, a teal burst rings outward.
     3 · the sad ends   — the machine goes QUIET AND GREY. Never red.
   ============================================================ */

.machine{
  direction:ltr;                 /* 🔴 a photograph of a real object: never mirrored */
  display:flex;align-items:center;justify-content:center;
  padding-block:4px;
}
.machine svg{width:min(270px,78%);height:auto;display:block}

/* only the cast shadow follows the theme; the device does not */
.dk-ground{fill:rgba(0,0,0,.5)}
:root[data-theme="light"] .dk-ground{fill:rgba(31,36,38,.22)}
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]) .dk-ground{fill:rgba(31,36,38,.22)}
}

/* --- send: the command travels, the screen glints ------------- */
.dk-signal path{stroke:#F3C63A;stroke-width:3;fill:none;stroke-linecap:round;opacity:0}
.machine[data-phase="send"] .dk-signal path{animation:dkSig 1.5s infinite}
.machine[data-phase="send"] .dk-signal path:nth-child(2){animation-delay:.22s}
.machine[data-phase="send"] .dk-signal path:nth-child(3){animation-delay:.44s}
@keyframes dkSig{
  0%{opacity:0;transform:translateY(10px)}
  35%{opacity:.95;transform:translateY(0)}
  70%{opacity:0;transform:translateY(-10px)}
  100%{opacity:0}
}
.dk-glint{opacity:0;transform:translateX(-80px) rotate(14deg)}
.machine[data-phase="send"] .dk-glint{animation:dkGlint 1.5s infinite}
@keyframes dkGlint{
  0%{opacity:0;transform:translateX(-80px) rotate(14deg)}
  38%{opacity:.6}
  62%{opacity:0;transform:translateX(130px) rotate(14deg)}
  100%{opacity:0}
}

/* --- wait: the station is alive and thinking ------------------ */
.dk-statusled{fill:#09CCB0}
.machine[data-phase="wait"] .dk-statusled{animation:dkBlink 1.5s infinite}
@keyframes dkBlink{0%,100%{opacity:1}50%{opacity:.25}}
.machine[data-phase="wait"] .dk-screenglow{animation:dkBreath 2.6s infinite ease-in-out}
@keyframes dkBreath{0%,100%{opacity:0}50%{opacity:.28}}

/* --- check: the verify sweep ---------------------------------- */
.dk-scan{opacity:0}
.machine[data-phase="check"] .dk-scan{animation:dkScan 1.15s infinite cubic-bezier(.45,.05,.55,.95)}
@keyframes dkScan{
  0%{opacity:0;transform:translateY(-4px)}
  12%{opacity:.9}
  88%{opacity:.9}
  100%{opacity:0;transform:translateY(215px)}
}

/* --- watch: dim the rest, spotlight the one -------------------
   Dimming the whole slot would fade its BLACK mouth toward the yellow
   body behind it and the machine would sprout yellow blobs. Only the
   battery face recedes; the mouths stay as dark as they really are. */
.dk-bank,.dk-slot{transition:opacity .4s}
.machine[data-phase="watch"] .dk-slot:not(.is-target) .dk-bank,
.machine[data-phase="success"] .dk-slot:not(.is-target) .dk-bank{opacity:.4}
.dk-halo{stroke:#09CCB0;stroke-width:3.5;fill:none;opacity:0;
  transform-box:fill-box;transform-origin:center;
  filter:drop-shadow(0 0 7px rgba(9,204,176,.85))}
.machine[data-phase="watch"] .is-target .dk-halo{animation:dkHalo .9s infinite ease-in-out}
@keyframes dkHalo{
  0%,100%{opacity:.35;transform:scale(1)}
  50%{opacity:1;transform:scale(1.06)}
}
.machine[data-phase="watch"] .is-target .dk-led{fill:#FFFFFF;filter:drop-shadow(0 0 5px rgba(255,255,255,.95))}
.dk-chev path{stroke:#09CCB0;stroke-width:4;fill:none;stroke-linecap:round;stroke-linejoin:round;opacity:0}
.machine[data-phase="watch"] .is-target .dk-chev path{animation:dkChev 1.1s infinite}
.machine[data-phase="watch"] .is-target .dk-chev path:nth-child(2){animation-delay:.18s}
.machine[data-phase="watch"] .is-target .dk-chev path:nth-child(3){animation-delay:.36s}
@keyframes dkChev{
  0%{opacity:0;transform:translateY(-7px)}
  40%{opacity:1}
  100%{opacity:0;transform:translateY(5px)}
}
/* no slot number to give ⇒ invent none: the whole grid breathes */
.machine[data-slot-unknown] .dk-grid{animation:dkGrid 1.8s infinite ease-in-out;
  transform-box:fill-box;transform-origin:center}
.machine[data-slot-unknown] .dk-slot .dk-bank{opacity:1!important}
@keyframes dkGrid{0%,100%{opacity:.7}50%{opacity:1}}

/* --- success: it comes out -------------------------------------- */
.dk-bank{transform-box:fill-box;transform-origin:center;
  transition:transform .5s cubic-bezier(.2,1.5,.4,1)}
.machine[data-phase="success"] .is-target .dk-bank{transform:translateY(15px) scale(1.18)}
.machine[data-phase="success"] .is-target .dk-led{fill:#FFFFFF}
.dk-burst{stroke:#09CCB0;fill:none;opacity:0;transform-box:fill-box;transform-origin:center}
.machine[data-phase="success"] .is-target .dk-burst{animation:dkBurst .9s ease-out forwards}
@keyframes dkBurst{
  0%{opacity:.95;stroke-width:4;transform:scale(.5)}
  100%{opacity:0;stroke-width:1;transform:scale(2.1)}
}
.machine[data-phase="success"] .is-target .dk-halo{opacity:.9}

/* --- the two sad endings: quiet and grey, NEVER red -------------- */
.dk-machine{transition:filter .7s}
.machine[data-phase="fail"] .dk-machine,
.machine[data-phase="limbo"] .dk-machine{filter:grayscale(.92) opacity(.78)}

/* --- reduced motion: hold the state, drop the pulse -------------- */
@media (prefers-reduced-motion:reduce){
  .machine *{animation:none!important;transition:none!important}
  .machine[data-phase="watch"] .is-target .dk-halo{opacity:1;transform:none}
  .machine[data-phase="watch"] .is-target .dk-chev path{opacity:1;transform:none}
  .machine[data-phase="send"] .dk-signal path{opacity:.9}
}
