/* Royale: dim the set, light the actor. No travelling frame or geometry.
   All levels follow the existing coarse public fuse, never a second clock. */
#zineRoyaleApp { --royale-dim: 0; --royale-key: 0; --royale-actor: 0; --royale-paper-light: 1; --royale-title-light: 1; }
#zineRoyaleApp .royale-light-field,
#zineRoyaleApp .royale-light-pool {
  display: block; position: absolute; inset: 0; pointer-events: none;
  transition: opacity 480ms ease-out;
}
/* Uniform dimming includes the bottom edge and the middle. Only the backdrop
   is under this light: not the words, paper cards, hearts, or controls. */
#zineRoyaleApp .royale-light-field { background: #21121c; opacity: var(--royale-dim); }
#zineRoyaleApp .royale-light-pool {
  /* A warm lamp on the same registered stock, underneath the physical cast.
     Pigment and grain remain visible; no white fog sits over the artwork. */
  background: color-mix(in srgb, var(--field) 62%, #ffe7b3) var(--stock) 0 0 / 640px;
  background-blend-mode: multiply;
  mask: radial-gradient(ellipse 43% 69% at 51% 51%, #000 0%, #000b 36%, transparent 100%);
  opacity: var(--royale-key);
}
/* Reset between bombs while hidden. The director resolves this state before
   reopening the carrier, so old light cannot fade backwards into a new turn. */
#zineRoyaleApp[data-moment-world-state="off"] :is(.royale-light-field,.royale-light-pool) { transition: none; }
#zineRoyaleApp[data-moment-world-fuse="1"] { --royale-dim: .14; --royale-key: .32; --royale-actor: .14; --royale-paper-light: .97; --royale-title-light: .94; }
#zineRoyaleApp[data-moment-world-fuse="2"] { --royale-dim: .25; --royale-key: .48; --royale-actor: .20; --royale-paper-light: .94; --royale-title-light: .87; }
#zineRoyaleApp[data-moment-world-fuse="3"] { --royale-dim: .36; --royale-key: .62; --royale-actor: .24; --royale-paper-light: .91; --royale-title-light: .80; }
#zineRoyaleApp[data-moment-world-fuse="4"] { --royale-dim: .46; --royale-key: .71; --royale-actor: .27; --royale-paper-light: .89; --royale-title-light: .76; }
#zineRoyaleApp[data-moment-world-fuse="5"] { --royale-dim: .55; --royale-key: .78; --royale-actor: .30; --royale-paper-light: .87; --royale-title-light: .72; }
#zineRoyaleApp[data-moment-world-fuse="6"] { --royale-dim: .63; --royale-key: .83; --royale-actor: .32; --royale-paper-light: .85; --royale-title-light: .69; }
#zineRoyaleApp[data-moment-world-fuse="7"] { --royale-dim: .70; --royale-key: .87; --royale-actor: .34; --royale-paper-light: .82; --royale-title-light: .66; }
#zineRoyaleApp[data-moment-world-fuse="8"] { --royale-dim: .76; --royale-key: .90; --royale-actor: .36; --royale-paper-light: .80; --royale-title-light: .64; }
#zineRoyaleApp:is([data-moment-world-fuse="9"],[data-moment-world-fuse="10"]) { --royale-dim: .82; --royale-key: .93; --royale-actor: .38; --royale-paper-light: .78; --royale-title-light: .62; }
/* The director deliberately retains the last fuse while its carrier is off.
   Paper lives outside that carrier: keep the completed house-light value,
   otherwise removing the exit animation reveals the old dimmed pigment. */
#zineRoyaleApp[data-moment-world-state="off"] { --royale-paper-light: 1; --royale-title-light: 1; }
/* Hold the actor's pool through the loss, then raise the house lights. The
   director clears this specific exit at 1970ms, after the 1900ms CSS finish. */
#zineRoyaleApp[data-moment-world-state="exiting"][data-moment-world-exit="impact"] > .moment-world {
  transition: opacity 800ms ease 1100ms;
}
/* Old cached markup cannot resurrect the former frame. New markup contains
   only the two fixed lighting planes. */
#zineRoyaleApp .moment-world :is(.moment-wing,.moment-rim,.moment-cut) { display: none; }

/* Material light on the actual cutout. Keep its photographed fibre, white
   glints and registered fuse: no duplicated glow or filter on reading text. */
