/* =====================================================================
   jk1x MODE — THE THREE-REEL MACHINE
   ---------------------------------------------------------------------
   Loaded AFTER arcade.css and wheel-fx.css, which makes this the last
   word in the cascade. It has to be: the machine skin below repaints the
   frame, the reels and the plaque, and every one of those is set from an
   earlier sheet.

   Everything here is gated behind body.jk1x-active (set by
   renderJk1xBanner) or [data-cols="3"] (set by createReels), so none of
   it can touch an ordinary machine.
   ===================================================================== */

:root {
  --jk1x-cyan: #22e6ff;
  --jk1x-cyan-soft: #7ff3ff;
  --jk1x-cyan-deep: #067b96;
  --jk1x-ink: #02080c;
}

/* --- THREE REELS, SIZED LIKE THEY MEAN IT -----------------------------
   .reels is flex with .reel-col{flex:1}, so dropping to three columns
   already fills the width — but it fills it by making each reel 5/3
   wider while the symbol inside stays one third of the reel's HEIGHT.
   object-fit: contain then letterboxes it, so the machine reads as three
   over-wide columns of small symbols with air either side.

   Constraining the container by aspect ratio instead lets the cells grow
   to a sensible shape and the symbols grow with them. width:auto is
   required — .reels sets width:100% and a percentage width beats
   aspect-ratio.

   1.3, measured rather than guessed. Against an 856px cabinet at 1440x900:

     ratio    reels width   fills   cell        cell aspect
     1/1        610px        71%    196x199        0.98
     1.15/1     701px        82%    226x199        1.13
     1.3/1      792px        93%    256x199        1.29
     1.45/1     848px        99%    275x199        1.38

   A perfect square leaves a seventh of the cabinet empty either side and
   reads as a five-reel machine with two reels missing. 1.45 fills it but
   the cells go noticeably letterbox, and object-fit:contain then pads
   each symbol with air rather than making it bigger. 1.3 fills all but a
   sliver and keeps the cell close to the shape a slot cell usually is. */
.reels[data-cols="3"] {
  width: auto;
  aspect-ratio: 1.3 / 1;
  max-width: 100%;
  margin-inline: auto;
}
.reels[data-cols="3"] .reel-col { min-width: 0; }
/* The gutter markers are laid out for five columns and mean nothing on
   three, where every reel is adjacent to the next. */
.reels[data-cols="3"] ~ .payline-grid,
body.jk1x-active .payline-grid { display: none; }

@media (max-width: 720px) {
  .reels[data-cols="3"] { aspect-ratio: 1.35 / 1; width: auto; }
}

