/* ROYALE / photographed card, registered fuse and four held impact poses.
   Presentation only. Existing phases and finite turn cues own every trigger. */
html[data-zine-material-gate="true"] #zineRoyaleApp.bomtafel {
  --table-bomb: url("assets/nachtzine/shipping/royale/bomb-body-v1.webp");
}
#zineRoyaleApp.bomtafel .bomb-case {
  background-size: contain; background-repeat: no-repeat; background-position: center;
  filter: drop-shadow(1px 2px 1px #21152970) drop-shadow(5px 9px 4px #21152930);
}
#zineRoyaleApp.bomtafel .royale-bomb { rotate: 14deg; }

/* The raster neck is (81.3%,10.5%). Rotate the engine's original segmented
   fuse around (52%,34%) by 25deg, uniformly scale .90, then translate its
   root onto that neck. The spark uses the SAME matrix, not a guessed path.
   These narrowly scoped !important properties replace the old roster-
   dependent distorted geometry; all groups now use one registered rig. */
#zineRoyaleApp.bomtafel .bomb-wick {
  translate: 29.3% -23.5%;
  transform: rotate(25deg) scale(.90) !important;
  transform-origin: 52% 34% !important;
}
#zineRoyaleApp.bomtafel .bomb-spark {
  margin: 0 !important;
  left: calc(81.3% + (var(--spark-x) - 52%) * .815677008 - (var(--spark-y) - 34%) * .380356436) !important;
  top: calc(10.5% + (var(--spark-x) - 52%) * .380356436 + (var(--spark-y) - 34%) * .815677008) !important;
  width: 18% !important; height: 18% !important;
  filter: drop-shadow(1px 2px 1px #21152960);
}
#zineRoyaleApp.bomtafel[data-phase="running"] .bomb-spark {
  animation: shipping-spark 800ms steps(1,end) infinite;
}
#zineRoyaleApp.bomtafel[data-phase="running"][data-danger="critical"] .bomb-spark { animation-duration: 520ms; }
@keyframes shipping-spark {
  0%,100% { background-image: var(--table-spark-a); rotate: -13deg; scale: .85; }
  33% { background-image: var(--table-spark-b); rotate: 8deg; scale: 1; }
  66% { background-image: var(--table-spark-a); rotate: 22deg; scale: .92; }
}

/* Most of each beat is a held pose. The rig—not an independent neck or
   spark—makes the short paper rattle. No flashing, breathing scale or glow.
   The word sheet is a separate, stationary reading plane throughout play. */
#zineRoyaleApp.bomtafel[data-phase="running"][data-danger="warm"] .royale-bomb {
  --shipping-rattle-x: 2px; --shipping-rattle-angle: 1deg;
  animation: shipping-rattle 1800ms steps(1,end) infinite;
}
#zineRoyaleApp.bomtafel[data-phase="running"][data-danger="hot"] .royale-bomb {
  --shipping-rattle-x: 4px; --shipping-rattle-angle: 2deg;
  animation: shipping-rattle 1100ms steps(1,end) infinite;
}
#zineRoyaleApp.bomtafel[data-phase="running"][data-danger="critical"] .royale-bomb {
  --shipping-rattle-x: 6px; --shipping-rattle-angle: 3deg;
  animation: shipping-rattle 620ms steps(1,end) infinite;
}
@keyframes shipping-rattle {
  0%,60%,100% { transform: none; }
  68% { transform: translate(calc(-1 * var(--shipping-rattle-x)), -2px) rotate(calc(-1 * var(--shipping-rattle-angle))); }
  81% { transform: translate(var(--shipping-rattle-x), 1px) rotate(var(--shipping-rattle-angle)); }
  93% { transform: translate(0, 1px) rotate(-.5deg); }
}

/* The incoming player receives one confidently placed paper ticket.
   No perpetual active-name wobble. Text/hearts/material stay one object. */