#zineRoyaleApp .bomb-case::before {
  content: ""; display: block; position: absolute; inset: 0;
  background: linear-gradient(132deg, #ffe7b3 4%, #ffe7b3b3 25%, #ffe7b340 48%, transparent 65%);
  mask: var(--table-bomb) center / contain no-repeat;
  clip-path: none; mix-blend-mode: screen; pointer-events: none;
  opacity: 0; transition: opacity 480ms ease-out;
}
#zineRoyaleApp[data-moment-active="true"][data-phase="running"] .bomb-case::before {
  opacity: var(--royale-actor);
}
#zineRoyaleApp .bomb-case::after {
  content: ""; display: block; position: absolute; inset: 0; opacity: 0;
  background: #cb1529; mix-blend-mode: screen;
  mask: var(--table-bomb) center / contain no-repeat; pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"]:is([data-moment-world-fuse="9"],[data-moment-world-fuse="10"]) .bomb-case::after {
    animation: royale-red-alert 1100ms steps(1,end) infinite;
  }
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"]:is([data-moment-world-fuse="9"],[data-moment-world-fuse="10"]) .bomb-case::before {
    animation: royale-warning-key 1100ms steps(1,end) infinite;
  }
}
/* One contained red/black beat per 1.1s, never a full-screen flash. It changes
   pigment only; the original fibres and separate paper glints still read. */
@keyframes royale-red-alert { 0%,44%,100% { opacity: 0; } 12% { opacity: .72; } }
/* The red cue replaces the warm actor lamp instead of adding both together
   into salmon. The backdrop pool stays still; original white glints survive. */
@keyframes royale-warning-key { 0%,44%,100% { opacity: var(--royale-actor); } 12% { opacity: .02; } }
@media (prefers-reduced-motion: reduce) {
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"][data-moment-pressure="3"] .bomb-case::after { opacity: .45; }
}
@media (forced-colors: active) { #zineRoyaleApp .bomb-case::after { display: none !important; } }

/* Cut-paper sweat, physically attached to the same rig as the bomb. The little
   asymmetric silhouette is code-native; its pigment/fibre is existing stock.
   No extra external image request, no glossy water or screen-space confetti. */
#zineRoyaleApp .bomb-sweat { display: none; position: absolute; inset: 0; pointer-events: none; z-index: 3; }
#zineRoyaleApp .bomb-sweat i {
  position: absolute; display: block; opacity: 0;
  width: 6%; height: 10%; left: var(--drop-x); top: var(--drop-y);
  rotate: var(--drop-angle); transform-origin: 50% 0;
  filter: drop-shadow(1px 2px .8px #24152e65) drop-shadow(2px 4px 2px #24152e28);
}
#zineRoyaleApp .bomb-sweat i::before {
  content: ""; position: absolute; inset: 0;
  background: #b8e3ca var(--stock) var(--drop-grain, 35% 15%) / 240px;
  background-blend-mode: multiply;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 64'%3E%3Cpath fill='white' d='M17 2 21 0 25 11 27 18 32 28 34 32 38 42 39 49 36 56 31 61 21 64 11 62 5 57 1 49 2 42 5 34 8 30 13 17Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}
/* These anchors meet the photographed dome, not the transparent square rig.
   Two drops are enough: the opposite shoulder belongs to the fuse and spark. */