/* --- THE CABINET: CYAN ON BLACK, LIKE THE LOGO ------------------------ */
body.jk1x-active .machine-frame {
  border-color: var(--jk1x-cyan);
  background:
    radial-gradient(ellipse at 50% 0%, rgba(34, 230, 255, 0.16), transparent 62%),
    linear-gradient(180deg, #04121a 0%, var(--jk1x-ink) 70%);
  box-shadow:
    0 0 0 1px rgba(34, 230, 255, 0.55),
    0 0 34px rgba(34, 230, 255, 0.42),
    0 0 96px rgba(34, 230, 255, 0.20),
    inset 0 0 62px rgba(34, 230, 255, 0.10);
}

/* A cyan sweep that travels the cabinet edge. Sits on the frame's own
   stacking context and never intercepts a click. */
body.jk1x-active .machine-frame::before {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(from 0deg,
    transparent 0deg, var(--jk1x-cyan) 40deg, transparent 120deg,
    transparent 240deg, var(--jk1x-cyan-soft) 300deg, transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: jk1xEdgeSweep 4.5s linear infinite;
  pointer-events: none;
  z-index: 3;
}
@keyframes jk1xEdgeSweep { to { transform: rotate(360deg); } }

body.jk1x-active .reel-col {
  background: linear-gradient(180deg, #03151d, #010609);
  border-color: rgba(34, 230, 255, 0.42);
  box-shadow:
    inset 0 0 22px rgba(34, 230, 255, 0.16),
    0 0 12px rgba(34, 230, 255, 0.18);
}
body.jk1x-active .reel-track img { background-color: #010609; }

/* --- THE PLAQUE CARRIES THE CLOCK -------------------------------------
   The timer used to be a fixed pill at top-centre, directly over the
   energy and coin meters. The plaque is where a machine says its name,
   it is empty while jk1x mode runs (the mode IS the machine), and it is
   the one piece of chrome guaranteed not to collide with anything. */
body.jk1x-active .machine-plaque {
  border-color: var(--jk1x-cyan);
  background: linear-gradient(180deg, rgba(3, 24, 32, 0.96), rgba(1, 8, 12, 0.98));
  box-shadow: 0 0 22px rgba(34, 230, 255, 0.45), inset 0 1px 0 rgba(127, 243, 255, 0.25);
  color: var(--jk1x-cyan);
}
body.jk1x-active #machineTitle {
  color: var(--jk1x-cyan);
  text-shadow: 0 0 12px rgba(34, 230, 255, 0.75);
  letter-spacing: 0.10em;
}
/* The countdown itself, appended after the label. Tabular figures so the
   plaque does not twitch as the seconds tick. */
#machineTitle .jk1x-plaque-clock {
  margin-left: 0.5em;
  font-variant-numeric: tabular-nums;
  color: #fff;
  text-shadow: 0 0 10px rgba(34, 230, 255, 0.9);
}
/* Under a minute it starts to insist. */
#machineTitle .jk1x-plaque-clock.is-low {
  color: #ffe27a;
  animation: jk1xClockPulse 1s ease-in-out infinite;
}
@keyframes jk1xClockPulse { 50% { opacity: 0.45; } }

/* The old fixed banner is gone while the plaque has the clock. Kept in
   the DOM (its markup still carries the logo) rather than deleted, so
   nothing that queries it has to change. */
body.jk1x-active .jk1x-banner { display: none !important; }

/* =====================================================================
   THE TAKEOVER
   ---------------------------------------------------------------------
   Five stacked layers over about 2.6s: a cyan flood, a rolling scan, a
   logo that punches in, a burst of shards, and a wipe that clears to the
   new machine. All of it is pointer-events:none and all of it is removed
   by the JS that built it, so an interrupted transition cannot leave
   anything painted over the reels.
   ===================================================================== */
.jk1x-takeover {
  position: fixed;
  inset: 0;
  z-index: 20400;          /* under the 20500 machine transition */
  pointer-events: none;
  overflow: hidden;
  background: radial-gradient(ellipse at center, rgba(2, 40, 52, 0.86), rgba(0, 0, 0, 0.96));
  opacity: 0;
  animation: jk1xFlood 2.6s ease-out forwards;
}
@keyframes jk1xFlood {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  78%  { opacity: 1; }
  100% { opacity: 0; }
}

/* A horizon line that opens into the full field. */
.jk1x-takeover-scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--jk1x-cyan), transparent);
  box-shadow: 0 0 26px 6px rgba(34, 230, 255, 0.75);
  transform: scaleX(0);
  animation: jk1xScanOpen 2.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes jk1xScanOpen {
  0%   { transform: scaleX(0); opacity: 0; }
  14%  { transform: scaleX(1); opacity: 1; }
  62%  { transform: scaleX(1) scaleY(120); opacity: 0.22; }
  100% { transform: scaleX(1) scaleY(160); opacity: 0; }
}

/* Rolling scanlines, the texture that makes it read as a takeover rather
   than a flash. */
.jk1x-takeover-lines {
  position: absolute;
  inset: -20%;
  background: repeating-linear-gradient(
    0deg, rgba(34, 230, 255, 0.10) 0 2px, transparent 2px 6px);
  animation: jk1xLinesRoll 2.6s linear forwards;
  opacity: 0;
}
@keyframes jk1xLinesRoll {
  10%  { opacity: 0.9; }
  70%  { opacity: 0.5; }
  100% { transform: translateY(120px); opacity: 0; }
}