#zineRoyaleApp.bomtafel[data-phase="running"][data-turn-event="none"] .royale-score[data-active="true"] { animation: none; }
#zineRoyaleApp.bomtafel[data-phase="running"][data-turn-event="handoff"][data-turn-take="a"] .royale-score[data-active="true"] { animation: shipping-receive-a 390ms steps(1,end) both; }
#zineRoyaleApp.bomtafel[data-phase="running"][data-turn-event="handoff"][data-turn-take="b"] .royale-score[data-active="true"] { animation: shipping-receive-b 390ms steps(1,end) both; }
@keyframes shipping-receive-a {
  0% { transform: translateY(-9px) rotate(calc(var(--table-card-rest-angle) - 2deg)); }
  30% { transform: translateY(3px) rotate(calc(var(--table-card-rest-angle) + 1deg)); }
  60% { transform: translateY(-1px) rotate(calc(var(--table-card-rest-angle) - .5deg)); }
  100% { transform: rotate(var(--table-card-rest-angle)); }
}
@keyframes shipping-receive-b {
  0% { transform: translateY(-9px) rotate(calc(var(--table-card-rest-angle) + 2deg)); }
  30% { transform: translateY(3px) rotate(calc(var(--table-card-rest-angle) - 1deg)); }
  60% { transform: translateY(-1px) rotate(calc(var(--table-card-rest-angle) + .5deg)); }
  100% { transform: rotate(var(--table-card-rest-angle)); }
}

/* Actual cut paper replaces the scaling CSS star: compact impact, full
   burst, separated scraps, then empty space for the existing loss sheet.
   All four poses are held, never interpolated across neighbouring cells. */
#zineRoyaleApp.bomtafel .royale-bomb .bomb-burst {
  inset: 0; background-image: url("assets/nachtzine/shipping/royale/burst-atlas-v2.webp");
  background-size: 200% 200%; background-position: 0 0; background-repeat: no-repeat;
  clip-path: none; filter: drop-shadow(2px 3px 1px #21152945);
}
#zineRoyaleApp.bomtafel[data-phase="exploding"] .bomb-burst {
  animation: shipping-impact 960ms steps(1,end) both;
}
@keyframes shipping-impact {
  0% { background-position: 0 0; opacity: 1; transform: none; }
  12% { background-position: 100% 0; opacity: 1; transform: none; }
  30% { background-position: 0 100%; opacity: 1; transform: none; }
  58% { background-position: 100% 100%; opacity: 1; transform: none; }
  100% { background-position: 100% 100%; opacity: 0; transform: none; }
}
#zineRoyaleApp.bomtafel[data-phase="matchEnd"] .royale-result::before {
  background: url("assets/nachtzine/shipping/royale/crown-v1.webp") center / contain no-repeat;
  clip-path: none; filter: drop-shadow(1px 2px 1px #2115296e) drop-shadow(3px 5px 2px #21152930);
}

/* A failed material gate keeps the earlier complete paper objects. Never
   leave an empty bomb or run atlas positions against a one-frame fallback. */
html[data-zine-material-gate="true"] #zineRoyaleApp.bomtafel[data-material-state="fallback"] {
  --table-bomb: url("assets/nachtzine/visual-finish/bomb-flat-v2-delivery.webp");
}
#zineRoyaleApp.bomtafel[data-material-state="fallback"] .royale-bomb .bomb-burst {
  background: var(--table-spark-b) center / contain no-repeat;
}
#zineRoyaleApp.bomtafel[data-material-state="fallback"][data-phase="exploding"] .bomb-burst { animation: show-burst 640ms steps(1,end) both; }
#zineRoyaleApp.bomtafel[data-material-state="fallback"][data-phase="matchEnd"] .royale-result::before {
  background: var(--action) var(--stock) 0 0 / 135px;
  clip-path: polygon(0 4%,25% 43%,49% 0,76% 43%,100% 4%,87% 100%,13% 96%);
}

/* Hidden/inert game roots do not keep decorative loops. Native phase
   changes still work immediately, and reduced motion shows outcomes. */
#zineRoyaleApp.bomtafel:is([hidden], [inert]) :is(.royale-bomb,.bomb-spark,.bomb-burst,.royale-score) { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  #zineRoyaleApp.bomtafel :is(.royale-bomb,.bomb-spark,.bomb-burst,.royale-score) { animation: none !important; }
  #zineRoyaleApp.bomtafel[data-phase="exploding"] .bomb-burst { background-position: 100% 100%; opacity: 1; transform: none; }
}
@media (forced-colors: active) {
  #zineRoyaleApp.bomtafel .bomb-case { filter: none; }
  #zineRoyaleApp.bomtafel .bomb-burst { filter: none; }
  #zineRoyaleApp.bomtafel[data-phase="matchEnd"] .royale-result::before { background-color: transparent; filter: none; }
}