#zineRoyaleApp .bomb-sweat i:nth-child(1) { --drop-x: 14%; --drop-y: 28%; --drop-angle: -34deg; --drop-lag: 0ms; --drop-side: -1; }
#zineRoyaleApp .bomb-sweat i:nth-child(2) { --drop-x: 30%; --drop-y: 17%; --drop-angle: -20deg; --drop-lag: -2200ms; --drop-side: -1; --drop-grain: 81% 44%; }
@media (prefers-reduced-motion: no-preference) {
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"]:is([data-moment-pressure="2"],[data-moment-pressure="3"]) .bomb-sweat { display: block; }
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"] .bomb-sweat i { animation: royale-paper-sweat 4400ms linear var(--drop-lag) infinite; }
}
@keyframes royale-paper-sweat {
  0%,8% { opacity: 0; translate: 0 -4px; scale: .82; animation-timing-function: steps(1,end); }
  12% { opacity: 1; translate: 0 0; scale: 1; animation-timing-function: steps(1,end); }
  18% { opacity: 1; translate: calc(var(--drop-side) * 2px) 2px; scale: 1; animation-timing-function: steps(1,end); }
  24% { opacity: 1; translate: calc(var(--drop-side) * 7px) 11px; scale: 1; animation-timing-function: steps(1,end); }
  30% { opacity: 1; translate: calc(var(--drop-side) * 13px) 28px; scale: 1; animation-timing-function: ease-in; }
  40%,100% { opacity: 0; translate: calc(var(--drop-side) * 20px) 48px; scale: 1; }
}
#zineRoyaleApp:not([data-moment-active="true"]) .bomb-sweat,
#zineRoyaleApp:not([data-phase="running"]) .bomb-sweat { display: none; }
#zineRoyaleApp:not([data-moment-active="true"]) .bomb-sweat i,
#zineRoyaleApp:not([data-phase="running"]) .bomb-sweat i { animation: none; }
@media (prefers-reduced-motion: reduce) {
  #zineRoyaleApp .moment-world * { transition: none !important; }
  #zineRoyaleApp .moment-world *::before { transition: none !important; }
  #zineRoyaleApp .bomb-sweat { display: none !important; }
}
@media (forced-colors: active) { #zineRoyaleApp .bomb-sweat { display: none !important; } }

/* Actual players, not additional perimeter symbols. These two photographic
   corner clips identify exactly the two survivors in a duel. They travel
   with their card; fixed seats, names and life tracks keep their geometry. */
#zineRoyaleApp .royale-seat-marks { display: none; }
@media (min-width: 901px) and (min-height: 561px) {
  /* Only pigment-bearing paper recedes. Printed names/hearts do not dim;
     current and struck seats keep their full, readable mint stock. */
  #zineRoyaleApp.bomtafel .royale-score::before { transition: filter 480ms ease-out; }
  #zineRoyaleApp.bomtafel[data-moment-active="true"] .royale-score:not([data-active="true"]):not(:has([data-losing="true"]))::before {
    filter: brightness(var(--royale-paper-light));
  }
  #zineRoyaleApp.bomtafel .royale-heading .ink-label::before { transition: filter 480ms ease-out; }
  #zineRoyaleApp.bomtafel[data-moment-active="true"] .royale-heading .ink-label::before {
    filter: brightness(var(--royale-title-light)) var(--wp-shadow-slip, var(--table-shadow-flat));
  }
  #zineRoyaleApp.bomtafel[data-moment-active="true"][data-moment-world-state="exiting"][data-moment-world-exit="impact"] .royale-heading .ink-label::before {
    animation: royale-title-lights-up 800ms ease 1100ms both;
  }
  #zineRoyaleApp.bomtafel[data-moment-active="true"][data-moment-world-state="exiting"][data-moment-world-exit="impact"] .royale-score:not([data-active="true"]):not(:has([data-losing="true"]))::before {
    animation: royale-paper-lights-up 800ms ease 1100ms both;
  }
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"][data-moment-duel="true"] .royale-score[data-eliminated="false"] .royale-seat-marks {
    display: block; position: absolute; inset: 0; z-index: 3;
    pointer-events: none; filter: drop-shadow(1px 2px .8px #35132755);
  }
  #zineRoyaleApp .royale-seat-marks::before,
  #zineRoyaleApp .royale-seat-marks::after {
    content: ""; position: absolute; width: clamp(29px, 18%, 53px); height: 11px;
    background: #955069 var(--stock) 22px 31px / 190px; background-blend-mode: multiply;
    mask: var(--moment-cut-a, var(--table-score)) center / 100% 100% no-repeat;
  }
  #zineRoyaleApp .royale-seat-marks::before { top: 5%; left: -3%; rotate: -39deg; }
  #zineRoyaleApp .royale-seat-marks::after { bottom: 5%; right: -3%; rotate: -39deg; mask-image: var(--moment-cut-b, var(--table-score)); }
  #zineRoyaleApp.bomtafel[data-moment-directed="true"][data-phase="running"] .royale-score[data-active="true"]::after {
    background: var(--table-active-tint);
  }
  #zineRoyaleApp .royale-score .royale-hearts { position: relative; isolation: isolate; }
  #zineRoyaleApp[data-moment-active="true"][data-phase="running"] .royale-score[data-active="true"][data-hearts="1"] .royale-hearts::before {
    content: ""; position: absolute; z-index: -1; left: -6px; top: -5px;
    width: calc((100% - 12px) / 3 + 12px); height: calc(100% + 10px);
    background: #edb165 var(--stock) 74px 31px / 200px; background-blend-mode: multiply;
    mask: var(--table-score) center / 100% 100% no-repeat;
    rotate: -5deg; pointer-events: none;
  }
  /* A single held-pose contact on a real pressure threshold. Never compete
     with the earlier start/handoff owner, and never animate the word sheet. */
  #zineRoyaleApp.bomtafel[data-moment-active="true"][data-phase="running"][data-turn-event="none"][data-moment-event="rise"] .royale-score[data-active="true"] {
    animation: moment-royale-seat-pressure 440ms steps(1, end) both;
  }
  #zineRoyaleApp.bomtafel[data-moment-active="true"][data-phase="exploding"] .royale-score:has([data-losing="true"]) {
    animation: moment-royale-seat-struck 420ms steps(1, end) both;
  }
  #zineRoyaleApp[data-moment-active="true"][data-moment-event="duel"] .royale-seat-marks {
    animation: moment-royale-duel-clips 540ms steps(1, end) both;
  }
}
@keyframes royale-title-lights-up {
  from { filter: brightness(var(--royale-title-light)) var(--wp-shadow-slip, var(--table-shadow-flat)); }
  to { filter: brightness(1) var(--wp-shadow-slip, var(--table-shadow-flat)); }
}
@keyframes royale-paper-lights-up {
  from { filter: brightness(var(--royale-paper-light)); }
  to { filter: brightness(1); }
}
@keyframes moment-royale-seat-pressure {
  0% { transform: rotate(var(--table-card-rest-angle)); }
  20% { transform: translateY(-3px) rotate(calc(var(--table-card-rest-angle) - .65deg)); filter: var(--wp-shadow-lift); }
  43% { transform: translateY(2px) rotate(calc(var(--table-card-rest-angle) + .4deg)); filter: var(--wp-shadow-slip); }
  69%,100% { transform: rotate(var(--table-card-rest-angle)); }
}
@keyframes moment-royale-seat-struck {
  0% { transform: rotate(var(--table-card-rest-angle)); }
  18% { transform: translateY(5px) rotate(calc(var(--table-card-rest-angle) + 1.6deg)); }
  46% { transform: translateY(-1px) rotate(calc(var(--table-card-rest-angle) - .4deg)); }
  70%,100% { transform: rotate(var(--table-card-rest-angle)); }
}
@keyframes moment-royale-duel-clips {
  0% { scale: .94; opacity: 0; }
  31% { scale: 1.04; opacity: 1; }
  63%,100% { scale: 1; opacity: 1; }
}