.jk1x-takeover-logo {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(46vmin, 300px);
  margin: calc(min(46vmin, 300px) / -2) 0 0 calc(min(46vmin, 300px) / -2);
  filter: drop-shadow(0 0 30px rgba(34, 230, 255, 0.95));
  animation: jk1xLogoPunch 2.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes jk1xLogoPunch {
  0%   { transform: scale(2.6) rotate(-8deg); opacity: 0; filter: blur(14px); }
  16%  { transform: scale(1) rotate(0deg);    opacity: 1; filter: blur(0); }
  66%  { transform: scale(1.04);              opacity: 1; }
  100% { transform: scale(0.72);              opacity: 0; }
}

.jk1x-takeover-word {
  position: absolute;
  left: 0;
  right: 0;
  top: 68%;
  text-align: center;
  font-family: 'Orbitron', sans-serif;
  font-size: clamp(1rem, 3.4vw, 1.9rem);
  font-weight: 800;
  letter-spacing: 0.42em;
  text-indent: 0.42em;          /* balances the trailing letter-space */
  color: var(--jk1x-cyan);
  text-shadow: 0 0 22px rgba(34, 230, 255, 0.9);
  opacity: 0;
  animation: jk1xWord 2.6s ease-out forwards;
}
@keyframes jk1xWord {
  0%, 14% { opacity: 0; transform: translateY(14px); }
  28%     { opacity: 1; transform: none; }
  74%     { opacity: 1; }
  100%    { opacity: 0; }
}

/* Shards thrown outward from the centre. Positioned by JS on --a/--d. */
.jk1x-shard {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 3px;
  height: 22px;
  margin: -11px 0 0 -1.5px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--jk1x-cyan-soft), transparent);
  transform: rotate(var(--a)) translateY(0);
  opacity: 0;
  animation: jk1xShard 1.5s cubic-bezier(0.16, 1, 0.3, 1) var(--delay, 0s) forwards;
}
@keyframes jk1xShard {
  0%   { opacity: 0; transform: rotate(var(--a)) translateY(0) scaleY(0.4); }
  22%  { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(var(--d)) scaleY(1.6); }
}

/* While the takeover runs the machine behind it braces. */
body.jk1x-arriving .machine-frame {
  animation: jk1xBrace 2.6s ease-out;
}
@keyframes jk1xBrace {
  0%   { transform: none; }
  14%  { transform: scale(0.965); filter: brightness(2.1) saturate(0.2); }
  30%  { transform: scale(1.012); filter: none; }
  100% { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .jk1x-takeover,
  .jk1x-takeover-scan,
  .jk1x-takeover-lines,
  .jk1x-takeover-logo,
  .jk1x-takeover-word,
  .jk1x-shard,
  body.jk1x-arriving .machine-frame,
  body.jk1x-active .machine-frame::before,
  #machineTitle .jk1x-plaque-clock.is-low {
    animation: none;
  }
  /* Still needs to appear and go away, just without the theatre. */
  .jk1x-takeover { opacity: 1; transition: opacity 0.3s linear; }
  .jk1x-takeover-logo, .jk1x-takeover-word { opacity: 1; }
}

/* --- LEAVING: the same layer, run backwards ---------------------------
   One class instead of a second set of keyframes. The arrival opens out
   from a line and punches the logo in; the exit collapses back to the
   line and pulls the logo away, so the two read as one journey and its
   return rather than as two unrelated effects. */
.jk1x-takeover.is-exit { animation-direction: reverse; }
.jk1x-takeover.is-exit .jk1x-takeover-scan,
.jk1x-takeover.is-exit .jk1x-takeover-logo,
.jk1x-takeover.is-exit .jk1x-takeover-lines,
.jk1x-takeover.is-exit .jk1x-shard { animation-direction: reverse; }
/* The word is the one thing NOT reversed: it names where the player is
   going, so it has to arrive readable rather than un-fade. */
.jk1x-takeover.is-exit .jk1x-takeover-word {
  animation: jk1xWord 2.6s ease-out forwards;
  letter-spacing: 0.22em;
  text-indent: 0.22em;
  color: var(--jk1x-cyan-soft);
}
@media (prefers-reduced-motion: reduce) {
  .jk1x-takeover.is-exit,
  .jk1x-takeover.is-exit .jk1x-takeover-scan,
  .jk1x-takeover.is-exit .jk1x-takeover-logo,
  .jk1x-takeover.is-exit .jk1x-takeover-lines,
  .jk1x-takeover.is-exit .jk1x-shard,
  .jk1x-takeover.is-exit .jk1x-takeover-word { animation: none; }
}

.jk1x-takeover.is-swapping::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: radial-gradient(ellipse at center, rgb(2, 40, 52), rgb(0, 0, 0));
    animation: jk1xSwapVeil 420ms ease-out forwards;
}

@keyframes jk1xSwapVeil {
    0% { opacity: 0; }
    22% { opacity: 1; }
    64% { opacity: 1; }
    100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .jk1x-takeover.is-swapping::before { animation: none; opacity: 1; }
}