/* No hidden tab/menu has a second performance. The director is the visible
   lifecycle owner; old phase markers alone cannot restart this scenery. */
#zineRoyaleApp:is([hidden], [inert]) .moment-world,
#zineRoyaleApp:not([data-moment-active="true"]) .moment-world,
#zineRoyaleApp:is([data-phase="setup"], [data-phase="loading"]) .moment-world { display: none; }
#zineRoyaleApp:is([hidden], [inert]) .moment-world *,
#zineRoyaleApp:not([data-moment-active="true"]) .moment-world * { animation: none !important; }
#zineRoyaleApp:not([data-moment-active="true"]) .royale-seat-marks { display: none; }

@media (max-width: 900px), (max-height: 560px) {
  /* Desktop is the lighting reference. Compact keeps its existing bright
     reading field; the registered fuse and contained red actor still warn. */
  #zineRoyaleApp .moment-world { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  #zineRoyaleApp .bomb-case::before { display: none !important; }
  #zineRoyaleApp.bomtafel :is(.royale-score,.royale-heading .ink-label)::before { transition: none !important; }
  #zineRoyaleApp .moment-world * { animation: none !important; translate: none !important; }
  #zineRoyaleApp .royale-seat-marks,
  #zineRoyaleApp .royale-score { animation: none !important; }
}
@media (forced-colors: active) {
  #zineRoyaleApp .bomb-case::before { display: none !important; }
  #zineRoyaleApp.bomtafel :is(.royale-score,.royale-heading .ink-label)::before { filter: none !important; }
  #zineRoyaleApp .moment-world { display: none; }
  html #zineRoyaleApp.bomtafel .bomb-case { filter: none !important; }
  #zineRoyaleApp .royale-seat-marks,
  #zineRoyaleApp .royale-score .royale-hearts::before { display: none !important; }
}
