/* Temple edition: a carved stone crocodile head on a stone island in a flooded
   jungle courtyard at dusk. The scene frame and the crocodile use the same
   formulas in the same container (the whole .game-layout), so the head always
   sits in the island. --band-top / --band-bottom are the free band between the
   top bar and the bet panel; temple-character.js measures them, these defaults
   cover the first paint. */
body[data-character="temple"] {
  background: #0b2629;
}
body[data-character="temple"] .game-layout {
  container-type: size;
  background: #0b2629;
  --band-top: 82px;
  --band-bottom: calc(100cqh - 162px);
}
/* The frame formula is declared on the layout's children, not on .game-layout
   itself: there 1cqw / 1cqh are the layout's (a container cannot query
   itself), and every length below is registered (see Registered lengths), so
   each child computes it once in px and its subtree inherits plain px instead
   of re-parsing the whole var() chain on every style change. */
body[data-character="temple"] .game-layout > * {
  /* Readout above the shut head (idle, bite): multiplier size, gap to the head,
     and the room it needs below the top bar (the multiplier, the next-tooth
     pill, the gap and 8 px of air). */
  --readout-size: clamp(46px, min(6vw, 8.5vh), 84px);
  --readout-gap: 10px;
  --readout-room: calc(var(--readout-size) * 0.95 + 58px);
  /* Readout inside the open mouth (playing, won): sizes follow the head. */
  --mouth-value: clamp(26px, calc(var(--croc-w) * 0.082), 60px);
  --mouth-next: clamp(10px, calc(var(--croc-w) * 0.027), 17px);
  --mouth-gap: 4px;
  /* Landscape: temple-lagoon-desktop (1672 x 941) covers the layout. Within the
     allowed range it slides so the island's front waterline clears the panel. */
  --scene-w: max(100cqw, 177.6833cqh);
  --scene-h: max(56.2799cqw, 100cqh);
  --scene-x: calc((100cqw - var(--scene-w)) / 2);
  --scene-y: clamp(
    calc(100cqh - var(--scene-h)),
    calc(var(--band-bottom) - 0.78 * var(--scene-h)),
    0px
  );
  /* The head sits in the island (see Seating): the jaw point, 49.8% / 71.5% of
     the picture, is inside the front slab, below the rim (the front edge of
     the top surface, 67.6% at the centre); the waterline is at 73.5%. The jaw
     sinks at most 9% of the head's width below the rim (the lower sockets end
     10.85% above the jaw), so a small head on a short, wide screen keeps its
     lower teeth clear of the rim. --seat-w is the head the terms below allow
     with the jaw on the rim; the real head is never smaller. */
  --platform-x: calc(var(--scene-x) + 0.498 * var(--scene-w));
  --rim-y: calc(var(--scene-y) + 0.676 * var(--scene-h));
  --water-y: calc(var(--scene-y) + 0.735 * var(--scene-h));
  /* The landscape head is at most --head-cap of the picture wide. Flat and
     Deep also cap it at --head-limit (see below); here it repeats 92cqw. */
  --head-cap: 0.43;
  --head-limit: 92cqw;
  --seat-w: min(
    var(--head-cap) * var(--scene-w),
    calc((var(--rim-y) - var(--band-top) - 16px) / 0.745),
    92cqw,
    calc((var(--rim-y) - var(--band-top) - var(--readout-room)) / 0.5486),
    var(--head-limit)
  );
  /* The last term lifts the head and its island so the island's stone base
     (--isle-drop head widths below the jaw) clears the bet panel by 8 px.
     --isle-base reserves that drop for --seat-w; Flat and Deep solve it for
     the head itself (see below). */
  --isle-base: calc(var(--band-bottom) - var(--isle-drop) * var(--seat-w) - 8px);
  --platform-y: min(
    calc(var(--scene-y) + 0.715 * var(--scene-h)),
    calc(var(--rim-y) + 0.09 * var(--seat-w)),
    var(--isle-base)
  );
  /* Largest head that fits the island (--head-cap of the picture), the width
     and the band below the top bar. The open head rises 73.13% of its frame
     above the jaw (1090 - 173 of 1254); dividing by 0.745 and keeping 16 px
     spare leaves room for the win hop, so the head never reaches the top bar.
     The readout sits inside the open mouth, so it needs no room above the open
     head. The shut head is 229 / 1254 lower (it rises 54.86 %, 1090 - 402),
     which leaves room for the readout above it; the last term only keeps that
     true on short landscape screens (it does not bind at 1024 x 768, 1280 x
     720 or larger desktop sizes). */
  --croc-w: min(
    var(--head-cap) * var(--scene-w),
    calc((var(--platform-y) - var(--band-top) - 16px) / 0.745),
    92cqw,
    calc((var(--platform-y) - var(--band-top) - var(--readout-room)) / 0.5486),
    var(--head-limit)
  );
  /* The island sprite (1774 x 500) is --isle-scale x the head wide and
     centred on the jaw. The jaw sits --isle-sink head widths below the
     sprite row --isle-lip (a fraction of its height): here the back edge of
     temple-island.webp's front lip (21 %), with no sink, so the head stands on
     the island and nothing covers it. --isle-drop is how far the island's
     stone base (its foam line) lies below the jaw, in head widths:
     (foam - lip) x 0.28185 x scale - sink. The Flat and Deep editions set
     their own values below. */
  --isle-sink: 0;
  --isle-drop: 0.24;
  --isle-scale: 1.4;
  --isle-lip: 0.21;
  --isle-w: calc(var(--isle-scale) * var(--croc-w));
  --isle-h: calc(0.28185 * var(--isle-w));
  --isle-x: calc(var(--platform-x) - 0.5 * var(--isle-w));
  --isle-y: calc(var(--platform-y) - var(--isle-sink) * var(--croc-w) - var(--isle-lip) * var(--isle-h));
}
body[data-character="temple"] .game-layout::before {
  background: linear-gradient(180deg, #04131799 0, #04131700 120px);
}
@media (orientation: portrait) {
  /* Portrait: temple-lagoon-phone (941 x 1672) covers the layout and slides so
     the island sits in the band above the bet panel. The head fills about 0.86
     of the picture width, capped by the screen and the band's height. Jaw
     point 50% / 65.5%, rim 62.1%, waterline 67.3%. */
  body[data-character="temple"] .game-layout > * {
    --readout-size: clamp(56px, 7.5vw, 76px);
    --scene-w: max(100cqw, 56.2799cqh);
    --scene-h: max(177.6833cqw, 100cqh);
    --scene-y: clamp(
      calc(100cqh - var(--scene-h)),
      calc(var(--band-bottom) - 0.72 * var(--scene-h)),
      0px
    );
    --platform-x: calc(var(--scene-x) + 0.5 * var(--scene-w));
    --rim-y: calc(var(--scene-y) + 0.621 * var(--scene-h));
    --water-y: calc(var(--scene-y) + 0.673 * var(--scene-h));
    --seat-w: min(
      0.86 * var(--scene-w),
      92cqw,
      calc((var(--rim-y) - var(--band-top) - 16px) / 0.745),
      calc((var(--rim-y) - var(--band-top) - var(--readout-room)) / 0.5486),
      var(--head-limit)
    );
    --platform-y: min(
      calc(var(--scene-y) + 0.655 * var(--scene-h)),
      calc(var(--rim-y) + 0.09 * var(--seat-w)),
      var(--isle-base)
    );
    --croc-w: min(
      0.86 * var(--scene-w),
      92cqw,
      calc((var(--platform-y) - var(--band-top) - 16px) / 0.745),
      calc((var(--platform-y) - var(--band-top) - var(--readout-room)) / 0.5486),
      var(--head-limit)
    );
  }
}
/* Flat and Deep (/temple-flat/, /temple-deep/): the crocodile is the accent,
   so the head is a little larger than on /temple/ and the island keeps
   /temple/'s scale (1.4 x the head wide). The landscape head may take up to
   0.47 of the picture, and never more than 1.12 x the head /temple/ gets on
   the same screen (--standing-w, /temple/'s own formula with its 0.43 cap
   and 0.24 drop, repeated here). Sprite rows are source rows less 300, and
   the drops use the foam line along the stone's base at 83 % (source row 715
   at the centre). Flat: the jaw stands on the paved top at 36 % (source row
   480), 32 source px behind the top's front edge (row 512; back edge row
   322). Deep: the head is wider than the pit and sits down in it: it settles
   until its width at the ring's top (the pit's widest row, source row
   399-400) is the pit's own 1020 px, which puts the jaw 0.6 % of the head
   below the pit's front edge (35.5 %, source row 477.5 at the centre); the
   wider sides above overhang the ring, and .temple-rim draws the pit's front
   arc and the blocks' front faces again over the chin (see Seating).
   The island's base is solved for the head the layout ends up with rather
   than for --seat-w, which this bigger head can outgrow where the jaw sits
   below the scene's rim. The head is never wider than any of its limits
   (92cqw, the win-hop term, the readout term, --head-limit), so the jaw may
   go as low as the lowest of the jaws that solve jaw + drop x that limit =
   the panel's top less 8 px. So the head grows wherever the height allows
   (up to its limit), while the open head keeps its 16 px and the win hop
   under the top bar, the readout fits above the shut head, and the island's
   foam line clears the bet panel by 8 px. */
body[data-isle] .game-layout > * {
  --head-cap: 0.47;
  --isle-scale: 1.4;
  --standing-cap: 0.43;
  --standing-jaw: 0.715;
  --standing-seat-w: min(
    var(--standing-cap) * var(--scene-w),
    calc((var(--rim-y) - var(--band-top) - 16px) / 0.745),
    92cqw,
    calc((var(--rim-y) - var(--band-top) - var(--readout-room)) / 0.5486)
  );
  --standing-y: min(
    calc(var(--scene-y) + var(--standing-jaw) * var(--scene-h)),
    calc(var(--rim-y) + 0.09 * var(--standing-seat-w)),
    calc(var(--band-bottom) - 0.24 * var(--standing-seat-w) - 8px)
  );
  --standing-w: min(
    var(--standing-cap) * var(--scene-w),
    calc((var(--standing-y) - var(--band-top) - 16px) / 0.745),
    92cqw,
    calc((var(--standing-y) - var(--band-top) - var(--readout-room)) / 0.5486)
  );
  --head-limit: calc(1.12 * var(--standing-w));
  --isle-base: max(
    calc(var(--band-bottom) - 8px - var(--isle-drop) * 92cqw),
    calc((var(--band-bottom) - 8px + var(--isle-drop) * (var(--band-top) + 16px) / 0.745) / (1 + var(--isle-drop) / 0.745)),
    calc((var(--band-bottom) - 8px + var(--isle-drop) * (var(--band-top) + var(--readout-room)) / 0.5486) / (1 + var(--isle-drop) / 0.5486)),
    calc(var(--band-bottom) - 8px - var(--isle-drop) * var(--head-limit))
  );
}
body[data-isle="flat"] .game-layout > * {
  --isle-lip: 0.36;
  --isle-sink: 0;
  --isle-drop: 0.186;
}
body[data-isle="deep"] .game-layout > * {
  --isle-lip: 0.355;
  --isle-sink: 0.006;
  --isle-drop: 0.182;
}
/* /temple/'s portrait formula for the limit: 0.86 of the picture and the
   jaw at 65.5 %. */
@media (orientation: portrait) {
  body[data-isle] .game-layout > * {
    --standing-cap: 0.86;
    --standing-jaw: 0.655;
  }
}

/* Registered lengths: the frame formula's results are computed once per
   child of the layout (see above) and inherited as px. */
@property --scene-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --scene-h {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --scene-x {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --scene-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --platform-x {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --rim-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --water-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --seat-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --isle-base {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --platform-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --croc-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --head-limit {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --standing-seat-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --standing-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --standing-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --isle-w {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --isle-h {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --isle-x {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --isle-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --mouth-value {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --mouth-next {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --mouth-gap {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --readout-size {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --readout-gap {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}
@property --readout-room {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

/* ---------- Top bar on the dusk scene ---------- */
body[data-character="temple"] .brand {
  color: #fff3d8;
  filter: drop-shadow(0 2px 3px #041317b0);
}

/* ---------- Scenery ---------- */
body[data-character="temple"] .jungle-background {
  background: #0b2629;
}
.temple-frame {
  position: absolute;
  left: var(--scene-x);
  top: var(--scene-y);
  width: var(--scene-w);
  height: var(--scene-h);
  overflow: hidden;
  /* The island (x 29.4-70.6%, y 61.5-73.4% of the picture) never moves: moving
     water and ripples are masked out over its whole footprint. */
  --island-hole: radial-gradient(
    ellipse 29.6% 9.9% at 49.9% 67.4%,
    transparent 86%,
    #000 100%
  );
}
.temple-picture,
.temple-loop,
.temple-water,
.temple-water-flow,
.temple-glow,
.temple-ripples {
  position: absolute;
  inset: 0;
}
/* The cinemagraph loop (temple-loop.js) plays over the still, frame for frame.
   It fades in from the still once it plays, and hides again if it cannot play. */
.temple-loop {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
  pointer-events: none;
  opacity: 0;
  transition: opacity 600ms ease-out;
}
.loop-shown .temple-loop {
  opacity: 1;
}
.loop-failed .temple-loop {
  visibility: hidden;
}
/* While the loop plays it already moves the water and flickers the lantern.
   Paused on a loop frame, the frame stays in charge too: the still's CSS copies
   would sit over it in slightly different colours. */
.loop-playing .temple-water,
.loop-playing .temple-lantern,
.loop-playing .temple-reflections,
.loop-shown .temple-water,
.loop-shown .temple-lantern,
.loop-shown .temple-reflections {
  display: none;
}
.temple-picture,
.temple-water-flow {
  background: url("/assets/temple-lagoon-clear-desktop.webp") 0 0 / 100% 100%
    no-repeat;
}
/* Only open water moves: the island, the pillar and the ruins stay put. */
.temple-water {
  clip-path: polygon(14.6% 54%, 87% 54%, 87% 63%, 100% 63%, 100% 100%, 0 100%, 0 60%, 14.6% 60%);
  -webkit-mask-image: var(--island-hole), linear-gradient(transparent 54.5%, #000 60%);
  -webkit-mask-composite: source-in;
  mask-image: var(--island-hole), linear-gradient(transparent 54.5%, #000 60%);
  mask-composite: intersect;
}
.temple-ripples {
  -webkit-mask-image: var(--island-hole);
  mask-image: var(--island-hole);
}
.temple-water-flow {
  transform-origin: 50% 53%;
  animation: temple-water 7.5s ease-in-out infinite alternate;
}
.temple-sun {
  background: radial-gradient(circle at 74.5% 31%, #ffe39a80, #ffb55a26 9%, transparent 22%);
  animation: temple-sun 9s ease-in-out infinite alternate;
}
.temple-lantern {
  background: radial-gradient(circle at 4% 34.2%, #ffd27acc, #ff9f4a55 3.2%, transparent 8%);
  mix-blend-mode: screen;
  animation: temple-flicker 3.1s steps(1, end) infinite;
}
/* The lantern's column of light on the water flickers with it. */
.temple-reflections {
  background: radial-gradient(ellipse 2.4% 15% at 4.2% 77%, #ffc0663d, transparent);
  mix-blend-mode: screen;
  animation: temple-shimmer 2.6s ease-in-out infinite alternate;
}
/* Event rings only (two at a bite, one amber ring at a cash-out; see
   Reactions): the loop already moves the water, so nothing rings the island at
   rest. Solid 2 px lines, softened by a slight blur, so they never break into
   dots on the rippled water. */
.temple-ripples span {
  position: absolute;
  left: 25.5%;
  top: 66%;
  width: 48.6%;
  height: 11%;
  border: 2px solid #dafff4;
  border-radius: 50%;
  opacity: 0;
  filter: blur(0.8px);
}
@media (orientation: portrait) {
  body[data-character="temple"] .temple-picture,
  body[data-character="temple"] .temple-water-flow {
    background-image: url("/assets/temple-lagoon-clear-phone.webp");
  }
  /* E3's island spans x 8-92%, y 55.5-67% of the portrait picture. */
  body[data-character="temple"] .temple-frame {
    --island-hole: radial-gradient(
      ellipse 59% 9.3% at 50% 61.3%,
      transparent 86%,
      #000 100%
    );
  }
  body[data-character="temple"] .temple-water {
    clip-path: polygon(0 52%, 100% 52%, 100% 100%, 0 100%);
    -webkit-mask-image: var(--island-hole), linear-gradient(transparent 52%, #000 57%);
    mask-image: var(--island-hole), linear-gradient(transparent 52%, #000 57%);
  }
  body[data-character="temple"] .temple-water-flow {
    transform-origin: 50% 49%;
  }
  body[data-character="temple"] .temple-sun {
    background: radial-gradient(ellipse 30% 14% at 58% 30%, #ffd99a5c, #ffb55a1f 45%, transparent);
  }
  body[data-character="temple"] .temple-lantern {
    background: radial-gradient(circle at 4.5% 31.4%, #ffd27acc, #ff9f4a55 5%, transparent 12%);
  }
  body[data-character="temple"] .temple-reflections {
    background: radial-gradient(ellipse 3.5% 13% at 3.8% 66%, #ffc0663d, transparent);
  }
  body[data-character="temple"] .temple-ripples span {
    left: 4%;
    top: 61.5%;
    width: 92%;
    height: 12%;
  }
}
@keyframes temple-water {
  from { transform: scale(1.012, 1.01) translate3d(-0.3%, 0, 0); }
  to { transform: scale(1.028, 1.022) translate3d(0.3%, 0.45%, 0); }
}
@keyframes temple-sun {
  from { opacity: 0.55; }
  to { opacity: 1; }
}
@keyframes temple-flicker {
  0%, 100% { opacity: 0.85; }
  12% { opacity: 1; }
  27% { opacity: 0.7; }
  41% { opacity: 0.95; }
  58% { opacity: 0.78; }
  74% { opacity: 1; }
  88% { opacity: 0.82; }
}
@keyframes temple-shimmer {
  from { opacity: 0.5; transform: scaleY(0.94); }
  to { opacity: 1; transform: scaleY(1.05); }
}

/* ---------- Fireflies over the far water ---------- */
/* The delivered stills and loops have no fireflies, so the game draws them.
   Soft points of light spread over the whole far-water band (landscape x
   12-88 %, y 46-58 % of the picture; portrait x 10-90 %, y 47-55 %), from the
   far ruins' base to above the island's back edge. The layer is part of the
   scenery, under the crocodile, so the specks behind the head are simply
   hidden by it. It is a size container over the frame, so 1cqw / 1cqh are
   1 % of the picture. Each speck is a warm radial disc with a wide faint halo
   that drifts on its own slow path and fades in and out of step with the
   others, so most are dim at any moment. The scenery pause freezes them;
   reduced motion (styles.css stops every scenery animation) leaves them still
   at 0.3. */
.temple-fireflies {
  position: absolute;
  inset: 0;
  container-type: size;
  pointer-events: none;
  --sway: 1cqw;
}
.temple-fireflies span {
  /* 0.19-0.37 % of the picture width: 3-6 px at 1440 wide, never under 3 px. */
  --size: max(3px, var(--s) * 1cqw);
  position: absolute;
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  background: radial-gradient(circle, #fff3c4 0 15%, #ffd27a 40%, transparent 70%);
  box-shadow: 0 0 10px 3px #ffb54f55;
  filter: blur(0.4px);
  opacity: 0.3;
  animation:
    temple-firefly-drift 12s ease-in-out infinite alternate,
    temple-firefly-pulse 5.5s ease-in-out infinite;
}
/* left / top: place in the picture; --s: size in % of the picture width;
   --x1 --y1, --x2 --y2: the drift's two turning points in % of the picture.
   Landscape: five specks left of the head, four behind it, five to its right;
   every drift stays inside the band. */
.temple-fireflies span:nth-child(1) { left: 13.6%; top: 52.4%; --s: 0.24; --x1: 0.9; --y1: -0.6; --x2: 0.3; --y2: -1; animation-duration: 13s, 6.2s; animation-delay: -2s, -0.4s; }
.temple-fireflies span:nth-child(2) { left: 17.4%; top: 47.6%; --s: 0.3; --x1: -0.8; --y1: 0.7; --x2: 0.6; --y2: 1; animation-duration: 10.5s, 4.8s; animation-delay: -7s, -2.1s; }
.temple-fireflies span:nth-child(3) { left: 20.9%; top: 55.8%; --s: 0.2; --x1: 1.1; --y1: -0.5; --x2: 0.4; --y2: 0.8; animation-duration: 15s, 7.1s; animation-delay: -4s, -5.3s; }
.temple-fireflies span:nth-child(4) { left: 24.6%; top: 50.2%; --s: 0.36; --x1: 0.7; --y1: 1; --x2: -0.9; --y2: 0.5; animation-duration: 12s, 5.4s; animation-delay: -9s, -1.2s; }
.temple-fireflies span:nth-child(5) { left: 27.8%; top: 54.1%; --s: 0.22; --x1: -1; --y1: -0.7; --x2: -0.4; --y2: 0.6; animation-duration: 9.5s, 6.6s; animation-delay: -1s, -3.9s; }
.temple-fireflies span:nth-child(6) { left: 36.2%; top: 48.9%; --s: 0.28; --x1: 0.8; --y1: 0.8; --x2: 1.2; --y2: -0.4; animation-duration: 14s, 4.4s; animation-delay: -11s, -0.9s; }
.temple-fireflies span:nth-child(7) { left: 44.5%; top: 56.2%; --s: 0.2; --x1: 0.6; --y1: 0.9; --x2: 1; --y2: 0.3; animation-duration: 11s, 7.4s; animation-delay: -5s, -6.3s; }
.temple-fireflies span:nth-child(8) { left: 53.7%; top: 51.3%; --s: 0.32; --x1: -0.9; --y1: 0.6; --x2: 0.5; --y2: -0.8; animation-duration: 16s, 5.9s; animation-delay: -13s, -1.8s; }
.temple-fireflies span:nth-child(9) { left: 63.1%; top: 47.4%; --s: 0.24; --x1: 0.7; --y1: -0.3; --x2: -0.5; --y2: 0.6; animation-duration: 12.5s, 6.9s; animation-delay: -3s, -4.2s; }
.temple-fireflies span:nth-child(10) { left: 72.2%; top: 53.6%; --s: 0.2; --x1: -0.6; --y1: 0.9; --x2: 0.8; --y2: 0.4; animation-duration: 15.5s, 5.1s; animation-delay: -8s, -2.5s; }
.temple-fireflies span:nth-child(11) { left: 75.9%; top: 49.1%; --s: 0.34; --x1: 1; --y1: -0.6; --x2: 0.4; --y2: 0.9; animation-duration: 10s, 7.2s; animation-delay: -6s, -0.2s; }
.temple-fireflies span:nth-child(12) { left: 79.7%; top: 56.6%; --s: 0.22; --x1: -0.9; --y1: -0.7; --x2: -1.1; --y2: 0.5; animation-duration: 13.5s, 4.6s; animation-delay: -10s, -3.5s; }
.temple-fireflies span:nth-child(13) { left: 83.4%; top: 51.8%; --s: 0.28; --x1: 0.5; --y1: 0.7; --x2: -0.7; --y2: -0.5; animation-duration: 9s, 6.4s; animation-delay: -0.5s, -5.5s; }
.temple-fireflies span:nth-child(14) { left: 86.5%; top: 47.9%; --s: 0.2; --x1: -1.1; --y1: -0.8; --x2: 0.6; --y2: -0.3; animation-duration: 11.5s, 5.7s; animation-delay: -12s, -2.8s; }
@media (orientation: portrait) {
  /* Ten specks across the portrait band, a few at each end beside the head
     (on phones it covers x 12-88 %), the rest behind it; they sway less
     sideways. The other four are hidden. */
  .temple-fireflies {
    --sway: 0.3cqw;
  }
  .temple-fireflies span:nth-child(1) { left: 10.6%; top: 49.2%; }
  .temple-fireflies span:nth-child(2) { left: 11.4%; top: 53.1%; }
  .temple-fireflies span:nth-child(3) { left: 12.1%; top: 50.9%; }
  .temple-fireflies span:nth-child(4) { left: 26.3%; top: 48.3%; }
  .temple-fireflies span:nth-child(5) { left: 41.8%; top: 52.6%; }
  .temple-fireflies span:nth-child(6) { left: 58.4%; top: 49.4%; }
  .temple-fireflies span:nth-child(7) { left: 73.9%; top: 53.4%; }
  .temple-fireflies span:nth-child(8) { left: 87.9%; top: 48.6%; }
  .temple-fireflies span:nth-child(9) { left: 88.8%; top: 52.2%; }
  .temple-fireflies span:nth-child(10) { left: 89.4%; top: 50.3%; }
  .temple-fireflies span:nth-child(n + 11) {
    display: none;
  }
}
@keyframes temple-firefly-drift {
  0% { transform: translate(0, 0); }
  50% { transform: translate(calc(var(--x1) * var(--sway)), calc(var(--y1) * 1cqh)); }
  100% { transform: translate(calc(var(--x2) * var(--sway)), calc(var(--y2) * 1cqh)); }
}
/* Dim for most of the cycle, then a slow fade up and back down (each step
   eases in and out), so the lights breathe rather than blink. */
@keyframes temple-firefly-pulse {
  0%, 40%, 100% { opacity: 0.05; }
  68% { opacity: 0.75; }
}

/* ---------- Crocodile placement ---------- */
body[data-character="temple"] .game-board {
  display: block;
}
body[data-character="temple"] .character-space {
  position: absolute;
  left: 0;
  top: calc(-1 * var(--band-top));
  width: 100cqw;
  height: 100cqh;
  padding: 0;
  display: block;
  z-index: 1;
  pointer-events: none;
}
/* The jaw (626.5, 1090 of the 1254 frame) sits on the anchor point. */
body[data-character="temple"] .character-wrap {
  position: absolute;
  left: calc(var(--platform-x) - 0.49960 * var(--croc-w));
  top: calc(var(--platform-y) - 0.86922 * var(--croc-w));
  width: var(--croc-w);
  height: var(--croc-w);
  aspect-ratio: auto;
}
body[data-character="temple"] .character-float,
body[data-character="temple"] #character-motion,
body[data-character="temple"] .character-breathe,
.temple-head {
  position: absolute;
  inset: 0;
  transform-origin: 49.96% 86.92%;
}
/* A stone head rests motionless on its stone island: no idle bob, sway or
   breathing (styles.css gives the other editions theirs, so switch them off).
   Only the reactions below move it. */
body[data-character="temple"] .character-float,
body[data-character="temple"] .character-breathe {
  animation: none;
}
/* Fades in once the open and closed poses are decoded (temple-character.js). */
body[data-character="temple"] .character-float,
body[data-character="temple"] .temple-contact,
body[data-character="temple"] .temple-reflection {
  transition: opacity 0.25s ease-out;
}
body[data-character="temple"] .character-wrap:not(.poses-ready) .character-float,
body[data-character="temple"] .character-wrap:not(.poses-ready) .temple-contact,
body[data-character="temple"] .character-wrap:not(.poses-ready) .temple-reflection {
  opacity: 0;
}
/* Contact shadow: a soft ambient-occlusion ellipse on the island's top surface
   around the base of the head, 1.15 x the frame wide and 9 % of it tall,
   centred on the jaw's x at the rim line (the jaw point itself is behind the
   rim, see Seating). It lies under the head and the rim, so only the stone
   beside the base of the head darkens: #03120f at 0.5 in the centre, still
   0.3-0.4 where the head's base ends (60-70 % of the way out) and clear by
   88 %, inside the island's edge. It never pulses. */
.temple-contact {
  position: absolute;
  left: -7.54%;
  /* Centred on the back edge of the island's front lip, --isle-sink head
     widths above the jaw. */
  top: calc(82.422% - var(--isle-sink) * 100%);
  width: 115%;
  height: 9%;
  background: radial-gradient(
    closest-side,
    rgb(3 18 15 / 0.5),
    rgb(3 18 15 / 0.45) 50%,
    rgb(3 18 15 / 0.3) 66%,
    rgb(3 18 15 / 0.1) 80%,
    rgb(3 18 15 / 0) 88%
  );
}
/* Flat: centred 1.5 % of the head above the jaw, so it darkens the paved top
   around the base and fades out by the top's front edge (2.5 % below the
   jaw) instead of spilling over the blocks' front faces. */
body[data-isle="flat"] .temple-contact {
  top: calc(80.922% - var(--isle-sink) * 100%);
}
/* Deep: the base of the head fills the pit's opening, from the pit's widest
   row (6.2 % above its front edge) down to the chin, so the shadow is wider,
   taller, darker further out and centred 4 % above the front edge: it
   darkens the ring's top under the head's overhanging sides and the strip of
   pit showing under the jaw (the rim hides the rest). */
body[data-isle="deep"] .temple-contact {
  left: -12.54%;
  top: calc(75.922% - var(--isle-sink) * 100%);
  width: 125%;
  height: 14%;
  background: radial-gradient(
    closest-side,
    rgb(3 18 15 / 0.55),
    rgb(3 18 15 / 0.5) 55%,
    rgb(3 18 15 / 0.35) 78%,
    rgb(3 18 15 / 0) 100%
  );
}
.temple-open,
.temple-closed,
.temple-bite {
  position: absolute;
  inset: 0;
}
/* Closed and bite poses (same canvas) moved down 225 px and scaled 0.993 about
   their jaw (626.5, 865) onto the open jaw (626.5, 1090): same width, same
   resting point. The whole head drops when the jaws shut. The reflection's
   copies of the poses follow the same rules as the poses. */
body[data-character="temple"] :is(.temple-closed, .temple-bite, .temple-reflection-closed, .temple-reflection-bite) {
  visibility: hidden;
  transform-origin: 49.96% 68.98%;
  transform: translateY(17.94%) scale(0.993);
}
/* Idle shows the shut mouth (once the closed pose has decoded). */
body[data-character="temple"] .game-board:not(.playing, .won, .lost) .has-closed-pose :is(.temple-open, .temple-reflection-open) {
  visibility: hidden;
}
body[data-character="temple"] .game-board:not(.playing, .won, .lost) .has-closed-pose :is(.temple-closed, .temple-reflection-closed) {
  visibility: visible;
}
/* A bite shows the snap pose (grumpy wide eyes), or the closed pose without it. */
body[data-character="temple"] .game-board.lost .has-bite-pose :is(.temple-open, .temple-reflection-open),
body[data-character="temple"] .game-board.lost .has-closed-pose :is(.temple-open, .temple-reflection-open) {
  visibility: hidden;
}
body[data-character="temple"] .game-board.lost .has-bite-pose :is(.temple-bite, .temple-reflection-bite),
body[data-character="temple"] .game-board.lost .has-closed-pose:not(.has-bite-pose) :is(.temple-closed, .temple-reflection-closed) {
  visibility: visible;
}
/* A bite holds the open jaws for 110 ms, then shuts them at the impact. The
   readout leaves the mouth for its place above the head at the same moment. */
body[data-character="temple"] .game-board.lost :is(.temple-open, .temple-closed, .temple-bite, .temple-reflection-poses img) {
  transition: visibility 0s 110ms;
}
body[data-character="temple"] .game-board.lost .temple-readout,
body[data-character="temple"] .game-board.lost .temple-readout * {
  transition: all 0s 110ms;
}
/* A lost round shows no multiplier: the readout vanishes at the impact and
   returns with the next bet. */
body[data-character="temple"] .game-board.lost .temple-readout {
  visibility: hidden;
}
/* game.js writes a new × span with the lost render; it follows the number at
   once instead of starting its own 110 ms delay when the number hides. */
body[data-character="temple"] .game-board.lost #current-multiplier > span {
  transition: none;
}
/* Until it hides, the number keeps its heat look too: the clipped gold of
   tension 3-4 is a discrete background, held with the colour instead of
   leaving bare outlines for 110 ms. */
body[data-character="temple"] .game-board.lost #current-multiplier {
  transition-behavior: allow-discrete;
}
/* A new round swaps to the open pose at the bottom of the anticipation dip,
   and the readout drops into the opened mouth with it. */
body[data-character="temple"] .game-board.playing :is(.temple-open, .temple-closed, .temple-bite, .temple-reflection-poses img) {
  transition: visibility 0s 90ms;
}
body[data-character="temple"] .game-board.playing .temple-readout,
body[data-character="temple"] .game-board.playing .temple-readout * {
  transition: all 0s 90ms;
}
/* Only the readout itself waits the 90 ms to show: its children follow its
   visibility at once, or the delays stack down the nesting and the number,
   hidden after a bite, shows only once its rise is over. */
body[data-character="temple"] .game-board.playing .temple-readout * {
  transition: all 0s 90ms, visibility 0s;
}

/* ---------- Seating: the head sits in the island ---------- */
/* The island is its own sprite (temple-island.webp, scripts/make-temple-
   island.py), drawn over the scene's small painted island and sized to the
   head, so it stays sharp on any screen. It lies under the crocodile, which
   stands on it with its jaw on the back edge of the front lip; the contact
   shadow and the base shade ground the head. Nothing is drawn over the head.
   /temple-flat/ (body[data-isle="flat"]) stands the head on the paved top of
   temple-island-flat.webp; /temple-deep/ (body[data-isle="deep"]) sets it
   down in the pit of temple-island-deep.webp, its wider sides over the ring,
   and .temple-rim draws the pit's front arc and the blocks' front faces
   again over the chin. */
.temple-island,
.temple-rim {
  position: absolute;
  left: var(--isle-x);
  top: var(--isle-y);
  width: var(--isle-w);
  height: var(--isle-h);
  background: url("/assets/temple-island.webp") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
  /* Shows with the head (.character-float's fade), as one piece. */
  transition: opacity 0.25s ease-out;
}
body[data-isle="flat"] .temple-island {
  background-image: url("/assets/temple-island-flat.webp");
}
body[data-isle="deep"] .temple-island,
body[data-isle="deep"] .temple-rim {
  background-image: url("/assets/temple-island-deep.webp");
}
/* The base of the head reads as in shadow where it meets the stone. Each pose
   carries a copy of its own silhouette (.temple-shade: a mask of the pose's
   WebP in the pose's box, so it shares the closed and bite transform and the
   pose's visibility), filled with a gradient that is clear above the lowest
   ~7 % of the frame and #03120f at 0.55 from the rim line down. The ramp never
   starts above 76.3 % of the frame (the lower sockets end at 76.1 %), and the
   open pose's copy lies under the tooth layer, so no tooth or socket pad is
   darkened, whether it stands or has retracted. */
.temple-shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    rgb(3 18 15 / 0) var(--shade-top),
    rgb(3 18 15 / 0.55) var(--shade-line)
  );
  -webkit-mask-image: var(--pose-art);
  mask-image: var(--pose-art);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  mask-mode: alpha;
}
/* The rim line in each pose's own box: the open jaw line (86.922 %) less the
   rim's height above the jaw; the closed and bite boxes are moved 17.94 % down
   and scaled 0.993 about 68.98 %, so there it is 68.98 % less that height
   / 0.993. */
.temple-open > .temple-shade {
  --pose-art: url("/assets/temple-croc-open.webp");
  --shade-line: calc(86.922% - (var(--platform-y) - var(--rim-y)));
  --shade-top: max(76.3%, calc(79.922% - (var(--platform-y) - var(--rim-y))));
}
.temple-closed > .temple-shade,
.temple-bite > .temple-shade {
  --shade-line: calc(68.98% - (var(--platform-y) - var(--rim-y)) / 0.993);
  --shade-top: max(58.28%, calc(61.93% - (var(--platform-y) - var(--rim-y)) / 0.993));
}
.temple-closed > .temple-shade {
  --pose-art: url("/assets/temple-croc-closed.webp");
}
.temple-bite > .temple-shade {
  --pose-art: url("/assets/temple-croc-bite.webp");
}
/* Flat and Deep key the line to their sprite instead of the scene's painted
   rim: the jaw line less the sink (the jaw itself on the flat top, the pit's
   front edge in the deep pit), with the same ramp and clamps. */
body[data-isle] .temple-open > .temple-shade {
  --shade-line: calc(86.922% - var(--isle-sink) * 100%);
  --shade-top: max(76.3%, calc(79.922% - var(--isle-sink) * 100%));
}
body[data-isle] .temple-closed > .temple-shade,
body[data-isle] .temple-bite > .temple-shade {
  --shade-line: calc(68.98% - var(--isle-sink) * 100% / 0.993);
  --shade-top: max(58.28%, calc(61.93% - var(--isle-sink) * 100% / 0.993));
}
/* A faint reflection of the visible pose in the water in front of the island:
   copies of the three poses (the same visibility rules and closed and bite
   transform as the poses) in a box 0.9 x the frame wide and 0.35 x its height,
   flipped about the rim line. Squashed like the head, the rim line's
   reflection lies below the waterline by 0.35 x the rim's height above it;
   the island's own reflection in the picture fills the water between. The head
   shows through a window over the middle 76 % of the frame (clear of the pause
   button), at most 10 % of the frame tall and never past the bet panel (short
   landscape phones have no room and show none). The window fades it out
   downwards and at the sides; it is blurred 2 px, 0.22 opaque, and keeps still
   through the reactions. It lies under the head, the rim, the pause button and
   the bet panel. */
/* The island sprite brings its own water in front of the head, so the
   reflection stays hidden. */
.temple-reflection {
  display: none;
  --reflect-top: calc(var(--water-y) + 0.35 * (var(--water-y) - var(--rim-y)));
  --reflect-fade: linear-gradient(#0006, #000 18%, transparent);
  --reflect-sides: linear-gradient(90deg, transparent, #000 24%, #000 76%, transparent);
  position: absolute;
  left: 12%;
  top: calc(86.922% + var(--reflect-top) - var(--platform-y));
  width: 76%;
  height: max(0px, min(10%, calc(var(--band-bottom) - var(--reflect-top))));
  opacity: 0.22;
  filter: blur(2px);
  pointer-events: none;
  -webkit-mask-image: var(--reflect-fade), var(--reflect-sides);
  -webkit-mask-composite: source-in;
  mask-image: var(--reflect-fade), var(--reflect-sides);
  mask-composite: intersect;
}
.temple-reflection-poses {
  /* The rim line's depth in the unflipped box, which sits on the window top. */
  --reflect-rim: calc(0.35 * (0.86922 * var(--croc-w) - (var(--platform-y) - var(--rim-y))));
  position: absolute;
  left: calc(-0.07 * var(--croc-w));
  top: calc(-1 * var(--reflect-rim));
  width: calc(0.9 * var(--croc-w));
  height: calc(0.35 * var(--croc-w));
  transform-origin: 50% var(--reflect-rim);
  transform: scaleY(-1);
}
.temple-reflection-poses img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* The rim: the deep sprite again, in the island's box, over the crocodile, its
   droplets and coins (under the CHOMP word, the readout, the top bar and the
   bet panel). The head is wider than the pit, so the rim holds only what may
   cover it: the pit's front arc and the ring in front of it, where the pit's
   floor and walls disappear behind the near ring's top, and the blocks'
   vertical front faces. The ring's top beside the pit is left out, so the
   head's wider sides lie over it. Traced by hand on zoomed crops of the
   source and checked by drawing it over the sprite (in % of the 1774 x 500
   sprite): along the top edge of the blocks' front faces from the sprite's
   left edge to below the pit's left extreme (x 383, source row 399), up to
   that extreme, along the front arc (lowest, row 477.5, at x 893) to the
   right extreme (x 1403, row 400), down to the faces again, along their top
   edge to the right edge, and everything below. At rest the head only
   reaches the arc at the chin (its lowest 0.6 %); where its outline crosses
   the arc it is at most 3 % of the head above the jaw, and the whole arc
   stays below 6.8 %, clear of every tooth and socket pad. */
.temple-rim {
  display: none;
}
body[data-isle="deep"] .temple-rim {
  display: block;
  clip-path: polygon(0% 23.4%, 6.09% 23.4%, 7.67% 25.2%, 8.85% 29.6%, 10.15% 31%, 11.56% 31.6%, 12.97% 32%, 14.43% 32.6%, 16.35% 35.2%, 17.93% 36.8%, 19.73% 37.4%, 21.59% 37.6%, 21.59% 19.8%, 21.76% 21%, 22.1% 22%, 22.55% 23%, 23.22% 24%, 24.24% 25.2%, 26.49% 27.4%, 29.88% 29.6%, 33.82% 32%, 39.46% 34%, 45.1% 35.2%, 50.34% 35.5%, 55.81% 35.4%, 61.44% 34.4%, 66.52% 33%, 71.03% 30.8%, 73.28% 29.4%, 74.97% 28%, 76.38% 26.4%, 77.51% 24.8%, 78.35% 23.2%, 78.81% 21.8%, 79.09% 20%, 79.09% 38.2%, 80.38% 38%, 82.07% 37%, 83.2% 34.8%, 83.54% 31.6%, 85.68% 32.8%, 87.37% 32%, 89.06% 30.8%, 90.42% 28.8%, 91.09% 28%, 91.54% 24.8%, 93.12% 24%, 93.91% 22.4%, 100% 22.4%, 100% 100%, 0% 100%);
}

/* ---------- Eyes: blink and satisfied composites over the open head ---------- */
.temple-eye {
  position: absolute;
  overflow: visible;
  pointer-events: none;
  opacity: 0;
}
.temple-eye-satisfied {
  transition: opacity 180ms ease-out;
}
.is-satisfied .temple-eye-satisfied {
  opacity: 1;
  transition-duration: 220ms;
}
.temple-eye-blink {
  /* Clipped to its own eye: the mask holds both eyes, so without it the
     right eye's composite paints the left eye too and the wink shuts both.
     The viewBox keeps the grown, feathered edge. */
  overflow: hidden;
  transition: opacity 70ms ease-out;
}
.is-blinking .temple-eye-blink {
  opacity: 1;
  transition-duration: 45ms;
}
.is-slow-blink .temple-eye-blink {
  transition-duration: 140ms;
}

/* ---------- Eye rig: gaze, lids and slits (batch 5) ---------- */
/* dist/temple-eye-rig.js (scripts/make-temple-eyes.py) layers each painted
   eye of the open and shut heads, clipped to its socket: the plate (socket
   without the eyeball), g.rig-ball (iris plate, g.rig-slit with the pupil,
   the tier-4 ring), the catchlight, g.rig-lid (the half-lid slab of the
   satisfied art, native at lid 0.45) and on the shut head g.rig-shut (the
   blink art's lid). At rest a rig recomposes its painting, so it shows only
   while temple-character.js holds .is-rigged, and inherits its pose's
   visibility. Gaze (--look-x/-y) is set per eye in canvas px; the stare
   follows data-stare (data-tension's mirror, held through a win's glance).
   Event classes set --lid/--slit/--iris-k directly and beat the stare's
   --stare-* values. Eye effects are gold, white or teal, never red. */
.temple-rig {
  --stare-lid: 0;
  --stare-tilt: 0deg;
  --stare-slit: 1;
  --lid: var(--stare-lid);
  --lid-tilt: var(--stare-tilt);
  --slit: var(--stare-slit);
  --iris-k: 1;
  position: absolute;
  overflow: visible;
  pointer-events: none;
  visibility: hidden;
}
.temple-rig-r {
  --tilt-sign: -1;
}
.is-rigged .temple-rig {
  visibility: inherit;
}
.rig-ball {
  transform-box: fill-box;
  transform-origin: center;
  transform: translate(calc(var(--look-x, 0) * 1px), calc(var(--look-y, 0) * 1px)) scale(var(--iris-k));
  transition: transform 140ms cubic-bezier(0.2, 0.8, 0.3, 1);
}
.rig-slit {
  transform-box: fill-box;
  transform-origin: center;
  transform: translateX(calc(var(--look-x, 0) * 0.35px)) scaleX(var(--slit));
  transition: transform 140ms cubic-bezier(0.2, 0.8, 0.3, 1);
}
/* lid 0 lifts the slab out of the socket; the tilt pivots it on the eye's
   outer corner (mirrored on the right), so the inner end sits lower. */
.rig-lid {
  transform-box: fill-box;
  transform-origin: var(--lid-pivot);
  transform: translateY(calc((var(--lid) - 0.45) * var(--lid-h))) rotate(calc(var(--tilt-sign, 1) * var(--lid-tilt)));
  transition: transform 300ms cubic-bezier(0.3, 0.7, 0.4, 1);
}
.rig-shut {
  opacity: 0;
  transition: opacity 90ms ease-out;
}
.rig-ring {
  transition: opacity 300ms ease-out;
}
#character-wrap.is-eyes-home .temple-rig :is(.rig-ball, .rig-slit) {
  transition: transform 260ms ease-in-out;
}
/* Asleep through the island rise (batch 6): the shut lids stay down until
   the wake-up, which starts shut, lifts them. */
#character-wrap.is-asleep .temple-closed .rig-shut {
  opacity: 1;
  transition: none;
}
/* Watching the far water (batch 6's carp and flock): the eyes turn over
   --track-ms, linearly with the flock's slow crossing. */
#character-wrap.is-tracking .temple-rig :is(.rig-ball, .rig-slit) {
  transition: transform var(--track-ms, 200ms) var(--track-ease, ease-out);
}
/* Tension stare: a wary scowl that hardens into a glare (tilt <= 15deg).
   Tiers 3-4 stop at lid 0.34 / 0.42 (the plan's 0.4 / 0.55 with the tilt
   covered the iris), so the glare keeps the lower iris and the ring. */
#character-wrap[data-stare="2"] .temple-rig {
  --stare-lid: 0.25;
  --stare-tilt: 7deg;
  --stare-slit: 0.8;
}
#character-wrap[data-stare="3"] .temple-rig {
  --stare-lid: 0.34;
  --stare-tilt: 10deg;
  --stare-slit: 0.6;
}
#character-wrap[data-stare="4"] .temple-rig {
  --stare-lid: 0.42;
  --stare-tilt: 13deg;
  --stare-slit: 0.45;
}
#character-wrap[data-stare="4"] .rig-ring {
  opacity: 0.7;
}
/* The growl and the press wince never soften a harder stare. */
#character-wrap.is-growling .temple-rig {
  --lid: max(var(--stare-lid), 0.25);
  --slit: min(var(--stare-slit), 0.6);
}
#character-wrap.is-wincing-l .temple-rig-l,
#character-wrap.is-wincing-r .temple-rig-r {
  --lid: max(var(--stare-lid), 0.35);
}
#character-wrap.is-wincing-both .temple-rig {
  --lid: max(var(--stare-lid), 0.2);
}
#character-wrap:is(.is-wincing-l, .is-wincing-r, .is-wincing-both) .rig-lid {
  transition-duration: 80ms;
}
/* Cash out: worried wide pupils, then a scheming relief. */
#character-wrap.is-relieved .temple-rig {
  --slit: 0.7;
}
#character-wrap.is-worried .temple-rig {
  --slit: 1.5;
  --iris-k: 1.05;
  --lid: 0;
  --lid-tilt: 0deg;
}
#character-wrap.is-worried .temple-rig :is(.rig-ball, .rig-slit, .rig-lid) {
  transition-duration: 140ms;
}
/* Gotcha: at the bite's wind-up the pupils snap to slits. */
#character-wrap.is-gotcha .temple-rig {
  --slit: 0.25;
  --iris-k: 1.06;
}
#character-wrap.is-gotcha .temple-rig :is(.rig-ball, .rig-slit) {
  transition-duration: 60ms;
}
/* Greedy eyes on the shut head between rounds. */
#character-wrap.is-greedy .temple-rig {
  --slit: var(--greed-slit, 1);
}
#character-wrap.is-unimpressed .temple-rig {
  --slit: 0.7;
  --lid: 0.2;
}
#character-wrap.is-menacing .temple-rig {
  --slit: 0.5;
  --lid: 0.18;
}
/* Shut-head lid blinks, and the wake-up: eyes shut, a sleepy half-open,
   then open while the pupils focus. Every last keyframe is the rest. */
#character-wrap.is-lid-blink .temple-closed .rig-shut {
  opacity: 1;
  transition-duration: 45ms;
}
#character-wrap.is-lid-slow .temple-closed .rig-shut {
  transition-duration: 140ms;
}
#character-wrap.is-waking .temple-closed .rig-shut {
  animation: temple-wake-shut 560ms linear;
}
#character-wrap.is-waking .temple-closed .rig-lid {
  animation: temple-wake-lid 1100ms linear;
}
#character-wrap.is-waking .temple-closed .rig-slit {
  animation: temple-wake-slit 1310ms linear;
}
@keyframes temple-wake-shut {
  0%,
  71.4% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
@keyframes temple-wake-lid {
  0%,
  73.6% {
    transform: translateY(calc(-0.05 * var(--lid-h)));
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  100% {
    transform: translateY(calc(-0.45 * var(--lid-h)));
  }
}
@keyframes temple-wake-slit {
  0%,
  61.8% {
    transform: translateX(0px) scaleX(1.5);
    animation-timing-function: cubic-bezier(0.3, 0.7, 0.4, 1);
  }
  100% {
    transform: translateX(0px) scaleX(1);
  }
}
/* Cash-out moods: a timid eye roll, a shock, the glance at the wallet, then
   the slab settles at its native half-lid under the painted one; the wink
   is the right blink composite over the right half-lid. */
#character-wrap.is-eye-rolling .temple-rig {
  --lid: 0.3;
}
#character-wrap.is-eye-rolling .temple-open .rig-ball {
  animation: temple-eye-roll 620ms ease-in-out both;
}
@keyframes temple-eye-roll {
  0%,
  100% {
    transform: translate(0px, 0px);
  }
  12.5% {
    transform: translate(-5.66px, 5.66px);
  }
  25% {
    transform: translate(-8px, 0px);
  }
  37.5% {
    transform: translate(-5.66px, -5.66px);
  }
  50% {
    transform: translate(0px, -8px);
  }
  62.5% {
    transform: translate(5.66px, -5.66px);
  }
  75% {
    transform: translate(8px, 0px);
  }
  87.5% {
    transform: translate(5.66px, 5.66px);
  }
}
#character-wrap.is-shocked .temple-rig {
  --slit: 2.6;
  --iris-k: 1.08;
  --lid: 0;
  --lid-tilt: 0deg;
}
#character-wrap.is-half-lid .temple-rig {
  --lid: 0.45;
  --lid-tilt: 0deg;
  --slit: 1;
}
#character-wrap.is-winking .temple-eye-blink + .temple-eye-blink {
  opacity: 1;
  transition-duration: 70ms;
}
.is-pfft .temple-nostril:last-child .temple-pfft {
  --o: 0.7;
  animation: temple-puff 760ms cubic-bezier(0.05, 0.85, 0.3, 1) var(--d) both;
}
/* The sweat drop on the outer brow on Cash out's side: beads up, clings,
   slides down the ridge and drips off. Teal and white. */
.temple-sweat {
  --dir: -1;
  position: absolute;
  overflow: visible;
  pointer-events: none;
  opacity: 0;
  transform-origin: 50% 100%;
}
.temple-sweat-r {
  --dir: 1;
}
.temple-sweat.is-sweating {
  animation: temple-sweat 1300ms linear both;
}
@keyframes temple-sweat {
  0% {
    opacity: 0;
    transform: translate(0%, 0%) scale(0);
    animation-timing-function: cubic-bezier(0.2, 0.9, 0.3, 1.2);
  }
  20%,
  43% {
    opacity: 1;
    transform: translate(0%, 0%) scale(1);
    animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5);
  }
  83% {
    opacity: 1;
    transform: translate(calc(var(--dir) * 135%), 236%) scale(1);
    animation-timing-function: cubic-bezier(0.5, 0, 1, 1);
  }
  100% {
    opacity: 0;
    transform: translate(calc(var(--dir) * 135%), 403%) scale(0.9);
  }
}

/* ---------- Readout: inside the open mouth, above the shut head ---------- */
/* Open head (playing, won, or idle without the closed pose): the readout sits
   in the dark cavity between the tooth tips. On the open art the upper tips
   end at y 589 and the lower tips start at y 768 of the 1254 frame, so the
   band is 179 px (14.3 %) tall, tooth-free by construction, and spans x
   155-1097; its centre (627, 678) is 50 %, 54.1 %. The readout is centred
   there, at most 70 % of the frame wide, with sizes that follow the head and
   no pill, and it never takes a pointer event, so every tooth stays
   pressable. Shut head (idle, bite): above the head as before, anchored to its
   top (402 / 1254 = 32.05 %). Every property that differs between the two
   placements interpolates, so the delayed transitions above swap all of them
   together with the pose. */
body[data-character="temple"] .temple-readout {
  position: absolute;
  left: 50%;
  top: 54.1%;
  width: max-content;
  max-width: 70%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 3;
}
body[data-character="temple"] .temple-readout .scoreboard {
  display: grid;
  justify-items: center;
  filter: none;
}
body[data-character="temple"] #current-multiplier {
  font-size: var(--mouth-value);
  letter-spacing: -0.02em;
  color: #f7f1dc;
  -webkit-text-stroke: 0 #0f3a2a;
  paint-order: stroke fill;
  text-shadow: 0 0 0.24em #010b09d9, 0 0.03em 0.08em #010b09;
}
body[data-character="temple"] .next-multiplier {
  margin-top: var(--mouth-gap);
  padding: 0;
  border: 0 solid transparent;
  border-radius: 999px;
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  color: #bfe3c9;
  font-size: var(--mouth-next);
  line-height: 1.1;
  white-space: nowrap;
  text-shadow: 0 0 0.35em #010b09;
}
body[data-character="temple"] #next-multiplier {
  color: #ffe08c;
  font-size: 1.15em;
}
/* Above the closed or bite head. */
body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose .temple-readout,
body[data-character="temple"] .game-board.lost .has-bite-pose .temple-readout {
  top: calc(32.05% - var(--readout-gap));
  transform: translate(-50%, -100%);
}
body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose #current-multiplier,
body[data-character="temple"] .game-board.lost .has-bite-pose #current-multiplier {
  font-size: var(--readout-size);
  letter-spacing: -0.03em;
  -webkit-text-stroke: 0.09em #0f3a2a;
  text-shadow: 0 0.05em 0 #0f3a2a, 0 0.12em 0.3em #02100cb3;
}
body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose .next-multiplier,
body[data-character="temple"] .game-board.lost .has-bite-pose .next-multiplier {
  margin-top: 6px;
  padding: 5px 13px;
  border-width: 1px;
  border-color: #fff5d42e;
  background: #0a2a24c7;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #d9ead6;
  font-size: 12px;
  line-height: 1.36;
  text-shadow: none;
}
body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose #next-multiplier,
body[data-character="temple"] .game-board.lost .has-bite-pose #next-multiplier {
  font-size: 19px;
}
body[data-character="temple"] .lost #current-multiplier {
  color: #ff9f84;
}
/* The count (temple-character.js) rolls the digits in place: equal-width
   figures keep the number from jittering while it counts. */
body[data-character="temple"] #current-multiplier {
  font-variant-numeric: tabular-nums;
}
body[data-character="temple"] #next-multiplier {
  display: inline-block;
  position: relative;
}
/* Heat: while a round plays the number warms with the tension (data-tension
   on #character-wrap, 1-4). A state, so it holds under reduced motion and
   switches at once (the stamp masks the switch). Tier 1 is the ivory above,
   2 a warm cream, 3 and 4 gold inlay: a gradient clipped to the glyphs, the
   legibility shadow moved to the readout as a filter (a text-shadow would
   paint over the clipped glyphs). The next-tooth value runs one step warmer
   and its caption turns sand at 3-4. Never orange-red: every hue here is 38
   degrees or more. A cash-out holds the tier-4 gold. */
body[data-character="temple"] .game-board.playing #character-wrap[data-tension="2"] #current-multiplier {
  color: #fce6ae;
}
body[data-character="temple"] .game-board.playing #character-wrap[data-tension="3"] #current-multiplier {
  color: transparent;
  background: linear-gradient(180deg, #fff3c4, #ffd24f 55%, #e0a02a);
  -webkit-background-clip: text;
  background-clip: text;
  text-shadow: none;
}
body[data-character="temple"] .game-board.playing #character-wrap[data-tension="4"] #current-multiplier,
body[data-character="temple"] .game-board.won #current-multiplier {
  color: transparent;
  background: linear-gradient(180deg, #fff6d0, #ffc948 55%, #c98a1c);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-stroke: 0.025em #6b420b;
  text-shadow: none;
}
/* The heat switches at once: the readout's "all 0s 90ms" would hold the old
   colour and shadow for 90 ms over the new clipped gradient (or leave the
   glyphs transparent for 90 ms when a round follows a cash-out's gold). */
body[data-character="temple"] .game-board.playing #current-multiplier,
body[data-character="temple"] .game-board.playing #current-multiplier > span {
  transition: all 0s 90ms, color 0s, text-shadow 0s, visibility 0s;
}
body[data-character="temple"] .game-board.playing #character-wrap:is([data-tension="3"], [data-tension="4"]) .multiplier-readout,
body[data-character="temple"] .game-board.won .multiplier-readout {
  filter: drop-shadow(0 0 3px #010b09e6) drop-shadow(0 1px 2px #010b09);
}
body[data-character="temple"] .game-board.playing #character-wrap[data-tension="2"] #next-multiplier {
  color: #ffd66b;
}
body[data-character="temple"] .game-board.playing #character-wrap[data-tension="3"] #next-multiplier {
  color: #ffc94d;
}
body[data-character="temple"] .game-board.playing #character-wrap[data-tension="4"] #next-multiplier {
  color: #ffbd4a;
}
body[data-character="temple"] .game-board.playing #character-wrap:is([data-tension="3"], [data-tension="4"]) .next-multiplier > span {
  color: #f3d7a0;
}
/* Hover preview: pointing at (or focusing) a standing tooth lifts the
   next-tooth value and underlines it, what that tooth would pay. The
   transition list starts with the readout's own "all 0s 90ms", so the pose
   swap still moves its size with the pose. */
body[data-character="temple"] .game-board.playing #next-multiplier {
  transition:
    all 0s 90ms,
    transform 160ms cubic-bezier(0.3, 0.7, 0.4, 1.3),
    color 160ms;
}
body[data-character="temple"] #next-multiplier::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.12em;
  height: 1.5px;
  border-radius: 1px;
  background: #ffd46b;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms ease-out;
  pointer-events: none;
}
@media (hover: hover) {
  body[data-character="temple"] .game-board.playing:has(.tooth:enabled:not(.picked, .is-trap):hover) #character-wrap #next-multiplier {
    color: #fff1c2;
    transform: translateY(-1px) scale(1.1);
  }
  body[data-character="temple"] .game-board.playing:has(.tooth:enabled:not(.picked, .is-trap):hover) #next-multiplier::after {
    transform: scaleX(1);
  }
}
body[data-character="temple"] .game-board.playing:has(.tooth:enabled:not(.picked, .is-trap):focus-visible) #character-wrap #next-multiplier {
  color: #fff1c2;
  transform: translateY(-1px) scale(1.1);
}
body[data-character="temple"] .game-board.playing:has(.tooth:enabled:not(.picked, .is-trap):focus-visible) #next-multiplier::after {
  transform: scaleX(1);
}

/* ---------- Teeth: the stone tooth click ---------- */
/* Hit areas grow to 44 px, but never past the tooth spacing (0.16 of the frame). */
body[data-character="temple"] .tooth::after {
  width: max(100%, min(44px, calc(var(--croc-w) * 0.155)));
  height: max(100%, min(44px, calc(var(--croc-w) * 0.155)));
}
body[data-character="temple"] .tooth-number {
  font-size: clamp(9px, 1.1vw, 12px);
}
body[data-character="temple"] .tooth-sprite {
  position: relative;
}
/* The checked socket pad under each tooth, hidden until the tooth is pressed. */
.tooth-pad {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease-out;
}
body[data-character="temple"] .tooth.picked .tooth-pad {
  opacity: 1;
  transition: opacity 160ms ease-out 70ms;
}
/* The pressed tooth travels into its collar (scaled from the root: top edge
   for the upper row, bottom edge for the lower row) and dims on the way. */
body[data-character="temple"] .tooth.picked .tooth-sprite {
  transform: scaleY(0.02);
  filter: brightness(0.72);
  opacity: 0;
  transition:
    transform 150ms cubic-bezier(0.55, 0, 0.85, 0.35),
    filter 150ms ease-in,
    opacity 40ms linear 125ms;
}
/* game.js releases every tooth at a bite: keep the pressed look until the
   jaws have shut, then reset out of sight. */
body[data-character="temple"] .game-board.lost .tooth-sprite,
body[data-character="temple"] .game-board.lost .tooth-pad {
  transition-delay: 300ms;
}
/* Tension (data-tension, 1-4, while a round plays) sets how long a safe tooth
   catches before it drops (--catch), how hard the other teeth rattle
   (--rattle) and how far the head strains (--amp); --seat is when the tooth
   has seated in its collar. */
body[data-character="temple"] #character-wrap {
  --catch: 50ms;
  --rattle: 1;
  --amp: 1;
  --seat: calc(60ms + var(--catch));
}
body[data-character="temple"] #character-wrap[data-tension="2"] {
  --catch: 80ms;
  --rattle: 1.4;
}
body[data-character="temple"] #character-wrap[data-tension="3"] {
  --catch: 110ms;
  --rattle: 1.9;
}
body[data-character="temple"] #character-wrap[data-tension="4"] {
  --catch: 140ms;
  --rattle: 2.3;
  --amp: 1.5;
}
/* Stone catch: a safe tooth does not simply sink. It catches part way down
   in its collar, wobbles once on its root (the same beat as a bite's
   wind-up, so every safe press opens like one), then slams home and dims.
   The slam's last frame is the static .picked look above, so nothing jumps
   when .just-picked ends; forwards (not both), so its first frame does not
   cover the catch during its delay. At most 60 + 140 + 100 = 300 ms, inside
   game.js's 330 ms unlock. The pad fades in once the tooth has seated. A
   restored round only marks .was-picked, so nothing replays. */
body[data-character="temple"] .tooth.just-picked .tooth-sprite {
  animation:
    temple-tooth-catch calc(60ms + var(--catch)) linear both,
    temple-tooth-slam 100ms cubic-bezier(0.55, 0, 0.85, 0.35) calc(60ms + var(--catch)) forwards;
}
body[data-character="temple"] .game-layout:not(.is-still) .tooth.just-picked .tooth-sprite {
  transition: none;
}
body[data-character="temple"] .tooth.just-picked .tooth-pad {
  transition-delay: calc(40ms + var(--seat));
}
@keyframes temple-tooth-catch {
  0% { transform: scaleY(0.92); filter: brightness(1); opacity: 1; }
  30% { transform: scaleY(0.8); }
  55% { transform: scaleY(0.8) rotate(-1.2deg); }
  80% { transform: scaleY(0.8) rotate(1.2deg); }
  100% { transform: scaleY(0.8) rotate(0deg); filter: brightness(1); opacity: 1; }
}
@keyframes temple-tooth-slam {
  0% { transform: scaleY(0.8); filter: brightness(1); opacity: 1; }
  70% { transform: scaleY(0.02); filter: brightness(0.72); opacity: 1; }
  100% { transform: scaleY(0.02); filter: brightness(0.72); opacity: 0; }
}
/* Jaw rattle: as the tooth seats, every other standing tooth rattles in its
   collar, a wave running out from the picked one (--wave: 45 ms per column,
   90 ms more across the mouth), harder with the tension. Symmetric, so no
   tooth is singled out. */
body[data-character="temple"] .is-rattling .tooth:not(.picked, .is-trap) .tooth-sprite {
  animation: temple-tooth-rattle 360ms ease-out calc(var(--seat, 110ms) + var(--wave, 0ms)) both;
}
@keyframes temple-tooth-rattle {
  0% { transform: rotate(0deg); }
  18% { transform: rotate(calc(1.5deg * var(--rattle, 1))); }
  40% { transform: rotate(calc(-1.1deg * var(--rattle, 1))); }
  62% { transform: rotate(calc(0.6deg * var(--rattle, 1))); }
  82% { transform: rotate(calc(-0.25deg * var(--rattle, 1))); }
  100% { transform: rotate(0deg); }
}
/* Round start: the teeth re-arm, rising out of their collars outside in
   (--arm: 0 for the outer teeth, 1 their neighbours, 2 the middle fangs)
   from the pose swap at 90 ms, then the shine runs over them. One
   declaration, so the shine is not overridden. A tooth tapped mid-rise is
   .picked and leaves this rule; its catch takes over. */
body[data-character="temple"] .is-rearming.is-shining .tooth:not(.picked) .tooth-sprite {
  animation:
    temple-tooth-rise 300ms cubic-bezier(0.3, 0.7, 0.4, 1.3) calc(90ms + var(--arm, 0) * 45ms) both,
    temple-tooth-shine 520ms ease-in-out calc(260ms + var(--n, 0) * 55ms) both;
}
@keyframes temple-tooth-rise {
  0% { transform: scaleY(0.02); opacity: 0; }
  20% { opacity: 1; }
  70% { transform: scaleY(1.08); }
  100% { transform: scaleY(1); opacity: 1; }
}
/* After a cash-out the jaws are already open, so there is no pose swap to
   wait for (.is-rearming-open): from the first frame the teeth still
   standing (--rest: 1) sink into their collars like a picked tooth and rise
   again, outside in, with the ones that were down (--rest: 0), which start
   in their collars. Nothing vanishes at once. */
body[data-character="temple"] .is-rearming.is-rearming-open.is-shining .tooth:not(.picked) .tooth-sprite {
  animation:
    temple-tooth-reseat 400ms linear calc(var(--arm, 0) * 45ms) both,
    temple-tooth-shine 520ms ease-in-out calc(260ms + var(--n, 0) * 55ms) both;
}
@keyframes temple-tooth-reseat {
  0% { transform: scaleY(calc(0.02 + 0.98 * var(--rest, 0))); opacity: var(--rest, 0); animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.35); }
  22% { opacity: var(--rest, 0); }
  25% { transform: scaleY(0.02); opacity: 0; animation-timing-function: cubic-bezier(0.3, 0.7, 0.4, 1); }
  40% { opacity: 1; }
  78% { transform: scaleY(1.08); animation-timing-function: ease-in-out; }
  100% { transform: scaleY(1); opacity: 1; }
}

/* ---------- Reactions ---------- */
body[data-character="temple"] .is-opening #character-motion {
  animation: temple-open 380ms cubic-bezier(0.3, 0.7, 0.35, 1) both;
}
body[data-character="temple"] .is-nodding:not(.biting) .character-breathe {
  animation: temple-nod 300ms ease-out;
}
/* The bite: squash at the impact, shake, splash (the head never bobs). */
body[data-character="temple"] .biting .character-breathe {
  animation: temple-chomp 520ms ease-out both;
}
body[data-character="temple"] .biting .temple-contact {
  animation: temple-contact-chomp 520ms ease-out both;
}
body[data-character="temple"] .croc-splash {
  inset: 0;
}
/* Droplets scale with the crocodile and leap from both sides of the jaw, just
   above the rim that hides its base. Each is a drawn teardrop (a pale body,
   a darker rim on its lower right and a white glint; temple-character.js
   writes the SVG), whose tip trails its flight (--side: the left three fly
   left, the right three right); no soft glow. */
body[data-character="temple"] .croc-splash span {
  top: calc(82% - (var(--platform-y) - var(--rim-y)));
  width: calc(var(--croc-w) * 0.026);
  height: calc(var(--croc-w) * 0.044);
  background: none;
  box-shadow: none;
  border-radius: 0;
  --side: -1;
}
body[data-character="temple"] .croc-splash span:nth-child(n + 4) {
  --side: 1;
}
body[data-character="temple"] :is(.croc-splash, .temple-drip, .temple-shard-splash) svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
body[data-character="temple"] .drop-body {
  fill: #cffcf2;
  fill-opacity: 0.92;
}
body[data-character="temple"] .drop-rim {
  fill: none;
  stroke: #5fb3a8;
  stroke-width: 0.9;
  stroke-linecap: round;
}
body[data-character="temple"] .drop-glint {
  fill: #ffffff;
}
/* Flat and Deep: from the sprite's jaw line less the sink, so in the pit they
   leap from the visible chin and fall back behind the rim. */
body[data-isle] .croc-splash span {
  top: calc(82% - var(--isle-sink) * 100%);
}
body[data-character="temple"] .biting .croc-splash span {
  animation: temple-droplet 0.75s 0.12s cubic-bezier(0.2, 0.7, 0.4, 1) both;
}
body[data-character="temple"] .croc-splash span:nth-child(1) { left: 5%; --splash-x: calc(var(--croc-w) * -0.1); --splash-y: calc(var(--croc-w) * -0.12); }
body[data-character="temple"] .croc-splash span:nth-child(2) { left: 12%; --splash-x: calc(var(--croc-w) * -0.06); --splash-y: calc(var(--croc-w) * -0.2); }
body[data-character="temple"] .croc-splash span:nth-child(3) { left: 20%; --splash-x: calc(var(--croc-w) * -0.03); --splash-y: calc(var(--croc-w) * -0.1); }
body[data-character="temple"] .croc-splash span:nth-child(4) { left: 78%; --splash-x: calc(var(--croc-w) * 0.03); --splash-y: calc(var(--croc-w) * -0.1); }
body[data-character="temple"] .croc-splash span:nth-child(5) { left: 86%; --splash-x: calc(var(--croc-w) * 0.06); --splash-y: calc(var(--croc-w) * -0.2); }
body[data-character="temple"] .croc-splash span:nth-child(6) { left: 93%; --splash-x: calc(var(--croc-w) * 0.1); --splash-y: calc(var(--croc-w) * -0.12); }
/* The bite rings the water around the island (scenery layer), with the
   impact (so they never replay when motion returns in the lost state). */
.game-layout:has(#character-wrap.is-impact) .temple-bite-ripples span {
  animation: temple-bite-ripple 0.9s 0.11s ease-out both;
}
.game-layout:has(#character-wrap.is-impact) .temple-bite-ripples span:nth-child(2) {
  animation-delay: 0.26s;
}
/* Cashing out sends one amber ring across the water. */
.temple-win-ripple span {
  border-color: #ffc56b;
  box-shadow: 0 0 8px #ffb24d4d;
}
.game-layout:has(#game-board.won) .temple-win-ripple span {
  animation: temple-win-ripple 600ms 0.08s ease-out both;
}
/* CHOMP! in the head's own carved jade: six letters, each a faceted jade
   gradient clipped to the glyph with a gold carved rim, over the shut lip,
   with a static dark-green depth shadow. z-index 4 (styles.css) keeps it over
   Deep's rim and under the top bar and the panel. Without the bite drama
   (pause, reduced motion) styles.css's chomp pop shows it as before. */
body[data-character="temple"] .snap-word {
  top: 63%;
  font-size: clamp(36px, calc(var(--croc-w) * 0.15), 88px);
  white-space: nowrap;
  color: transparent;
  filter: drop-shadow(0 0.07em 0 #0b2a20);
}
body[data-character="temple"] .snap-word span {
  display: inline-block;
  background: linear-gradient(165deg, #d2f7da 0 30%, #5fbf86 30% 55%, #2d7a55 55% 78%, #174a36 78%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-stroke: 0.06em #e8b54a;
  paint-order: stroke fill;
  --r: -12deg;
}
body[data-character="temple"] .snap-word span:nth-child(odd) {
  --r: 14deg;
}

@keyframes temple-open {
  0% { transform: none; }
  24% { transform: translateY(1.2%) scale(1.035, 0.93); }
  50% { transform: translateY(-1.6%) scale(0.975, 1.045); }
  74% { transform: translateY(0.3%) scale(1.01, 0.99); }
  100% { transform: none; }
}
/* The nod leans toward the picked tooth's column (--lean, -0.7 to 0.7deg
   about the jaw) and tucks the chin deeper for a bottom tooth (--tuck);
   temple-character.js sets both on each safe pick. */
@keyframes temple-nod {
  0%, 100% { transform: none; }
  40% { transform: translateY(var(--tuck, 0.7%)) rotate(var(--lean, 0.5deg)) scale(1.006, 0.99); }
  72% { transform: translateY(-0.25%) rotate(calc(var(--lean, 0.5deg) * -0.3)); }
}
@keyframes temple-chomp {
  0% { transform: none; }
  17% { transform: translateY(-1.2%) scale(0.985, 1.03); }
  22% { transform: scale(1.03, 0.95); }
  36% { transform: translateX(-0.9%) scale(0.99, 1.015); }
  50% { transform: translateX(0.8%) scale(1.008, 0.995); }
  64% { transform: translateX(-0.5%); }
  80% { transform: translateX(0.25%); }
  100% { transform: none; }
}
@keyframes temple-contact-chomp {
  0%, 100% { transform: scale(1); }
  22% { transform: scale(1.08, 1.2); }
}
/* The teardrop's tip (up in the SVG) trails its flight: down and back while
   it rises, level at the top of the arc, up and back as it falls. */
@keyframes temple-droplet {
  0% { opacity: 0; transform: translate(0, 0) rotate(calc(180deg + var(--side, 1) * 30deg)) scale(0.4); }
  15% { opacity: 0.95; }
  55% { opacity: 0.9; transform: translate(calc(var(--splash-x) * 0.7), var(--splash-y)) rotate(calc(180deg + var(--side, 1) * 90deg)) scale(0.95); }
  100% { opacity: 0; transform: translate(var(--splash-x), calc(var(--splash-y) * 0.35)) rotate(calc(180deg + var(--side, 1) * 135deg)) scale(0.7); }
}
@keyframes temple-bite-ripple {
  0% { transform: scale(0.96); opacity: 0; }
  12% { opacity: 0.7; }
  100% { transform: scale(1.45, 1.6); opacity: 0; }
}
@keyframes temple-win-ripple {
  0% { transform: scale(0.95); opacity: 0; }
  18% { opacity: 0.65; }
  100% { transform: scale(1.4, 1.55); opacity: 0; }
}

/* ---------- Tooth-pick reactions ---------- */
/* temple-character.js sets these classes on #character-wrap for a safe
   tooth, only while !still(): .is-counting (the readout's stamp and the next
   value's flip, while the numbers count up), .is-straining or .is-growling
   (300 ms later, on .temple-head), .is-flaring (the nostrils, below) and
   .is-rattling (the teeth, above); .is-on on the pick ring. */

/* Strain and growl: the stone head strains under a high tension, or growls
   (a fast shiver) when the multiplier crosses 2x, 5x, 10x, 25x, 50x or 100x.
   On .temple-head, which nothing else animates, pivoting on the jaw; the
   readout is its sibling, so the number stays steady while the stone shakes.
   Never under the wind-up or the bite. The base never leaves the island: at
   most 0.4 % down and 0.35 % sideways. */
body[data-character="temple"] #character-wrap.is-straining:not(.is-snorting, .biting) .temple-head {
  animation: temple-strain 360ms cubic-bezier(0.3, 0.6, 0.4, 1) both;
}
body[data-character="temple"] #character-wrap.is-straining[data-tension="4"]:not(.is-snorting, .biting) .temple-head {
  animation-duration: 480ms;
}
body[data-character="temple"] #character-wrap.is-growling:not(.is-snorting, .biting) .temple-head {
  animation: temple-growl 300ms linear both;
}
@keyframes temple-strain {
  0% { transform: none; }
  12% { transform: scale(1.004, 0.99); }
  26% { transform: rotate(calc(0.35deg * var(--amp, 1))); }
  40% { transform: rotate(calc(-0.3deg * var(--amp, 1))); }
  55% { transform: rotate(calc(0.22deg * var(--amp, 1))); }
  70% { transform: rotate(calc(-0.14deg * var(--amp, 1))); }
  85% { transform: rotate(calc(0.06deg * var(--amp, 1))); }
  100% { transform: none; }
}
@keyframes temple-growl {
  0% { transform: none; }
  8% { transform: translate(-0.35%, 0.1%); }
  16% { transform: translate(0.35%, 0.2%); }
  24% { transform: translate(-0.3%, 0.3%); }
  32% { transform: translate(0.3%, 0.4%); }
  40% { transform: translate(-0.25%, 0.4%) scale(1.004, 0.994); }
  50% { transform: translate(0.25%, 0.4%); }
  60% { transform: translate(-0.18%, 0.35%); }
  70% { transform: translate(0.12%, 0.25%); }
  85% { transform: translate(0, 0.1%); }
  100% { transform: none; }
}

/* In-mouth readout. The number counts up from the old multiplier over 280 ms
   (temple-character.js), then lands with a stamp: a small squeeze, a
   brighter pop as the count lands (61 % of 460 ms), and back. The next-tooth
   value flips up into place (the caption stays). A cash-out stamps the gold
   number and counts the cashed-out amount up from $0.00. Nothing grows past
   1.1x, so it all stays inside the tooth-free band. The stamp is later than
   the throat rise below at the same specificity, so a tooth picked during
   the opening still lands its stamp. */
body[data-character="temple"] .is-opening .temple-readout #current-multiplier {
  animation: temple-readout-born 310ms cubic-bezier(0.2, 0.8, 0.3, 1.2) 90ms both;
}
body[data-character="temple"] .is-opening .temple-readout .next-multiplier {
  animation: temple-next-in 200ms 180ms both;
}
body[data-character="temple"] .is-counting .temple-readout #current-multiplier {
  animation: temple-readout-stamp 460ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
body[data-character="temple"] .is-counting .temple-readout #next-multiplier {
  animation: temple-next-in 220ms cubic-bezier(0.2, 0.8, 0.3, 1) 80ms both;
}
@keyframes temple-readout-stamp {
  0% { transform: scale(1); filter: none; }
  55% { transform: scale(0.97); filter: brightness(1); }
  61% { transform: scale(1.07); filter: brightness(1.28); }
  80% { transform: scale(0.99); }
  100% { transform: scale(1); filter: none; }
}
@keyframes temple-next-in {
  0% { opacity: 0; transform: translateY(0.55em); }
  100% { opacity: 1; transform: none; }
}
/* Round start: the number rises out of the throat as the jaws open. Its
   backwards fill hides the old number over the first 90 ms, exactly while
   the readout moves from above the shut head into the mouth. */
@keyframes temple-readout-born {
  0% { opacity: 0; transform: translateY(18%) scale(0.6); }
  60% { opacity: 1; transform: translateY(0) scale(1.08); }
  100% { opacity: 1; transform: none; }
}

/* Pick tremor ring: each safe tooth sends one faint ring across the water
   (fainter and quicker than the bite's), wider at tension 3-4, where a
   second ring follows. It shares the event rings' box, so every island's
   ring size carries over. Scenery, so the pause freezes it on its invisible
   first frame and reduced motion (styles.css) stops it. */
.temple-pick-ripples.is-on span:first-child {
  animation: temple-pick-ring 700ms ease-out both;
}
.game-layout:has(#character-wrap[data-tension="3"]) .temple-pick-ripples {
  --ring-o: 0.45;
  --ring-s: 1.25;
}
.game-layout:has(#character-wrap[data-tension="4"]) .temple-pick-ripples {
  --ring-o: 0.55;
  --ring-s: 1.3;
}
.game-layout:has(#character-wrap:is([data-tension="3"], [data-tension="4"])) .temple-pick-ripples.is-on span:nth-child(2) {
  animation: temple-pick-ring 700ms ease-out 140ms both;
}
/* The ring starts at the island's outline (--ring-s0), where the island
   mask lets it show, and peaks once it is out on the open water, so a tier-1
   ring is seen too. */
@keyframes temple-pick-ring {
  0% { transform: scale(calc(var(--ring-s0, 1.05) * var(--ring-k, 1)), calc((var(--ring-s0, 1.05) + 0.03) * var(--ring-k, 1))); opacity: 0; }
  30% { opacity: var(--ring-o, 0.3); }
  100% { transform: scale(calc(var(--ring-s, 1.16) * var(--ring-k, 1)), calc((var(--ring-s, 1.16) + 0.05) * var(--ring-k, 1))); opacity: 0; }
}
/* Flat's and Deep's island sprites are about 8 % wider than /temple/'s
   (950 against 879 px at 1440 x 900), so their ring grows by as much to
   clear them. In portrait the ring's box is wider than the screen and its
   near arc is under the bet panel, so it would never be seen: none. */
body[data-isle] .temple-pick-ripples {
  --ring-k: 1.085;
}
@media (orientation: portrait) {
  .temple-pick-ripples {
    display: none;
  }
}

/* ---------- Temper: steam, the snort before a bite, coins on a cash-out ---------- */
/* Every effect sizes with the head (--croc-w) and only animates transform and
   opacity. temple-character.js sets the classes: .is-pushing with data-push
   (1-4) on a safe tooth, .is-snorting for the wind-up game.js waits for
   before a bite, .is-blasting as the jaws shut, .is-cashing on a cash-out,
   .is-exhaling for an idle puff and .just-picked on a safe tooth. */

/* Steam: rendered puffs of steam from the nostrils that spin, swell and thin
   out as they drift up and away from the centre line. The layer is in front of the
   head and never takes a pointer event. */
.temple-steam,
.temple-coins {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* The coin layer (about 250 nodes) is out of the layout until a cash-out,
   and fades out over 150 ms when a new round starts while coins still fly. */
.temple-coins {
  display: none;
}
.is-cashing .temple-coins {
  display: block;
}
.is-cash-fading .temple-coins {
  opacity: 0;
  transition: opacity 150ms ease-out;
}
.temple-nostril {
  position: absolute;
  left: var(--open-x);
  top: var(--open-y);
}
body[data-character="temple"] .game-board.lost .temple-nostril,
body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose .temple-nostril {
  left: var(--shut-x);
  top: var(--shut-y);
}
/* A bite holds the open jaws for 110 ms: the steam moves to the shut
   nostrils only as they shut, so a snort still in the air never sits in the
   open mouth over the teeth. */
body[data-character="temple"] .game-board.lost .temple-steam .temple-nostril {
  transition: left 0s 110ms, top 0s 110ms;
}
.temple-nostril span {
  --o: 0.85;
  position: absolute;
  left: 0;
  top: 0;
  width: calc(var(--croc-w) * 0.13);
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  background: url("/assets/temple-smoke-1.webp") center / contain no-repeat;
}
/* Three steam sprites (scripts/make-temple-smoke.py), each turned its own way. */
.temple-nostril span:nth-child(3n + 2) {
  --r0: 130deg;
  background-image: url("/assets/temple-smoke-2.webp");
}
.temple-nostril span:nth-child(3n) {
  --r0: 250deg;
  background-image: url("/assets/temple-smoke-3.webp");
}
/* One strong push per safe tooth: both nostrils shoot a burst of puffs out
   and up at once, fast at first and braking hard, and the steam thins out
   within a second. temple-character.js sets data-push from the multiplier
   the pick reached: 1 under 1.5x (four puffs per nostril), 2 under 2.5x
   (five), 3 under 5x (six), 4 from 5x (six); each level drives the puffs
   farther (--push-far), larger (--push-big) and denser (--push-o). Nothing
   rises between picks. */
.temple-push {
  --far: var(--push-far, 1);
  --big: var(--push-big, 1);
}
.is-pushing .temple-push {
  --o: var(--push-o, 0.6);
  animation: temple-puff var(--push-t, 760ms) cubic-bezier(0.04, 0.9, 0.25, 1) var(--d) both;
}
[data-push="2"] { --push-far: 1.15; --push-big: 1.1; --push-o: 0.68; --push-t: 820ms; }
[data-push="3"] { --push-far: 1.3; --push-big: 1.2; --push-o: 0.76; --push-t: 880ms; }
[data-push="4"] { --push-far: 1.45; --push-big: 1.32; --push-o: 0.85; --push-t: 940ms; }
[data-push="1"] .temple-push:is([data-level="2"], [data-level="3"]),
[data-push="2"] .temple-push[data-level="3"] {
  animation: none;
}
.is-snorting .temple-snort {
  --o: 0.95;
  animation: temple-puff 640ms cubic-bezier(0.08, 0.8, 0.3, 1) var(--d) both;
}
.is-blasting .temple-jet {
  --o: 1;
  animation: temple-puff 760ms cubic-bezier(0.05, 0.8, 0.3, 1) calc(110ms + var(--d)) both;
}
.is-cashing .temple-sigh {
  --o: 0.42;
  animation: temple-puff 1.7s cubic-bezier(0.2, 0.6, 0.35, 1) calc(620ms + var(--d)) both;
}
/* A lazy idle exhale from the shut snout. */
.is-exhaling .temple-sigh {
  --o: 0.6;
  animation: temple-puff 1.8s cubic-bezier(0.2, 0.6, 0.35, 1) var(--d) both;
}
@keyframes temple-puff {
  /* A puff starts tiny inside the nostril and shows at once, so the steam
     comes out of the hole rather than appearing above it. */
  0% {
    opacity: 0;
    transform: translate(0, 0) scale(0.12) rotate(var(--r0, 0deg));
  }
  /* The movement eases out over the whole puff; the fade has its own curve,
     so a puff stays dense for most of its rise. */
  6% {
    opacity: var(--o);
    animation-timing-function: cubic-bezier(0.45, 0, 0.8, 0.6);
  }
  /* A push goes --far times as far and grows --big times as large. */
  100% {
    opacity: 0;
    transform: translate(calc(var(--side) * var(--dx) * var(--far, 1) * var(--croc-w)), calc(var(--dy) * var(--far, 1) * var(--croc-w))) scale(calc(var(--s) * var(--big, 1))) rotate(calc(var(--r0, 0deg) + var(--side) * 55deg));
  }
}

/* Nostril flare: each pose carries a copy of its own nostrils, masked to the
   holes grown by 12 px with a feathered edge (.temple-flare, built by
   temple-character.js), so at scale 1 it is the painting itself. With a
   push, a snort, the jet, an exhale or the sigh it shows and swells about
   the hole for 260 ms, darker inside; a hard flare (the jet) swells further.
   Only the visible pose's copy shows. The ember rims are a thin amber line
   along each open hole's lower edges, a state while a round plays: dark at
   tension 1, then 0.25, 0.45 and 0.7, flashing hotter as the nostrils flare.
   Amber only, never red, never near the eyes. */
.temple-flare,
.temple-ember {
  position: absolute;
  overflow: visible;
  pointer-events: none;
  transform-origin: 50% 50%;
}
.temple-flare {
  opacity: 0;
}
.temple-ember {
  opacity: var(--ember-o, 0);
}
body[data-character="temple"] #character-wrap[data-tension="2"] {
  --ember-o: 0.25;
  --ember-hot: 0.6;
}
body[data-character="temple"] #character-wrap[data-tension="3"] {
  --ember-o: 0.45;
  --ember-hot: 0.85;
}
body[data-character="temple"] #character-wrap[data-tension="4"] {
  --ember-o: 0.7;
  --ember-hot: 1;
}
.is-flaring-hard {
  --flare-x: 1.22;
  --flare-y: 1.14;
}
:is(.is-flaring, .is-flaring-hard) .temple-flare {
  opacity: 1;
  animation: temple-flare 260ms cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
:is(.is-flaring, .is-flaring-hard) .temple-ember {
  animation: temple-ember 260ms cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
@keyframes temple-flare {
  0% { transform: scale(1); }
  30% { transform: scale(var(--flare-x, 1.16), var(--flare-y, 1.1)); }
  100% { transform: scale(1); }
}
@keyframes temple-ember {
  0% { transform: scale(1); opacity: var(--ember-o, 0); }
  30% { transform: scale(var(--flare-x, 1.16), var(--flare-y, 1.1)); opacity: var(--ember-hot, 0); }
  100% { transform: scale(1); opacity: var(--ember-o, 0); }
}

/* Wind-up: the head draws a breath (rises and swells), trembles with a growl,
   then drops into the snap. No tooth takes a pointer during it. */
body[data-character="temple"] .is-snorting #character-motion {
  animation: temple-windup 420ms both;
}
body[data-character="temple"] .is-snorting .tooth {
  pointer-events: none;
}
@keyframes temple-windup {
  0% { transform: translate(0, 0) scale(1, 1); animation-timing-function: cubic-bezier(0.3, 0.7, 0.4, 1); }
  30% { transform: translate(0, -1.3%) scale(1.012, 1.03); }
  42% { transform: translate(-0.35%, -1.5%) scale(1.014, 1.034); }
  54% { transform: translate(0.35%, -1.45%) scale(1.014, 1.034); }
  66% { transform: translate(-0.3%, -1.5%) scale(1.014, 1.034); }
  78% { transform: translate(0.2%, -1.4%) scale(1.012, 1.032); animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.5); }
  100% { transform: translate(0, 0) scale(1, 1); }
}
/* The bite tooth sinks part way, rattles and dims while the crocodile
   snorts; its cracks (below) are the tell, so it has no glow. */
body[data-character="temple"] .tooth.is-trap .tooth-sprite {
  animation: temple-trap-tooth 420ms cubic-bezier(0.3, 0.7, 0.4, 1) both;
}
@keyframes temple-trap-tooth {
  0% { transform: scaleY(1) rotate(0deg); filter: brightness(1); }
  24% { transform: scaleY(0.78) rotate(0deg); filter: brightness(0.85); }
  42% { transform: scaleY(0.8) rotate(-2.5deg); filter: brightness(0.9); }
  58% { transform: scaleY(0.8) rotate(2.5deg); }
  74% { transform: scaleY(0.8) rotate(-1.5deg); }
  100% { transform: scaleY(0.8) rotate(0deg); filter: brightness(0.9); }
}
/* A tooth under the pointer wobbles in its collar, pivoting on its root; not
   while the teeth re-arm at a round start (.is-rearming), so a hovered tooth
   rises with the others. */
@media (hover: hover) {
  body[data-character="temple"] .game-board.playing .tooth:enabled:not(.picked, .is-trap, .is-rearming *):hover .tooth-sprite {
    animation: temple-tooth-wobble 520ms ease-in-out;
  }
}
@keyframes temple-tooth-wobble {
  0%, 100% { transform: rotate(0deg); }
  20% { transform: rotate(3deg); }
  45% { transform: rotate(-2.4deg); }
  68% { transform: rotate(1.3deg); }
  86% { transform: rotate(-0.5deg); }
}
/* Press shiver: a pressed tooth (pointer down, before the click) gives a
   little in its collar and shivers instead of styles.css's 0.75 squash; it
   ends on the 0.92 the stone catch starts from, so press and catch read as
   one motion. Later than the wobble at the same specificity, so it wins
   while pressed. */
body[data-character="temple"] .game-board.playing .tooth:enabled:not(.picked, .is-trap):active .tooth-sprite {
  transform: scaleY(0.92);
  animation: temple-tooth-shiver 180ms linear;
}
@keyframes temple-tooth-shiver {
  0% { transform: scaleY(1) rotate(0deg); }
  25% { transform: scaleY(0.9) rotate(-2deg); }
  50% { transform: scaleY(0.9) rotate(2deg); }
  75% { transform: scaleY(0.91) rotate(-1deg); }
  100% { transform: scaleY(0.92) rotate(0deg); }
}

/* Cash-out: three waves of gold coins burst out of the mouth, tumble and spin
   (the face darkens edge-on and glints), land about a third of the head below
   the mouth and bounce once; the rim hides the ones that land on the island.
   Horizontal travel is on the coin, the rise, fall and tumble on its inner
   element, the spin on the face. Nine collectors fly on into the wallet
   (--tx / --ty, measured by temple-character.js). */
.temple-coin {
  position: absolute;
  left: 50%;
  top: 58%;
  width: calc(var(--croc-w) * 0.064 * var(--s));
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
}
.temple-coin i,
.temple-coin b {
  display: block;
  width: 100%;
  height: 100%;
}
.temple-coin b {
  position: relative;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, #fffbe0 0 7%, #fffbe000 24%),
    radial-gradient(circle, #ffd95e 0 48%, #c98a1c 51% 57%, #ffd24f 60% 84%, #a86a12 89% 100%);
  box-shadow: 0 0 calc(var(--croc-w) * 0.014) #ffc14db3;
}
.temple-coin b::before,
.temple-coin b::after {
  content: "";
  position: absolute;
  opacity: 0;
}
/* Edge-on shading, in step with the spin. */
.temple-coin b::before {
  inset: 0;
  border-radius: 50%;
  background: #6b3f08;
}
/* A glint that flashes across the face. */
.temple-coin b::after {
  left: 8%;
  top: 4%;
  width: 60%;
  aspect-ratio: 1;
  background:
    radial-gradient(closest-side, #fff 0, #fff0 100%) 50% 50% / 100% 18% no-repeat,
    radial-gradient(closest-side, #fff 0, #fff0 100%) 50% 50% / 18% 100% no-repeat;
}
.is-cashing .temple-coin {
  animation: temple-coin-x var(--t) linear var(--d) both;
}
.is-cashing .temple-coin i {
  animation: temple-coin-y var(--t) var(--d) both;
}
.is-cashing .temple-coin b {
  animation: temple-coin-spin var(--spin) linear infinite;
}
.is-cashing .temple-coin b::before {
  animation: temple-coin-shade var(--spin) linear infinite;
}
.is-cashing .temple-coin b::after {
  animation: temple-coin-glint 900ms ease-out calc(var(--d) + 300ms) infinite;
}
/* Collectors leave from the mouth corner on the wallet's side (--wside, set
   by temple-character.js with --tx / --ty from that corner). */
.temple-collector {
  left: calc(50% + var(--wside, -1) * 41%);
  top: 57%;
}
.is-cashing .temple-collector {
  animation: temple-collect-x var(--collect, 950ms) var(--d) both;
}
.is-cashing .temple-collector i {
  animation: temple-collect-y var(--collect, 950ms) var(--d) both;
}
@keyframes temple-coin-x {
  0% { opacity: 0; transform: translateX(0); }
  5% { opacity: 1; }
  78% { transform: translateX(calc(var(--dx) * var(--croc-w) * 0.93)); }
  86% { opacity: 1; }
  100% { opacity: 0; transform: translateX(calc(var(--dx) * var(--croc-w))); }
}
@keyframes temple-coin-y {
  0% { transform: translateY(0) scale(0.35) rotate(0deg); animation-timing-function: cubic-bezier(0.15, 0.7, 0.35, 1); }
  36% { transform: translateY(calc(var(--up) * var(--croc-w) * -1)) scale(1.05) rotate(calc(var(--tumble) * 0.4)); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5); }
  78% { transform: translateY(calc(var(--land) * var(--croc-w))) scale(0.95) rotate(var(--tumble)); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  88% { transform: translateY(calc((var(--land) - 0.04) * var(--croc-w))) scale(0.95) rotate(calc(var(--tumble) + 20deg)); animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.5); }
  100% { transform: translateY(calc(var(--land) * var(--croc-w))) scale(0.9) rotate(calc(var(--tumble) + 30deg)); }
}
@keyframes temple-coin-spin {
  0%, 100% { transform: scaleX(1); }
  50% { transform: scaleX(0.12); }
}
@keyframes temple-coin-shade {
  0%, 100% { opacity: 0; }
  50% { opacity: 0.5; }
}
@keyframes temple-coin-glint {
  0%, 60%, 100% { opacity: 0; transform: scale(0.3) rotate(0deg); }
  75% { opacity: 1; transform: scale(1) rotate(45deg); }
}
/* Up with the burst, a swing to one side, then a swoop into the wallet. */
@keyframes temple-collect-x {
  0% { opacity: 0; transform: translateX(0); }
  6% { opacity: 1; }
  32% { transform: translateX(calc(var(--wside, -1) * var(--ox) * var(--croc-w))); animation-timing-function: cubic-bezier(0.5, 0, 0.3, 1); }
  93% { opacity: 1; }
  100% { opacity: 0; transform: translateX(var(--tx, 0px)); }
}
@keyframes temple-collect-y {
  0% { transform: translateY(0) scale(0.4); animation-timing-function: cubic-bezier(0.15, 0.7, 0.35, 1); }
  32% { transform: translateY(calc(var(--up) * var(--croc-w) * -1)) scale(1.1); animation-timing-function: cubic-bezier(0.45, 0, 0.7, 0.4); }
  100% { transform: translateY(var(--ty, -300px)) scale(0.55); }
}
.temple-sparkle {
  position: absolute;
  width: calc(var(--croc-w) * 0.11 * var(--s));
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  background: radial-gradient(closest-side, #fff 0, #fff8d6 12%, #ffd76a80 26%, #ffd76a00 58%);
}
.temple-sparkle::before,
.temple-sparkle::after {
  content: "";
  position: absolute;
  inset: 46.5% 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, #fff 0, #fff4c8 30%, #ffe9a000 100%);
}
.temple-sparkle::after {
  inset: 0 46.5%;
}
.is-cashing .temple-sparkle {
  animation: temple-sparkle 720ms ease-out var(--d) both;
}
@keyframes temple-sparkle {
  0% { opacity: 0; transform: scale(0.2) rotate(0deg); }
  35% { opacity: 1; transform: scale(1) rotate(25deg); }
  100% { opacity: 0; transform: scale(0.5) rotate(60deg); }
}
/* Golden rays fan out behind the head and turn slowly as they fade. */
.temple-rays {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 200%;
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  pointer-events: none;
  /* Twelve soft rays. */
  background: conic-gradient(
    #fff0bf00 0deg, #fff0bf 9deg 13deg, #fff0bf00 22deg 30deg,
    #fff0bf00 30deg, #fff0bf 39deg 43deg, #fff0bf00 52deg 60deg,
    #fff0bf00 60deg, #fff0bf 69deg 73deg, #fff0bf00 82deg 90deg,
    #fff0bf00 90deg, #fff0bf 99deg 103deg, #fff0bf00 112deg 120deg,
    #fff0bf00 120deg, #fff0bf 129deg 133deg, #fff0bf00 142deg 150deg,
    #fff0bf00 150deg, #fff0bf 159deg 163deg, #fff0bf00 172deg 180deg,
    #fff0bf00 180deg, #fff0bf 189deg 193deg, #fff0bf00 202deg 210deg,
    #fff0bf00 210deg, #fff0bf 219deg 223deg, #fff0bf00 232deg 240deg,
    #fff0bf00 240deg, #fff0bf 249deg 253deg, #fff0bf00 262deg 270deg,
    #fff0bf00 270deg, #fff0bf 279deg 283deg, #fff0bf00 292deg 300deg,
    #fff0bf00 300deg, #fff0bf 309deg 313deg, #fff0bf00 322deg 330deg,
    #fff0bf00 330deg, #fff0bf 339deg 343deg, #fff0bf00 352deg 360deg
  );
  -webkit-mask-image: radial-gradient(closest-side, #000 30%, #000b 56%, transparent 82%);
  mask-image: radial-gradient(closest-side, #000 30%, #000b 56%, transparent 82%);
  mix-blend-mode: screen;
}
.is-cashing .temple-rays {
  animation: temple-rays 2s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
@keyframes temple-rays {
  0% { opacity: 0; transform: scale(0.55) rotate(0deg); }
  16% { opacity: 0.9; }
  55% { opacity: 0.7; }
  100% { opacity: 0; transform: scale(1.15) rotate(35deg); }
}
/* The wallet glows and swells as the coins land, and the win floats up into it. */
body[data-character="temple"] .wallet {
  position: relative;
}
body[data-character="temple"] .wallet.is-collecting {
  animation: temple-wallet-tick 75ms ease-out 60ms 9, temple-wallet-glow 1.1s ease-out;
}
body[data-character="temple"] .wallet.is-collecting strong {
  animation: temple-wallet-amount 1.1s ease-out;
}
.temple-gain {
  position: absolute;
  right: 14px;
  top: calc(100% + 4px);
  font-family: "Fredoka", sans-serif;
  font-size: 18px;
  font-weight: 700;
  white-space: nowrap;
  color: #ffd95e;
  -webkit-text-stroke: 0.14em #5a3a0e;
  paint-order: stroke fill;
  opacity: 0;
  pointer-events: none;
}
body[data-character="temple"] .wallet.is-collecting .temple-gain {
  animation: temple-gain 1.4s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
/* One small tick as each collector lands (they land 75 ms apart). */
@keyframes temple-wallet-tick {
  0%, 100% { transform: none; }
  35% { transform: scale(1.03) translateY(1px); }
}
@keyframes temple-wallet-glow {
  0%, 100% { box-shadow: 0 3px 0 #31794715, 0 0 0 0 #ffc94d00; }
  18% { box-shadow: 0 3px 0 #31794715, 0 0 0 5px #ffc94d8c; }
  45% { box-shadow: 0 3px 0 #31794715, 0 0 18px 4px #ffc94d59; }
}
@keyframes temple-wallet-amount {
  0%, 100% { color: inherit; }
  20%, 60% { color: #b7780f; }
}
@keyframes temple-gain {
  0% { opacity: 0; transform: translateY(14px) scale(0.7); }
  20% { opacity: 1; transform: translateY(0) scale(1.08); }
  70% { opacity: 1; transform: translateY(-2px) scale(1); }
  100% { opacity: 0; transform: translateY(-10px) scale(0.95); }
}

/* A safe tooth throws a small gold spark from its socket: a thin ring and a
   four-point star with hard edges (an inline SVG from temple-character.js),
   no glow; the socket seat draws the gold check under it (Batch 4). The
   readout's count and stamp are under Readout reactions. */
.tooth-spark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 95%;
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  pointer-events: none;
}
.tooth-spark svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
body[data-character="temple"] .tooth.just-picked .tooth-spark {
  animation: temple-tooth-spark 600ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
@keyframes temple-tooth-spark {
  0% { opacity: 0; transform: scale(0.4) rotate(0deg); }
  25% { opacity: 0.8; }
  100% { opacity: 0; transform: scale(1.05) rotate(30deg); }
}

/* A new round: a shine runs along each row of teeth, left to right, as the
   jaws open. Each tooth brightens a little while two slanted ivory stripes
   with hard edges (.tooth-shine, inside the tooth's own clip) sweep across
   it from left to right; no glow around the tooth. At rest the stripes wait
   beside the tooth, outside its clip, and are hidden. */
body[data-character="temple"] .is-shining .tooth:not(.picked) .tooth-sprite {
  animation: temple-tooth-shine 520ms ease-in-out calc(140ms + var(--n) * 55ms) both;
}
@keyframes temple-tooth-shine {
  0%, 100% { filter: brightness(1); }
  45% { filter: brightness(1.16); }
}
.tooth-shine {
  opacity: 0;
  transform-box: fill-box;
  pointer-events: none;
}
body[data-character="temple"] .is-shining .tooth:not(.picked) .tooth-shine {
  animation: temple-tooth-band 520ms cubic-bezier(0.45, 0.05, 0.55, 0.95) calc(var(--shine-at, 140ms) + var(--n, 0) * 55ms) both;
}
body[data-character="temple"] .is-rearming.is-shining .tooth:not(.picked) .tooth-shine {
  --shine-at: 260ms;
}
@keyframes temple-tooth-band {
  0% { opacity: 1; transform: translateX(0); }
  100% { opacity: 1; transform: translateX(200%); }
}

/* ---------- Bite drama ---------- */
/* temple-character.js drives a bite, only while !still(). The wind-up
   (beforeBite, the 420 ms game.js waits before revealing the bite) adds
   .is-bracing (1100 ms) and .is-cracking; the reveal (enter("lost")) adds
   .is-impact and .is-bitten for the whole lost state, .is-jolted on the
   layout at 110 ms (320 ms), .is-chewing at 700 ms (1100 ms) and .is-huffing
   at 1300 ms and then every 7-11 s (700 ms). Times below are from the reveal
   unless they say otherwise; the jaws shut at 110 ms. Every animation ends
   on its rest state (invisible or none), except the cracks and the cowering
   number, which hold their end only while their class is on and never start
   when still. Nothing here is soft: shaped SVG, clip-path polygons and
   hard-stop gradients. Turning still removes .is-impact (and every transient
   class); .is-bitten then keeps the lost state's rest look, so nothing
   replays when motion returns. */

/* The world thumps: as the jaws shut, the whole scene lurches toward the
   crocodile and settles in a few decaying shakes. The near layer (the
   island, the head, the rim and the teeth, all in .character-space) moves
   more than the far one (the scenery). Both boxes are the layout's, so one
   origin, the jaw, serves both; the scale always grows more than the offset,
   so no edge shows. The top bar, the game board (pause button) and the bet
   panel never move. */
.game-layout:has(#character-wrap.is-impact) .jungle-background {
  transform-origin: var(--platform-x) var(--platform-y);
  animation: temple-thump-far 450ms ease-out 110ms both;
}
.game-layout:has(#character-wrap.is-impact) .character-space {
  transform-origin: var(--platform-x) var(--platform-y);
  animation: temple-thump-near 450ms ease-out 110ms both;
}
@keyframes temple-thump-near {
  0% { transform: none; animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1); }
  15% { transform: translateY(calc(var(--croc-w) * 0.006)) scale(1.03); }
  32% { transform: translateY(calc(var(--croc-w) * -0.003)) scale(1.022); }
  48% { transform: translateX(calc(var(--croc-w) * 0.004)) scale(1.014); }
  64% { transform: translateX(calc(var(--croc-w) * -0.0025)) scale(1.008); }
  80% { transform: translateX(calc(var(--croc-w) * 0.001)) scale(1.003); }
  100% { transform: none; }
}
@keyframes temple-thump-far {
  0% { transform: none; animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1); }
  15% { transform: translateY(calc(var(--croc-w) * 0.0036)) scale(1.018); }
  32% { transform: translateY(calc(var(--croc-w) * -0.0018)) scale(1.013); }
  48% { transform: translateX(calc(var(--croc-w) * 0.0024)) scale(1.008); }
  64% { transform: translateX(calc(var(--croc-w) * -0.0015)) scale(1.005); }
  80% { transform: translateX(calc(var(--croc-w) * 0.0006)) scale(1.002); }
  100% { transform: none; }
}

/* The fireflies flinch: the swarm jumps out from the island and dims, then
   drifts back (only the container moves; each speck keeps its own drift and
   pulse). Scenery, so the pause freezes it and reduced motion removes it. */
.game-layout:has(#character-wrap.is-impact) .temple-fireflies {
  transform-origin: 49.9% 67.4%;
  animation: temple-swarm-flinch 2s 110ms both;
}
@media (orientation: portrait) {
  .game-layout:has(#character-wrap.is-impact) .temple-fireflies {
    transform-origin: 50% 61.3%;
  }
}
@keyframes temple-swarm-flinch {
  0% { transform: none; opacity: 1; }
  6% { transform: scale(1.06); opacity: 0.25; animation-timing-function: ease-out; }
  100% { transform: none; opacity: 1; }
}

/* The panel jolts with the thump (never the glass panel itself, whose
   backdrop would re-sample the scene every frame): the controls drop 3 px
   and bounce back, and the quick chips rattle left to right. */
body[data-character="temple"] .game-layout.is-jolted .bet-controls {
  animation: temple-jolt 240ms cubic-bezier(0.3, 0.7, 0.4, 1);
}
body[data-character="temple"] .game-layout.is-jolted .quick-bets button {
  animation: temple-chip-rattle 200ms calc(var(--q, 0) * 20ms);
}
body[data-character="temple"] .quick-bets button:nth-child(2) { --q: 1; }
body[data-character="temple"] .quick-bets button:nth-child(3) { --q: 2; }
body[data-character="temple"] .quick-bets button:nth-child(4) { --q: 3; }
body[data-character="temple"] .quick-bets button:nth-child(5) { --q: 4; }
@keyframes temple-jolt {
  0% { transform: none; }
  30% { transform: translateY(3px); }
  60% { transform: translateY(-1px); }
  100% { transform: none; }
}
@keyframes temple-chip-rattle {
  0% { transform: none; }
  35% { transform: rotate(-2deg); }
  70% { transform: rotate(1.5deg); }
  100% { transform: none; }
}

/* The trap tooth cracks while the crocodile winds up: three cracks (a dark
   groove with a thin gold seam, traced per tooth by temple-character.js
   inside the tooth's clip) spring open at 90, 200 and 310 ms from the click,
   sinking and rattling with the tooth. The tooth keeps .is-trap until the
   next round, so it stays sunk until the jaws have shut over it. */
.tooth-crack path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transform-box: view-box;
  opacity: 0;
}
.tooth-crack .crack-groove {
  stroke: #2a1a0a;
  stroke-width: 1.6px;
}
.tooth-crack .crack-seam {
  stroke: #ffc56b;
  stroke-width: 0.7px;
}
body[data-character="temple"] .is-cracking .tooth.is-trap .tooth-crack path {
  animation: temple-crack 80ms ease-out 90ms both;
}
body[data-character="temple"] .is-cracking .tooth.is-trap .tooth-crack path:nth-of-type(n + 3) {
  animation-delay: 200ms;
}
body[data-character="temple"] .is-cracking .tooth.is-trap .tooth-crack path:nth-of-type(n + 5) {
  animation-delay: 310ms;
}
@keyframes temple-crack {
  0% { opacity: 0; transform: scale(0.3); }
  100% { opacity: 1; transform: scale(1); }
}

/* The number cowers through the wind-up (from the click): it shrinks,
   drains to cold wet stone and rattles with the growl, never red. A small
   box, so the filter is cheap; the heat shadow is on .multiplier-readout. */
body[data-character="temple"] .is-bracing .temple-readout .scoreboard {
  animation: temple-readout-dread 420ms both;
}
@keyframes temple-readout-dread {
  0% { transform: none; filter: none; opacity: 1; }
  28% { transform: scale(0.93) translateY(0.02em); filter: saturate(0.35) brightness(0.85); opacity: 0.85; }
  42% { transform: scale(0.93) translate(-1px, 0.02em); }
  54% { transform: scale(0.93) translate(1px, 0.02em); }
  66% { transform: scale(0.93) translate(-1px, 0.02em); }
  78% { transform: scale(0.93) translate(0.6px, 0.02em); }
  100% { transform: scale(0.93) translateY(0.02em); filter: saturate(0.35) brightness(0.85); opacity: 0.8; }
}

/* ...then gets chomped. The real readout hides at the reveal and a copy of
   the number it showed (.temple-crushed, placed where the number stood)
   takes over: the closing jaws squash it (0-110 ms), it splits along its
   middle and the halves are spat out up-left and down-right, spinning and
   fading, while six flakes spray from the split. It rides the chomp. */
body[data-character="temple"] #character-wrap.is-impact .temple-readout,
body[data-character="temple"] #character-wrap.is-impact .temple-readout * {
  visibility: hidden;
  transition: none;
}
.temple-crushed {
  position: absolute;
  left: 50%;
  top: 50.8%;
  translate: -50% -50%;
  z-index: 3;
  display: none;
  font-family: "Fredoka", sans-serif;
  font-size: var(--mouth-value);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* The cowering number's drained stone (ivory at saturate 0.35,
     brightness 0.85 and opacity 0.8 over the throat), so it does not
     brighten at the reveal. */
  color: #aaa89c;
  text-shadow: 0 0 0.24em #010b09d9, 0 0.03em 0.08em #010b09;
  pointer-events: none;
}
body[data-character="temple"] #character-wrap.is-impact .temple-crushed {
  display: block;
}
.temple-crushed i {
  display: block;
  font-style: normal;
  transform-origin: 50% 50%;
}
.temple-crushed i:first-child {
  clip-path: inset(0 0 50% 0);
}
.temple-crushed i + i {
  position: absolute;
  left: 0;
  top: 0;
  clip-path: inset(50% 0 0 0);
}
.temple-crushed span {
  font-size: 0.64em;
  margin-left: 2px;
}
.temple-crushed b {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--croc-w) * 0.008);
  aspect-ratio: 1;
  background: #c9c6b8;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  opacity: 0;
}
.is-impact .temple-crushed i:first-child {
  animation: temple-crush-top 265ms both;
}
.is-impact .temple-crushed i + i {
  animation: temple-crush-bottom 265ms both;
}
.is-impact .temple-crushed b {
  animation: temple-crush-flake 300ms ease-out 110ms both;
}
/* The halves squash together in place as the jaws meet (110 ms) and are
   gone 150 ms later: CHOMP! is the only text at the impact, and nothing
   flies up into the steam over the nostrils. */
@keyframes temple-crush-top {
  0% { transform: translateY(0.02em) scale(0.93); animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.5); }
  41.5% { transform: translateY(12%) scale(0.93, 0.35); opacity: 1; animation-timing-function: ease-out; }
  100% { transform: translateY(14%) scale(1.02, 0.12); opacity: 0; }
}
@keyframes temple-crush-bottom {
  0% { transform: translateY(0.02em) scale(0.93); animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.5); }
  41.5% { transform: translateY(-12%) scale(0.93, 0.35); opacity: 1; animation-timing-function: ease-out; }
  100% { transform: translateY(-14%) scale(1.02, 0.12); opacity: 0; }
}
@keyframes temple-crush-flake {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--fx) * var(--croc-w)), calc(-50% + var(--fy) * var(--croc-w))) rotate(90deg) scale(0.8); }
}

/* CHOMP! slams in letter by letter as the jaws shut (squash and settle), a
   gold crack runs through the word at 780 ms and the letters fall apart and
   vanish from 880 ms. */
body[data-character="temple"] #character-wrap.is-impact .snap-word {
  animation: none;
  opacity: 1;
  transform: translate(-50%, -50%) rotate(-6deg);
}
body[data-character="temple"] #character-wrap.is-impact .snap-word span {
  animation:
    temple-letter-slam 260ms cubic-bezier(0.3, 0.7, 0.4, 1.4) calc(110ms + var(--i) * 28ms) both,
    temple-letter-fall 300ms cubic-bezier(0.5, 0, 0.9, 0.5) calc(880ms + var(--i) * 20ms) forwards;
}
/* After the drama (or once turning still has ended it) the word is gone. */
body[data-character="temple"] #character-wrap.is-bitten:not(.is-impact) .snap-word {
  animation: none;
  opacity: 0;
}
body[data-character="temple"] .snap-crack {
  position: absolute;
  left: -2%;
  top: 38%;
  width: 104%;
  height: 0.3em;
  overflow: visible;
  transform: scaleX(0);
  transform-origin: left;
}
body[data-character="temple"] .snap-crack path {
  fill: none;
  stroke: #ffe39a;
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}
body[data-character="temple"] #character-wrap.is-impact .snap-crack {
  animation:
    temple-snap-crack 90ms linear 780ms forwards,
    temple-snap-crack-out 200ms 880ms forwards;
}
@keyframes temple-letter-slam {
  0% { opacity: 0; transform: translateY(-0.9em) scale(1.35); }
  60% { opacity: 1; transform: translateY(0) scale(1.12, 0.8); }
  80% { transform: scale(0.97, 1.04); }
  100% { opacity: 1; transform: none; }
}
@keyframes temple-letter-fall {
  100% { opacity: 0; transform: translateY(0.7em) rotate(var(--r)); }
}
@keyframes temple-snap-crack {
  100% { transform: scaleX(1); }
}
@keyframes temple-snap-crack-out {
  100% { opacity: 0; }
}

/* Jade chips burst from the jaw seam: twelve from the lip's corners and the
   lip, four stone flakes from the chin, and four grains of grit that trickle
   from the lip corners while the head chews. Each is a small faceted
   polygon (three hard-stop facets, no gold) that flies like a coin: drift on
   the chip, rise, fall and one bounce on its <i>, a finite spin on its <b>.
   Deep's rim hides the ones that fall into the pit. Phones keep the first
   ten. */
.temple-chips {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Out of the layout until the impact. */
  display: none;
}
.is-impact .temple-chips {
  display: block;
}
/* A wind-up that began still loaded no tip; a landing off a narrow
   screen's side gets no splash. */
.temple-chips.is-unloaded :is(.temple-shard, .temple-shard-splash),
.temple-shard-splash.is-off {
  display: none;
}
.temple-chip,
.temple-shard {
  position: absolute;
  translate: -50% -50%;
  opacity: 0;
}
.temple-chip {
  /* --cdx is the chip's sideways throw; phones halve it (--dx-k). */
  --dx: calc(var(--cdx) * var(--dx-k, 1));
  width: calc(var(--croc-w) * 0.022 * var(--k));
  aspect-ratio: 1;
}
.temple-chip i,
.temple-chip b,
.temple-shard i,
.temple-shard b {
  display: block;
  width: 100%;
  height: 100%;
}
.temple-chip b {
  background: linear-gradient(var(--a, 135deg), #a7e3bd 0 34%, #3f8f66 34% 68%, #1d4d3a 68%);
}
.temple-chip:not([data-kind="jade"]) b {
  background: linear-gradient(var(--a, 135deg), #cbbf9f 0 34%, #8f8268 34% 68%, #5b5143 68%);
}
.temple-chip:nth-child(4n + 1) b {
  --a: 125deg;
  clip-path: polygon(8% 30%, 46% 0, 100% 22%, 88% 78%, 38% 100%, 0 70%);
}
.temple-chip:nth-child(4n + 2) b {
  --a: 160deg;
  clip-path: polygon(0 18%, 70% 0, 100% 55%, 52% 100%, 10% 82%);
}
.temple-chip:nth-child(4n + 3) b {
  --a: 100deg;
  clip-path: polygon(20% 0, 100% 10%, 80% 100%, 0 64%);
}
.temple-chip:nth-child(4n) b {
  --a: 145deg;
  clip-path: polygon(0 40%, 36% 0, 100% 30%, 76% 88%, 28% 100%);
}
.is-impact .temple-chip:not([data-kind="grit"]),
.is-chewing .temple-chip[data-kind="grit"] {
  animation: temple-coin-x var(--t) linear calc(110ms + var(--d)) both;
}
.is-impact .temple-chip:not([data-kind="grit"]) i,
.is-chewing .temple-chip[data-kind="grit"] i {
  animation: temple-coin-y var(--t) calc(110ms + var(--d)) both;
}
.is-impact .temple-chip:not([data-kind="grit"]) b,
.is-chewing .temple-chip[data-kind="grit"] b {
  animation: temple-chip-spin var(--spin) linear calc(110ms + var(--d)) 3;
}
@keyframes temple-chip-spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
/* Phones (portrait, and landscape ones, whose head is even smaller) keep
   the animated-node count down: the first ten chips, which only tumble with
   their flight (no extra spin; at that size it does not show), and three of
   the six flakes. */
@media (max-width: 600px), (orientation: landscape) and (max-height: 480px) {
  .temple-chip:nth-child(n + 11) {
    display: none;
  }
  /* Half the sideways throw, so the burst stays on the screen. */
  .temple-chip {
    --dx-k: 0.5;
  }
  .is-impact .temple-chip:not([data-kind="grit"]) b,
  .is-chewing .temple-chip[data-kind="grit"] b {
    animation: none;
  }
  .temple-crushed b:nth-of-type(even) {
    display: none;
  }
}

/* The trap tooth's tip snaps off: the painted ivory of its tip end (cut
   along a jagged break by temple-character.js) pops out of the shut jaws,
   tumbles over the island to the tooth's side and drops into the water just
   past it (no bounce), where a ring and two droplets splash up. */
.is-impact .temple-shard {
  animation: temple-coin-x 820ms linear 110ms both;
}
.is-impact .temple-shard i {
  animation: temple-shard-y 820ms 110ms both;
}
.temple-shard svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
@keyframes temple-shard-y {
  0% { transform: none; animation-timing-function: cubic-bezier(0.15, 0.7, 0.35, 1); }
  36% { transform: translateY(calc(var(--up) * var(--croc-w) * -1)) rotate(calc(var(--tumble) * 0.4)); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5); }
  100% { transform: translateY(calc(var(--land) * var(--croc-w))) rotate(var(--tumble)); }
}
.temple-shard-splash {
  position: absolute;
  width: 10%;
  height: 3%;
  translate: -50% -50%;
}
.temple-shard-splash i {
  position: absolute;
  inset: 0;
  border: 2px solid #dafff4;
  border-radius: 50%;
  opacity: 0;
}
.temple-shard-splash b {
  position: absolute;
  left: 50%;
  bottom: 50%;
  width: calc(var(--croc-w) * 0.016);
  aspect-ratio: 10 / 14;
  opacity: 0;
  --hop: -1;
}
.temple-shard-splash b + b {
  --hop: 1;
}
.is-impact .temple-shard-splash i {
  animation: temple-shard-ring 500ms ease-out 900ms both;
}
.is-impact .temple-shard-splash b {
  animation: temple-shard-hop 400ms 900ms both;
}
@keyframes temple-shard-ring {
  0% { opacity: 0; transform: scale(0.3); }
  20% { opacity: 0.6; }
  100% { opacity: 0; transform: scale(1.4); }
}
@keyframes temple-shard-hop {
  0% { opacity: 0; transform: translateX(-50%) rotate(calc(180deg + var(--hop) * 20deg)) scale(0.5); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  15% { opacity: 0.95; }
  45% { transform: translate(calc(-50% + var(--hop) * var(--croc-w) * 0.012), calc(var(--croc-w) * -0.03)) rotate(calc(180deg + var(--hop) * 90deg)) scale(1); animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.5); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--hop) * var(--croc-w) * 0.024), 0) rotate(calc(180deg + var(--hop) * 150deg)) scale(0.7); }
}

/* Drips: after the splash, four drops (the same teardrop, hanging tip up)
   well up below the shut tooth tips and slide down the jaw on thin wet
   streaks, one after another, gone at the chin. They live in the bite pose,
   so they show only with it (on Deep the rim swallows them at the pit's
   edge). The two on the right catch the warm light. */
.temple-drips {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.temple-drip {
  position: absolute;
  top: 58%;
  /* About 15 px at 1440, never under 7 px on a phone. */
  width: max(7px, 2.2%);
  aspect-ratio: 10 / 14;
  translate: -50% 0;
}
.temple-drip svg {
  opacity: 0;
  transform-origin: 50% 0;
}
.temple-drip .streak {
  position: absolute;
  left: 41%;
  top: 30%;
  width: max(2px, 18%);
  height: calc(var(--len) * var(--croc-w));
  background: linear-gradient(#dffcf400, #dffcf499);
  transform: scaleY(0);
  transform-origin: top;
  opacity: 0;
}
body[data-character="temple"] .temple-drip:nth-child(n + 3) .drop-glint {
  fill: #ffe0b0;
}
body[data-character="temple"] #character-wrap.is-impact .temple-drip svg {
  animation: temple-drip 1.8s calc(600ms + var(--d)) both;
}
body[data-character="temple"] #character-wrap.is-impact .temple-drip .streak {
  animation: temple-drip-streak 1.8s calc(600ms + var(--d)) both;
}
@keyframes temple-drip {
  0% { opacity: 0; transform: scale(0.4); }
  14% { opacity: 0.95; transform: scale(1); }
  30% { opacity: 0.95; transform: scale(1); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.55); }
  72% { transform: translateY(calc(var(--len) * var(--croc-w))) scaleY(1.4); }
  86% { opacity: 0.8; transform: translateY(calc((var(--len) + 0.06) * var(--croc-w))); }
  100% { opacity: 0; transform: translateY(calc((var(--len) + 0.08) * var(--croc-w))); }
}
@keyframes temple-drip-streak {
  0%, 30% { opacity: 0; transform: scaleY(0); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.55); }
  34% { opacity: 0.9; }
  72% { transform: scaleY(1); }
  100% { opacity: 0; transform: scaleY(1); }
}

/* Grumpy aftermath: the head chews the bite (two grinding squashes pivoting
   on the jaw, then a settle), grit trickles from the lip corners, and it
   huffs (two short, fast, almost sideways puffs per shut nostril) 1.3 s
   after the bite and every 7-11 s until the next bet. Between huffs the head
   is dead still, and the grumpy face stays until the next bet. Later than
   the wind-up's rule, so a chew always wins. */
body[data-character="temple"] .is-chewing #character-motion {
  animation: temple-chew 860ms ease-in-out;
}
@keyframes temple-chew {
  0% { transform: none; }
  12% { transform: scale(1.01, 0.985) rotate(-0.4deg); }
  25% { transform: none; }
  38% { transform: scale(1.01, 0.985) rotate(0.4deg); }
  51% { transform: none; }
  70% { transform: translateY(0.4%); }
  85% { transform: translateY(-0.1%); }
  100% { transform: none; }
}
.is-huffing .temple-huff {
  --o: 0.7;
  animation: temple-puff 450ms cubic-bezier(0.05, 0.8, 0.3, 1) var(--d) both;
}

/* ---------- Presses: every button squashes and springs back ---------- */
/* temple-bet.js adds .is-tapped on each press (and to a newly chosen risk). The
   BET button presses deeper and a light sweeps across it; while it waits for a
   bet, a soft sheen passes over it every few seconds. */
body[data-character="temple"] :is(.bet-panel, .topbar) button.is-tapped,
body[data-character="temple"] .risk-options span.is-tapped {
  animation: temple-tap 320ms cubic-bezier(0.3, 0.7, 0.4, 1);
}
body[data-character="temple"] #bet-button.is-tapped {
  animation: temple-tap-deep 420ms cubic-bezier(0.3, 0.7, 0.4, 1);
}
body[data-character="temple"] #bet-button {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
body[data-character="temple"] #bet-button::before,
body[data-character="temple"] #bet-button::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg, #fff0 30%, #ffffff8c 47%, #fff0 64%);
  transform: translateX(-110%);
  pointer-events: none;
}
body[data-character="temple"] #bet-button.is-tapped::after {
  animation: temple-sweep 420ms ease-out;
}
body[data-character="temple"] #bet-button[data-label="bet"]:enabled::before {
  opacity: 0.6;
  animation: temple-sheen 5s ease-in-out 1.5s infinite;
}
@keyframes temple-tap {
  0%, 100% { transform: scale(1); }
  35% { transform: scale(0.9); }
  70% { transform: scale(1.05); }
}
@keyframes temple-tap-deep {
  0%, 100% { transform: scale(1); }
  30% { transform: scale(0.95, 0.92); }
  65% { transform: scale(1.02, 1.03); }
}
@keyframes temple-sweep {
  from { transform: translateX(-110%); }
  to { transform: translateX(110%); }
}
@keyframes temple-sheen {
  0%, 72% { transform: translateX(-110%); }
  100% { transform: translateX(110%); }
}

/* ---------- Batch 4: grit, gold and glints ---------- */
/* Collar grit and jade flakes: as a safe tooth seats (--seat), a fan of hard
   grains sprays from its collar lip (a rendered sprite, never a soft puff)
   and a few jade flakes tumble down the empty column (top row) or hop on the
   ledge (bottom row); more flakes at higher tension. The top row's grit ends
   above the readout band (y 589), the bottom row's below it (y 768). */
.tooth-grit {
  position: absolute;
  pointer-events: none;
}
.tooth-grit b {
  position: absolute;
  inset: 0;
  background: url("/assets/temple-grit-fan-1.webp") center / 100% 100% no-repeat;
  opacity: 0;
  transform-origin: 50% 0;
}
.tooth-grit[data-fan="2"] b {
  background-image: url("/assets/temple-grit-fan-2.webp");
}
.tooth-grit[data-row="bottom"] b {
  transform-origin: 50% 100%;
}
.tooth-grit i {
  position: absolute;
  top: 17.86%;
  width: calc(var(--croc-w) * 0.014 * var(--k2, 1));
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  background: linear-gradient(135deg, #a6e3bb 0 48%, #2f6a50 52%);
  clip-path: polygon(13% 87%, 7% 46%, 81% 33%, 85% 67%, 39% 98%);
}
.tooth-grit i:nth-of-type(4n + 2) {
  clip-path: polygon(13% 91%, 2% 63%, 25% 15%, 78% 8%, 85% 51%, 60% 96%);
}
.tooth-grit i:nth-of-type(4n + 3) {
  clip-path: polygon(30% 85%, 13% 52%, 32% 15%, 81% 48%, 56% 98%);
}
.tooth-grit i:nth-of-type(4n) {
  clip-path: polygon(2% 49%, 20% 21%, 77% 24%, 96% 63%, 56% 83%, 9% 74%);
}
.tooth-grit[data-row="bottom"] i {
  top: 82.14%;
}
body[data-character="temple"] .tooth.just-picked .tooth-grit[data-row="top"] b {
  animation: temple-grit-top 520ms cubic-bezier(0.1, 0.7, 0.3, 1) var(--seat, 110ms) both;
}
body[data-character="temple"] .tooth.just-picked .tooth-grit[data-row="bottom"] b {
  animation: temple-grit-bottom 520ms cubic-bezier(0.1, 0.7, 0.3, 1) var(--seat, 110ms) both;
}
body[data-character="temple"] .tooth.just-picked .tooth-grit[data-row="top"] i {
  animation: temple-flake-fall 420ms cubic-bezier(0.4, 0, 0.9, 0.6) calc(var(--seat, 110ms) + var(--dd, 0ms)) both;
}
body[data-character="temple"] .tooth.just-picked .tooth-grit[data-row="bottom"] i {
  animation: temple-flake-hop 460ms ease-out calc(var(--seat, 110ms) + var(--dd, 0ms)) both;
}
/* Two flakes at tension 1, three at 2, four at 3, all five at 4. */
#character-wrap[data-tension="1"] .tooth-grit i:nth-of-type(n + 3),
#character-wrap[data-tension="2"] .tooth-grit i:nth-of-type(n + 4),
#character-wrap[data-tension="3"] .tooth-grit i:nth-of-type(n + 5) {
  display: none;
}
@keyframes temple-grit-top {
  0% { opacity: 0; transform: translateY(0) scale(0.3, 0.15); }
  15% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(1.5%) scale(1, 1); }
}
/* The bottom row's fan is the same sprite mirrored about its middle, so its
   lip lands on the pad top and it sprays up. */
@keyframes temple-grit-bottom {
  0% { opacity: 0; transform: translateY(0) scale(0.3, 0.15) translateY(-100%) scaleY(-1); }
  15% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-1.5%) scale(1, 1) translateY(-100%) scaleY(-1); }
}
@keyframes temple-flake-fall {
  0% { opacity: 0; transform: translate(0, 0) rotate(0deg); }
  12% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(var(--fx) * var(--croc-w)), calc(var(--fy) * var(--croc-w))) rotate(var(--spin)); }
}
@keyframes temple-flake-hop {
  0% { opacity: 0; transform: translate(0, 0) rotate(0deg); }
  12% { opacity: 1; }
  45% { transform: translate(calc(var(--fx) * 0.6 * var(--croc-w)), calc(-0.025 * var(--croc-w))) rotate(calc(var(--spin) * 0.6)); }
  80% { transform: translate(calc(var(--fx) * var(--croc-w)), 0px) rotate(var(--spin)); }
  90% { opacity: 1; transform: translate(calc(var(--fx) * var(--croc-w)), calc(-0.004 * var(--croc-w))) rotate(var(--spin)); }
  100% { opacity: 0; transform: translate(calc(var(--fx) * var(--croc-w)), 0px) rotate(var(--spin)); }
}

/* Socket seat: as the tooth seats, the pad's mint check is drawn over in gold
   (on a dark edge) and cools back to the painted mint, and a gold ring
   pushes out from the collar's well. At a cash-out the checks of the
   survived sockets light up in pick order (--k) and keep a faint gold record
   until the next bet. Pads lie outside the readout band. */
.tooth-seat {
  position: absolute;
  overflow: visible;
  pointer-events: none;
  opacity: 0;
}
.seat-well {
  fill: none;
  stroke: #ffd86b;
  stroke-width: 4;
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
}
.seat-edge,
.seat-check {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
}
.seat-edge {
  stroke: #6b420b;
  stroke-width: 11;
  /* It draws with the gold check, never ahead of it. */
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.seat-check {
  stroke: #ffd86b;
  stroke-width: 7;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
body[data-character="temple"] .tooth.just-picked .tooth-seat {
  opacity: 1;
}
body[data-character="temple"] .tooth.just-picked .seat-check {
  animation:
    temple-seat-draw 180ms ease-out var(--seat, 110ms) both,
    temple-seat-cool 250ms ease-in calc(var(--seat, 110ms) + 300ms) forwards;
}
body[data-character="temple"] .tooth.just-picked .seat-edge {
  animation:
    temple-seat-trace 180ms ease-out var(--seat, 110ms) both,
    temple-seat-edge 730ms ease-out var(--seat, 110ms) both;
}
@keyframes temple-seat-trace {
  0% { stroke-dashoffset: 1; }
  100% { stroke-dashoffset: 0; }
}
body[data-character="temple"] .tooth.just-picked .seat-well {
  animation: temple-seat-push 420ms cubic-bezier(0.2, 0.7, 0.3, 1) var(--seat, 110ms) both;
}
#character-wrap.is-tallying .tooth.picked .tooth-seat {
  opacity: 1;
}
#character-wrap.is-tallying .tooth.picked .seat-check {
  stroke-dashoffset: 0;
  animation: temple-seat-tally 420ms cubic-bezier(0.2, 0.7, 0.3, 1) calc(120ms + var(--k, 0) * 70ms) both;
}
#character-wrap.is-tallying .tooth.picked .seat-edge {
  stroke-dashoffset: 0;
  animation: temple-seat-tally-edge 420ms cubic-bezier(0.2, 0.7, 0.3, 1) calc(120ms + var(--k, 0) * 70ms) both;
}
@keyframes temple-seat-draw {
  0% { opacity: 1; stroke-dashoffset: 1; }
  100% { opacity: 1; stroke-dashoffset: 0; }
}
@keyframes temple-seat-cool {
  0% { opacity: 1; stroke-dashoffset: 0; }
  100% { opacity: 0; stroke-dashoffset: 0; }
}
@keyframes temple-seat-edge {
  0% { opacity: 0; }
  25%, 68% { opacity: 0.9; }
  100% { opacity: 0; }
}
@keyframes temple-seat-push {
  0% { opacity: 0; transform: scale(1); }
  20% { opacity: 0.9; }
  100% { opacity: 0; transform: scale(1.1); }
}
@keyframes temple-seat-tally {
  0% { opacity: 0; }
  30% { opacity: 0.95; }
  100% { opacity: 0.3; }
}
@keyframes temple-seat-tally-edge {
  0% { opacity: 0; }
  30% { opacity: 0.85; }
  100% { opacity: 0.25; }
}

/* Eye glints: a white-gold star on each eye's catch-light (open, satisfied,
   shut and bite heads; only the visible pose's show). Menace on a tension
   rise, gotcha at a bite's wind-up, smug after a cash-out, tap-me from the
   idle director and BET. No halo, no blur, never the iris colour. */
.temple-glint {
  position: absolute;
  width: 7.5%;
  aspect-ratio: 1;
  translate: -50% -50%;
  overflow: visible;
  opacity: 0;
  transform: scale(0);
  pointer-events: none;
}
.temple-glint-sat,
.is-satisfied .temple-glint-open {
  display: none;
}
.is-satisfied .temple-glint-sat {
  display: block;
}
body[data-character="temple"] .is-glinting .temple-glint,
body[data-character="temple"] .is-glinting-right .temple-glint.is-r {
  animation: temple-glint 380ms cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
body[data-character="temple"] .is-glinting .temple-glint.is-r {
  animation-delay: 70ms;
}
@keyframes temple-glint {
  0% { opacity: 0; transform: scale(0) rotate(0deg); }
  35% { opacity: 1; transform: scale(1.1) rotate(20deg); }
  100% { opacity: 0; transform: scale(0) rotate(45deg); }
}

/* Fang glint (an idle director moment on the shut or bite head): a tilted
   light band sweeps the five fangs left to right, clipped to each, the
   middle tip tings, and then the BET button's sweep (.is-inviting) takes the
   eye down to it. */
.temple-fang-glint {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.fang-band {
  transform-box: fill-box;
}
.fang-ting {
  opacity: 0;
  transform-box: view-box;
  transform: scale(0);
}
body[data-character="temple"] .is-fang-glinting .fang-band {
  animation: temple-fang-sweep 380ms ease-in-out calc(var(--f, 0) * 70ms) both;
}
body[data-character="temple"] .is-fang-glinting .fang-ting {
  animation: temple-glint 200ms cubic-bezier(0.2, 0.8, 0.3, 1) 440ms both;
}
body[data-character="temple"] #bet-button.is-inviting::after {
  animation: temple-sweep 520ms ease-out;
}
@keyframes temple-fang-sweep {
  0% { transform: translateX(-120%); }
  100% { transform: translateX(420%); }
}

/* Kintsugi veins: hairline gold seams in dark grooves along the facet seams,
   opening from the picked sockets through a round (temple-character.js adds
   .is-on and, for a moment, .is-new), flickering with the bite's wind-up
   and melting away after a cash-out. Each round starts clean. */
.temple-veins {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.vein-seg {
  opacity: 0;
  transform-box: view-box;
}
.vein-seg.is-on {
  opacity: 1;
}
.vein-groove,
.vein-seam {
  fill: none;
  stroke-linecap: round;
}
.vein-groove {
  stroke: #0b241b;
  stroke-width: 4;
}
.vein-seam {
  stroke: url(#temple-vein-gold);
  stroke-width: 1.6;
}
.vein-tip {
  opacity: 0;
  transform-box: view-box;
  transform: scale(0);
}
body[data-character="temple"] .vein-seg.is-new {
  animation: temple-vein-grow 200ms steps(2, end) calc(var(--j, 0) * 45ms) both;
}
body[data-character="temple"] .vein-seg.is-new .vein-tip {
  animation: temple-glint 220ms ease-out calc(var(--j, 0) * 45ms + 120ms) both;
}
body[data-character="temple"] .is-bracing .vein-seg.is-on {
  animation: temple-vein-strain 420ms steps(1) both;
}
#character-wrap.is-tallying .temple-veins {
  animation: temple-vein-melt 1800ms ease-out both;
}
@keyframes temple-vein-grow {
  0% { opacity: 0; transform: scale(0.2); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes temple-vein-strain {
  0% { opacity: 1; }
  20% { opacity: 0.5; }
  40% { opacity: 1; }
  60% { opacity: 0.5; }
  80%, 100% { opacity: 1; }
}
@keyframes temple-vein-melt {
  0%, 25% { opacity: 1; }
  100% { opacity: 0; }
}

/* Ground-thump dust skirt (a bite's impact): grainy stone dust rolls out and
   up from the base of the head on both sides; the head hides the middle,
   and on Deep the rim hides the lower part. */
.temple-dust {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.temple-dust span {
  position: absolute;
  top: calc(86.922% - var(--isle-sink) * 100% - 1%);
  width: 14%;
  aspect-ratio: 3 / 2;
  translate: -50% -70%;
  transform-origin: 50% 70%;
  opacity: 0;
  background: url("/assets/temple-dust-1.webp") center / 100% 100% no-repeat;
}
.temple-dust span[data-dust="2"] {
  background-image: url("/assets/temple-dust-2.webp");
}
body[data-character="temple"] .is-impact .temple-dust span {
  animation: temple-dust 820ms cubic-bezier(0.15, 0.75, 0.3, 1) calc(110ms + var(--d, 0ms)) both;
}
@keyframes temple-dust {
  0% { opacity: 0; transform: translate(0, 0) scale(0.4); }
  15% { opacity: 0.75; }
  100% { opacity: 0; transform: translate(calc(var(--side) * var(--dx) * var(--croc-w)), calc(var(--dy) * var(--croc-w))) scale(var(--g)); }
}

/* Splash crowns (a bite's impact): four crowns of water rise from the
   island's waterline (--crown-y-N, measured per island sprite by
   scripts/make-temple-splash.py), the inner pair a beat later, the right
   pair mirrored. They are appended to .character-space after the head and
   Deep's rim, inside the island's box. */
.temple-splashes {
  position: absolute;
  left: var(--isle-x);
  top: var(--isle-y);
  width: var(--isle-w);
  height: var(--isle-h);
  pointer-events: none;
  --crown-y-0: 73.6%;
  --crown-y-1: 81.2%;
  --crown-y-2: 81.4%;
  --crown-y-3: 76.8%;
}
body[data-isle="flat"] .temple-splashes {
  --crown-y-0: 75.6%;
  --crown-y-1: 81.4%;
  --crown-y-2: 81.8%;
  --crown-y-3: 77%;
}
body[data-isle="deep"] .temple-splashes {
  --crown-y-0: 73.8%;
  --crown-y-1: 81.4%;
  --crown-y-2: 82.2%;
  --crown-y-3: 77%;
}
.temple-crown {
  position: absolute;
  width: 14%;
  aspect-ratio: 4 / 3;
  translate: -50% -100%;
  transform-origin: 50% 100%;
  opacity: 0;
  background: url("/assets/temple-splash-1.webp") center / 100% 100% no-repeat;
}
.temple-crown[data-c="0"] {
  left: 14%;
  top: var(--crown-y-0);
}
.temple-crown[data-c="1"] {
  left: 30%;
  top: var(--crown-y-1);
  width: 10%;
  background-image: url("/assets/temple-splash-2.webp");
}
.temple-crown[data-c="2"] {
  left: 70%;
  top: var(--crown-y-2);
  width: 10%;
  --flip: -1;
}
.temple-crown[data-c="3"] {
  left: 86%;
  top: var(--crown-y-3);
  --flip: -1;
  background-image: url("/assets/temple-splash-2.webp");
}
#character-wrap.is-impact ~ .temple-splashes .temple-crown {
  animation: temple-crown 620ms cubic-bezier(0.2, 0.8, 0.3, 1) 150ms both;
}
#character-wrap.is-impact ~ .temple-splashes .temple-crown:is([data-c="1"], [data-c="2"]) {
  animation-delay: 210ms;
}
@keyframes temple-crown {
  0% { opacity: 0; transform: translateY(0) scale(var(--flip, 1), 0.15); }
  12% { opacity: 0.9; }
  30% { transform: translateY(0) scale(var(--flip, 1), 1.05); }
  43% { transform: translateY(0) scale(var(--flip, 1), 1); }
  70% { opacity: 0.8; transform: translateY(2%) scale(var(--flip, 1), 0.7); }
  100% { opacity: 0; transform: translateY(6%) scale(var(--flip, 1), 0.5); }
}
/* A portrait phone shows only the middle of the island: the inner pair. */
@media (orientation: portrait), (max-width: 600px) {
  .temple-crown:is([data-c="0"], [data-c="3"]) {
    display: none;
  }
}

/* ---------- Betting panel: dark petrol glass with three cards ---------- */
/* Temple-only restyle of the shared panel (styles.css keeps it for the other
   editions): a floating glass panel over the water with the amount card
   (− amount + ½ 2× and the quick chips), the BET button and the risk card.
   temple-bet.js drives the −/+ steppers and the BET / BET AGAIN labels. */
body[data-character="temple"] .bet-panel {
  width: min(1120px, calc(100% - 48px));
  margin: 0 auto 16px;
  padding: 12px;
  border: 1px solid #2c5b52;
  border-radius: 18px;
  background: #0f2b28e0;
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 18px 44px -14px #010a09cc, inset 0 1px 0 #ffffff0f;
  color: #c9e6d0;
}
body[data-character="temple"] .bet-controls {
  max-width: none;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.92fr) minmax(0, 1.12fr);
  gap: 12px;
  align-items: stretch;
}
body[data-character="temple"] .amount-field,
body[data-character="temple"] .difficulty-field {
  position: relative;
  padding: 10px 12px 12px;
  border: 1px solid #1f4a44;
  border-radius: 12px;
  background: #0b2321;
}
body[data-character="temple"] .amount-field > label,
body[data-character="temple"] .difficulty-field legend {
  margin: 0 0 6px;
  color: #c9e6d0;
  font-size: 11px;
  font-weight: 900;
  line-height: 14px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
/* The risk card: label row on top (an absolute legend is an ordinary box, not
   the fieldset's border legend), the segmented control fills the rest. */
body[data-character="temple"] .difficulty-field {
  display: flex;
  flex-direction: column;
  padding-top: 30px;
}
body[data-character="temple"] .difficulty-field legend {
  position: absolute;
  top: 10px;
  left: 12px;
  right: 12px;
  width: auto;
  margin: 0;
}
body[data-character="temple"] #risk-hint {
  color: #c9e6d0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  opacity: 0.88;
}
body[data-character="temple"] .risk-options {
  flex: 1 1 auto;
  height: auto;
  min-height: 40px;
  padding: 4px;
  gap: 4px;
  border: 1px solid #1f4a44;
  border-radius: 11px;
  background: #081d1b;
}
body[data-character="temple"] .risk-options span {
  border-radius: 8px;
  color: #cfe6d3;
  font-size: 15px;
  font-weight: 800;
  transition: background 0.15s, color 0.15s;
}
body[data-character="temple"] .risk-options label:hover input:enabled:not(:checked) + span {
  background: #ffffff0d;
}
body[data-character="temple"] .risk-options input:checked + span {
  background: #4f7f4d;
  color: #fff;
  box-shadow: inset 0 1px 0 #ffffff21, 0 2px 6px #00000047;
}
body[data-character="temple"] .risk-options input:disabled + span {
  opacity: 0.5;
}
/* The amount row: − $10.00 + ½ 2× straight on the card, the amount centred
   between the steppers. */
body[data-character="temple"] .amount-input {
  --amount-gap: 8px;
  height: 40px;
  padding: 0;
  gap: var(--amount-gap);
  border: 0;
  border-radius: 0;
  background: none;
}
body[data-character="temple"] .amount-input > span,
body[data-character="temple"] .amount-input input {
  color: #f7f1dc;
  font-family: "Fredoka", sans-serif;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
}
/* "$" and the digits read as one word: cancel most of the row gap between. */
body[data-character="temple"] .amount-input > span {
  margin-left: auto;
  margin-right: calc(2px - var(--amount-gap));
  padding: 0;
}
body[data-character="temple"] .amount-input input {
  flex: 0 1 auto;
  width: 5.4ch;
  min-width: 2ch;
  margin-right: auto;
  padding: 2px 0;
  border-radius: 6px;
  font-variant-numeric: tabular-nums;
}
@supports (field-sizing: content) {
  body[data-character="temple"] .amount-input input {
    width: auto;
    field-sizing: content;
  }
}
body[data-character="temple"] .amount-input button {
  flex: none;
  width: 40px;
  height: 40px;
  border: 1px solid #2a5a52;
  border-radius: 999px;
  background: #0f302c;
  box-shadow: none;
  color: #e9f4e7;
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
  transition: background 0.15s, border-color 0.15s;
}
body[data-character="temple"] #temple-bet-minus,
body[data-character="temple"] #temple-bet-plus {
  font-size: 22px;
  font-weight: 600;
}
body[data-character="temple"] #half-bet,
body[data-character="temple"] #double-bet {
  width: 52px;
}
body[data-character="temple"] .amount-input button:hover:enabled {
  background: #174640;
  border-color: #3b766b;
}
body[data-character="temple"] .amount-input button:disabled {
  opacity: 0.45;
}
/* While a round plays game.js marks the amount field; dim its controls and
   keep the card. */
body[data-character="temple"] .amount-field.disabled {
  opacity: 1;
}
body[data-character="temple"] .amount-field.disabled > label,
body[data-character="temple"] .amount-field.disabled > .amount-input {
  opacity: 0.55;
}
body[data-character="temple"] .quick-bets {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
  margin-top: 8px;
}
body[data-character="temple"] .quick-bets button {
  height: 28px;
  border: 1px solid #1f4a44;
  border-radius: 8px;
  background: #0f2c29;
  color: #e3efe1;
  font-size: 13px;
  font-weight: 900;
}
body[data-character="temple"] .quick-bets button:hover:enabled:not([aria-pressed="true"]) {
  background: #16403a;
  border-color: #2f6559;
}
body[data-character="temple"] .quick-bets button[aria-pressed="true"] {
  background: #4f7f4d;
  border-color: #4f7f4d;
  color: #fff;
}
body[data-character="temple"] .quick-bets button:disabled {
  opacity: 0.4;
}
/* BET: amber, bold uppercase and letter-spaced; the short BET / BET AGAIN
   labels (data-label="bet", set by temple-bet.js) are larger than the
   in-round ones ("Pick a tooth", "Cash out $X"). */
body[data-character="temple"] #bet-button {
  height: auto;
  min-height: 60px;
  padding: 0 16px;
  gap: 8px;
  justify-content: center;
  border: 0;
  border-radius: 14px;
  background: #f0c14b linear-gradient(180deg, #ffffff30, #ffffff00 55%, #0000000d);
  box-shadow: inset 0 -3px 0 #c8912d, inset 0 1px 0 #ffe7a3, 0 10px 22px -10px #010a09b3;
  color: #1a2d10;
  font-family: "Fredoka", sans-serif;
  font-size: clamp(17px, 1.5vw, 22px);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
body[data-character="temple"] #bet-button[data-label="bet"] {
  font-size: clamp(22px, 2.2vw, 32px);
  letter-spacing: 0.07em;
}
body[data-character="temple"] #bet-button > svg,
body[data-character="temple"] #bet-button > i {
  display: none;
}
/* A long cash-out ("Cash out $29,100.00") wraps in a narrow button. */
body[data-character="temple"] #bet-button > span {
  white-space: normal;
  text-wrap: balance;
  line-height: 1.1;
}
body[data-character="temple"] #bet-button:hover:enabled {
  background-color: #f5cd63;
}
body[data-character="temple"] #bet-button.cashing {
  background-color: #add974;
  box-shadow: inset 0 -3px 0 #6c9a44, inset 0 1px 0 #d0ed9e, 0 10px 22px -10px #010a09b3;
}
body[data-character="temple"] #bet-button.cashing:hover:enabled {
  background-color: #b8e083;
}
body[data-character="temple"] #bet-button:disabled {
  background: #1b3934;
  box-shadow: inset 0 0 0 1px #2c5b52;
  color: #9dbfae;
}
body[data-character="temple"] .bet-error {
  margin: 8px 0 0;
  color: #ffc4b0;
  font-weight: 700;
}
body[data-character="temple"] .bet-panel :is(button, input):focus-visible,
body[data-character="temple"] .risk-options input:focus-visible + span {
  outline: 2px solid #9fe3c0;
  outline-offset: 2px;
}
/* Narrower cards: smaller amount-row controls so "$1000.00" still fits. */
@media (max-width: 1100px) {
  body[data-character="temple"] .amount-input {
    --amount-gap: 6px;
  }
  body[data-character="temple"] .amount-input button {
    width: 36px;
    height: 36px;
  }
  body[data-character="temple"] #half-bet,
  body[data-character="temple"] #double-bet {
    width: 44px;
  }
  body[data-character="temple"] .amount-input > span,
  body[data-character="temple"] .amount-input input {
    font-size: 21px;
  }
}
@media (max-width: 1000px) {
  body[data-character="temple"] .amount-input {
    --amount-gap: 5px;
  }
  body[data-character="temple"] .amount-input button {
    width: 34px;
    height: 34px;
  }
  body[data-character="temple"] #half-bet,
  body[data-character="temple"] #double-bet {
    width: 40px;
  }
  body[data-character="temple"] .amount-input > span,
  body[data-character="temple"] .amount-input input {
    font-size: 20px;
  }
}
/* Short screens (landscape phones, low windows): the same three cards,
   tighter, so the head keeps its room. */
@media (max-height: 650px) and (min-width: 601px) {
  body[data-character="temple"] .bet-panel {
    width: min(1120px, calc(100% - 24px));
    margin-bottom: 8px;
    padding: 8px;
    border-radius: 14px;
  }
  body[data-character="temple"] .bet-controls {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.75fr) minmax(0, 1fr);
    gap: 8px;
  }
  body[data-character="temple"] .amount-field,
  body[data-character="temple"] .difficulty-field {
    padding: 7px 10px 9px;
    border-radius: 10px;
  }
  body[data-character="temple"] .amount-field > label,
  body[data-character="temple"] .difficulty-field legend {
    margin-bottom: 4px;
    font-size: 10px;
    line-height: 12px;
  }
  body[data-character="temple"] .difficulty-field {
    padding-top: 23px;
  }
  body[data-character="temple"] .difficulty-field legend {
    top: 7px;
    left: 10px;
    right: 10px;
    margin: 0;
  }
  body[data-character="temple"] #risk-hint {
    font-size: 10px;
  }
  body[data-character="temple"] .amount-input {
    --amount-gap: 5px;
    height: 32px;
  }
  body[data-character="temple"] .amount-input button {
    width: 32px;
    height: 32px;
  }
  body[data-character="temple"] #half-bet,
  body[data-character="temple"] #double-bet {
    width: 38px;
  }
  body[data-character="temple"] .amount-input > span,
  body[data-character="temple"] .amount-input input {
    font-size: 18px;
  }
  body[data-character="temple"] .quick-bets {
    margin-top: 6px;
    gap: 5px;
  }
  body[data-character="temple"] .quick-bets button {
    height: 24px;
    font-size: 11px;
  }
  body[data-character="temple"] .risk-options {
    min-height: 32px;
  }
  body[data-character="temple"] .risk-options span {
    font-size: 13px;
  }
  body[data-character="temple"] #bet-button {
    min-height: 0;
    font-size: 15px;
  }
  body[data-character="temple"] #bet-button[data-label="bet"] {
    font-size: 21px;
  }
}
/* Phones and narrow tall screens: the amount card and the risk card side by
   side, the quick chips below both, then a full-width BET. The amount field's
   box steps aside (display: contents) so its chips can span the row; a grid
   pseudo-element draws the amount card behind its label and amount row. */
@media (max-width: 600px), (max-width: 900px) and (min-height: 651px) {
  body[data-character="temple"] .bet-panel {
    width: calc(100% - 16px);
    margin: 0 auto max(8px, env(safe-area-inset-bottom));
    padding: 8px;
    border-radius: 16px;
  }
  body[data-character="temple"] .bet-controls {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto auto;
    gap: 0 8px;
  }
  body[data-character="temple"] .bet-controls::before {
    content: "";
    grid-column: 1;
    grid-row: 1 / span 2;
    border: 1px solid #1f4a44;
    border-radius: 12px;
    background: #0b2321;
  }
  body[data-character="temple"] .amount-field {
    display: contents;
  }
  body[data-character="temple"] .amount-field > label {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
    padding: 9px 11px 6px;
  }
  body[data-character="temple"] .amount-input {
    grid-column: 1;
    grid-row: 2;
    height: auto;
    min-height: 36px;
    margin: 0 9px 9px;
  }
  body[data-character="temple"] .difficulty-field {
    grid-column: 2;
    grid-row: 1 / span 2;
    padding: 29px 9px 9px;
  }
  body[data-character="temple"] .difficulty-field legend {
    top: 9px;
    left: 11px;
    right: 11px;
  }
  body[data-character="temple"] .quick-bets {
    grid-column: 1 / -1;
    grid-row: 3;
    margin-top: 8px;
  }
  body[data-character="temple"] .quick-bets button {
    height: 32px;
  }
  body[data-character="temple"] #bet-button {
    grid-column: 1 / -1;
    grid-row: 4;
    min-height: 50px;
    height: 50px;
    margin-top: 8px;
    font-size: 17px;
  }
  body[data-character="temple"] #bet-button[data-label="bet"] {
    font-size: 22px;
  }
}
@media (max-width: 600px) {
  /* Phones: − amount + on the first line of the amount card, ½ and 2× on the
     second; the segmented risk control fills its card beside it. */
  body[data-character="temple"] .amount-input {
    --amount-gap: 4px;
    flex-wrap: wrap;
    row-gap: 6px;
  }
  body[data-character="temple"] .amount-input button {
    width: 32px;
    height: 32px;
  }
  body[data-character="temple"] #half-bet,
  body[data-character="temple"] #double-bet {
    flex: 1 1 40%;
    height: 28px;
    border-radius: 8px;
  }
  body[data-character="temple"] .amount-input > span,
  body[data-character="temple"] .amount-input input {
    font-size: 18px;
  }
  body[data-character="temple"] .amount-field > label,
  body[data-character="temple"] .difficulty-field legend {
    font-size: 10px;
    letter-spacing: 0.1em;
  }
  body[data-character="temple"] #risk-hint {
    font-size: 10px;
  }
  /* Narrow cards: each segment as wide as its label needs. */
  body[data-character="temple"] .risk-options {
    padding: 3px;
    gap: 2px;
  }
  body[data-character="temple"] .risk-options label {
    flex: 1 1 auto;
  }
  body[data-character="temple"] .risk-options span {
    padding: 0 5px;
    font-size: 12px;
  }
}

/* ---------- Layout details ---------- */
@media (max-height: 650px) and (min-width: 601px) {
  body[data-character="temple"] .game-layout {
    --band-top: 52px;
    --band-bottom: calc(100cqh - 122px);
  }
}
@media (max-width: 900px) and (min-height: 651px) {
  body[data-character="temple"] .game-layout {
    --band-bottom: calc(100cqh - 204px);
  }
}
@media (max-width: 600px) {
  body[data-character="temple"] .game-layout {
    --band-top: 64px;
    --band-bottom: calc(100cqh - 228px);
  }
  body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose .next-multiplier,
  body[data-character="temple"] .game-board.lost .has-bite-pose .next-multiplier {
    font-size: 11px;
    padding: 4px 11px;
  }
  body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose #next-multiplier,
  body[data-character="temple"] .game-board.lost .has-bite-pose #next-multiplier {
    font-size: 17px;
  }
}
/* Landscape phones: the head is small (about 200-260 px), so the in-mouth
   readout drops the 26 px / 10 px floors to stay inside the 14.3 % band, and
   the readout above the shut head shrinks to fit under the top bar. */
@media (orientation: landscape) and (max-height: 480px) {
  body[data-character="temple"] .game-layout > * {
    --mouth-value: max(15px, calc(var(--croc-w) * 0.08));
    --mouth-next: max(8px, calc(var(--croc-w) * 0.033));
    --mouth-gap: 2px;
    --readout-size: clamp(28px, 8vh, 46px);
    --readout-gap: 6px;
    --readout-room: calc(var(--readout-size) * 0.95 + 40px);
  }
  body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose .next-multiplier,
  body[data-character="temple"] .game-board.lost .has-bite-pose .next-multiplier {
    margin-top: 3px;
    padding: 2px 9px;
    font-size: 10px;
  }
  body[data-character="temple"] .game-board:not(.playing, .won) .has-closed-pose #next-multiplier,
  body[data-character="temple"] .game-board.lost .has-bite-pose #next-multiplier {
    font-size: 14px;
  }
}
/* ---------- Cash-out celebration (Batch 3) ---------- */
/* temple-character.js sets data-win (1-4) on #character-wrap for a won state
   when nothing is still: 4 for a clean sweep, 3 from 5x, 2 from 2x, 1 below.
   Every effect below keys on it (with .is-cashing), so none of them starts
   under the scenery pause, reduced motion or a hidden tab. */

/* A proud chin-up hop, pivoting on the jaw, bigger with the tier; never more
   than 12 px up (the headroom the layout reserves). It replaces styles.css's
   win-hop, which stays for a cash-out made while still (data-hop="still").
   temple-character.js sets data-hop once, at the cash-out, and keeps it for
   the won state, so pausing or resuming never swaps (and so restarts) the
   hop. */
body[data-character="temple"] .game-board.won #character-motion {
  animation: temple-proud-1 620ms both;
}
body[data-character="temple"] .game-board.won #character-wrap[data-hop="2"] #character-motion {
  animation: temple-proud-2 700ms both;
}
body[data-character="temple"] .game-board.won #character-wrap:is([data-hop="3"], [data-hop="4"]) #character-motion {
  animation: temple-proud-3 780ms both;
}
body[data-character="temple"] .game-board.won #character-wrap[data-hop="still"] #character-motion {
  animation-name: win-hop;
  animation-duration: 560ms;
}
body[data-character="temple"] .game-board.won .temple-contact {
  animation: temple-contact-hop 620ms ease-out both;
}
body[data-character="temple"] .game-board.won #character-wrap[data-hop="2"] .temple-contact {
  animation-duration: 700ms;
}
body[data-character="temple"] .game-board.won #character-wrap:is([data-hop="3"], [data-hop="4"]) .temple-contact {
  animation: temple-contact-hop-3 780ms ease-out both;
}
body[data-character="temple"] .game-board.won #character-wrap[data-hop="still"] .temple-contact {
  animation: none;
}
@keyframes temple-proud-1 {
  0% { transform: none; animation-timing-function: ease-out; }
  14% { transform: translateY(3px) scale(1.02, 0.975); animation-timing-function: cubic-bezier(0.2, 0.65, 0.3, 1); }
  46% { transform: translateY(-12px) scale(0.99, 1.02); animation-timing-function: cubic-bezier(0.6, 0, 0.8, 0.4); }
  74% { transform: translateY(0) scale(1.015, 0.985); }
  100% { transform: none; }
}
@keyframes temple-proud-2 {
  0% { transform: none; animation-timing-function: ease-out; }
  14% { transform: translateY(3px) scale(1.02, 0.975) rotate(0deg); animation-timing-function: cubic-bezier(0.2, 0.65, 0.3, 1); }
  46% { transform: translateY(-12px) scale(0.99, 1.02) rotate(-1.2deg); }
  60% { transform: translateY(-11px) scale(0.995, 1.01) rotate(-1.2deg); animation-timing-function: cubic-bezier(0.6, 0, 0.8, 0.4); }
  78% { transform: translateY(0) scale(1.015, 0.985) rotate(0deg); }
  100% { transform: none; }
}
@keyframes temple-proud-3 {
  0% { transform: none; animation-timing-function: ease-out; }
  8% { transform: translateY(3px) scale(1.02, 0.975) rotate(0deg); animation-timing-function: cubic-bezier(0.2, 0.65, 0.3, 1); }
  28% { transform: translateY(-12px) scale(0.99, 1.02) rotate(-1.2deg); }
  36% { transform: translateY(-11px) scale(0.995, 1.01) rotate(-1.2deg); animation-timing-function: cubic-bezier(0.6, 0, 0.8, 0.4); }
  47% { transform: translateY(0) scale(1.015, 0.985) rotate(0deg); }
  60% { transform: translateY(0) scale(1, 1) rotate(0deg); animation-timing-function: ease-out; }
  72% { transform: translateY(-5px) scale(1, 1) rotate(0.6deg); animation-timing-function: ease-in; }
  86% { transform: translateY(0) scale(1.008, 0.992) rotate(0deg); }
  100% { transform: none; }
}
/* The contact shadow shrinks and fades as the head leaves the stone and
   spreads at the landing. */
@keyframes temple-contact-hop {
  0%, 100% { transform: none; opacity: 1; }
  46% { transform: scale(0.92, 0.85); opacity: 0.8; }
  74% { transform: scale(1.06, 1.15); opacity: 1; }
}
@keyframes temple-contact-hop-3 {
  0%, 60%, 100% { transform: none; opacity: 1; }
  28% { transform: scale(0.92, 0.85); opacity: 0.8; }
  47% { transform: scale(1.06, 1.15); opacity: 1; }
  72% { transform: scale(0.97, 0.94); opacity: 0.92; }
  86% { transform: scale(1.02, 1.05); opacity: 1; }
}

/* Smoke rings of satisfaction (tiers 2-4) replace the sigh: one, two or three
   rings per nostril, the second faster so it catches up and passes through
   the first; the right nostril 120 ms after the left. They rise from the
   nostrils (23 % of the frame) to about 3 %, only up and outward, clear of
   the eyes, teeth and readout. */
.temple-nostril span.temple-ring {
  --r0: 0deg;
  width: calc(var(--croc-w) * 0.14);
  aspect-ratio: 2 / 1;
  background-image: url("/assets/temple-smoke-ring-1.webp");
}
.temple-nostril span.temple-ring:nth-child(even) {
  background-image: url("/assets/temple-smoke-ring-2.webp");
}
#character-wrap.is-cashing:is([data-win="2"], [data-win="3"], [data-win="4"]) .temple-ring[data-i="0"],
#character-wrap.is-cashing[data-win="4"] .temple-ring[data-i="2"] {
  animation: temple-smoke-ring 1400ms cubic-bezier(0.15, 0.75, 0.3, 1) calc(900ms + var(--d)) both;
}
#character-wrap.is-cashing:is([data-win="3"], [data-win="4"]) .temple-ring[data-i="1"] {
  animation: temple-smoke-ring 1100ms cubic-bezier(0.15, 0.75, 0.3, 1) calc(900ms + var(--d)) both;
}
#character-wrap.is-cashing .temple-nostril + .temple-nostril .temple-ring[data-i] {
  animation-delay: calc(1020ms + var(--d));
}
#character-wrap.is-cashing:is([data-win="2"], [data-win="3"], [data-win="4"]) .temple-sigh {
  animation: none;
}
@keyframes temple-smoke-ring {
  0% { opacity: 0; transform: translate(0, 0) rotate(0deg) scale(0.2); }
  8% { opacity: 0.9; }
  40% { transform: translate(calc(var(--side) * var(--dx) * var(--croc-w) * 0.5), calc(var(--dy) * var(--croc-w) * 0.5)) rotate(calc(var(--side) * 5deg)) scale(calc(var(--s) * 0.7), calc(var(--s) * 0.62)); }
  70% { opacity: 0.6; transform: translate(calc(var(--side) * var(--dx) * var(--croc-w) * 0.8), calc(var(--dy) * var(--croc-w) * 0.8)) rotate(calc(var(--side) * 7deg)) scale(calc(var(--s) * 0.9), calc(var(--s) * 0.95)); }
  100% { opacity: 0; transform: translate(calc(var(--side) * var(--dx) * var(--croc-w)), calc(var(--dy) * var(--croc-w))) rotate(calc(var(--side) * 8deg)) scale(var(--s), calc(var(--s) * 0.88)); }
}

/* The fountain grows with the tier: waves 3 and 4 of coins (data-w), jade and
   amber gems, and at tiers 3-4 four far coins that sail past the island's
   ends and splash into the water. All of them spill from the mouth corners
   and arc outward. Phones drop wave 4 and half the gems; portrait screens
   drop the far coins (the island is wider than the screen there). */
.temple-coin[data-w],
.temple-gem,
.temple-coin-far,
.temple-coin-splash {
  display: none;
}
#character-wrap[data-win="2"] :is(.temple-coin[data-w="3"], .temple-gem:is([data-g="0"], [data-g="1"], [data-g="2"], [data-g="3"], [data-g="4"], [data-g="5"])),
#character-wrap:is([data-win="3"], [data-win="4"]) :is(.temple-coin[data-w], .temple-gem) {
  display: block;
}
/* The far coins land past the island's ends, off a portrait screen: shown
   in landscape only (a portrait rule would lose to the rule above on
   specificity). */
@media (orientation: landscape) {
  #character-wrap:is([data-win="3"], [data-win="4"]) :is(.temple-coin-far, .temple-coin-splash) {
    display: block;
  }
}
@media (max-width: 600px) {
  #character-wrap[data-win] .temple-coin[data-w="4"],
  #character-wrap[data-win] .temple-gem:is([data-g="6"], [data-g="7"], [data-g="8"], [data-g="9"], [data-g="10"], [data-g="11"]),
  .temple-coins > .temple-coin:nth-child(n + 21):nth-child(-n + 30) {
    display: none;
  }
}
/* Gems: a rendered brilliant (scripts/make-temple-gems.py) that turns in its
   plane instead of flipping like a coin, and flashes a crisp star once at the
   top of its arc. */
.temple-gem b {
  background: url("/assets/temple-gem-jade.webp") center / contain no-repeat;
  box-shadow: none;
}
.temple-gem[data-kind="amber"] b {
  background-image: url("/assets/temple-gem-amber.webp");
}
.temple-gem b::before {
  display: none;
}
.temple-gem b::after {
  left: 12%;
  top: 6%;
  width: 46%;
  background: linear-gradient(135deg, #fff, #fff6d0);
  clip-path: polygon(50% 0, 56% 44%, 100% 50%, 56% 56%, 50% 100%, 44% 56%, 0 50%, 44% 44%);
}
.is-cashing .temple-gem b {
  animation: temple-gem-spin var(--spin) linear infinite;
}
.is-cashing .temple-gem b::after {
  animation: temple-coin-glint 900ms ease-out calc(var(--d) + var(--t) * 0.36 - 675ms) 1;
}
@keyframes temple-gem-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
/* Far coins land in the water beyond the island (no bounce) and splash: a
   thin ring and three hopping drops. */
.temple-coin-far {
  --land: calc(0.29 + var(--isle-drop, 0.24) + var(--row, 0) * 0.04);
}
.is-cashing .temple-coin-far i {
  animation: temple-coin-sink var(--t) var(--d) both;
}
@keyframes temple-coin-sink {
  0% { transform: translateY(0) scale(0.35) rotate(0deg); animation-timing-function: cubic-bezier(0.15, 0.7, 0.35, 1); }
  36% { transform: translateY(calc(var(--up) * var(--croc-w) * -1)) scale(1.05) rotate(calc(var(--tumble) * 0.4)); animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.5); }
  78% { transform: translateY(calc(var(--land) * var(--croc-w))) scale(0.95) rotate(var(--tumble)); animation-timing-function: ease-out; }
  100% { transform: translateY(calc((var(--land) + 0.015) * var(--croc-w))) scale(0.7) rotate(var(--tumble)); }
}
.temple-coin-splash {
  position: absolute;
  left: calc(50% + var(--dx) * 100%);
  /* The second pair lands a little nearer (--row 1), so two splashes on
     one side never stack. */
  top: calc(57% + (0.29 + var(--isle-drop, 0.24) + var(--row, 0) * 0.04) * 100%);
  width: calc(var(--croc-w) * 0.1);
  aspect-ratio: 3;
  translate: -50% -50%;
  pointer-events: none;
}
.temple-coin-splash i {
  position: absolute;
  inset: 0;
  border: 2px solid #dafff4;
  border-radius: 50%;
  opacity: 0;
}
/* Three drops of different sizes and heights leave the middle of the ring
   at different moments and fan outward (never a level row of dots). */
.temple-coin-splash b {
  position: absolute;
  left: 46%;
  top: 30%;
  width: 7%;
  aspect-ratio: 0.7;
  border-radius: 50% 50% 50% 50% / 64% 64% 36% 36%;
  background: #dcfff7;
  opacity: 0;
}
.temple-coin-splash b:nth-of-type(1) { --hop: -1; --rise: 0.034; --lag: 0ms; left: 40%; width: 6%; }
.temple-coin-splash b:nth-of-type(2) { --hop: 0.2; --rise: 0.052; --lag: 50ms; left: 47%; width: 8.5%; }
.temple-coin-splash b:nth-of-type(3) { --hop: 1.1; --rise: 0.024; --lag: 110ms; left: 55%; width: 5%; }
.is-cashing .temple-coin-splash i {
  animation: temple-coin-ring 500ms ease-out calc(var(--d) + var(--t) * 0.78) both;
}
.is-cashing .temple-coin-splash b {
  animation: temple-coin-drop 500ms linear calc(var(--d) + var(--t) * 0.78 + var(--lag, 0ms)) both;
}
@keyframes temple-coin-ring {
  0% { opacity: 0; transform: scale(0.3); }
  30% { opacity: 0.6; }
  100% { opacity: 0; transform: scale(1.3); }
}
@keyframes temple-coin-drop {
  0% { opacity: 0; transform: translate(0, 0); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  15% { opacity: 1; }
  50% { transform: translate(calc(var(--hop) * var(--croc-w) * 0.02), calc(var(--croc-w) * var(--rise, 0.03) * -1)) rotate(calc(var(--hop) * 25deg)); animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.5); }
  90% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(var(--hop) * var(--croc-w) * 0.034), 0) rotate(calc(var(--hop) * 50deg)); }
}

/* Glints on the island's foam line (JS appends the layer after the Deep rim,
   in the island box): crisp thin 4-point stars from the front centre
   outward, 6 at tier 1, 10 at tier 2, 14 at tiers 3-4, as the amber ring
   leaves the island. Big wins (3-4) ring the water twice. */
.temple-win-glints {
  position: absolute;
  left: var(--isle-x);
  top: var(--isle-y);
  width: var(--isle-w);
  height: var(--isle-h);
  pointer-events: none;
}
.temple-win-glints span {
  position: absolute;
  width: calc(var(--g-w, 1) * 3.2%);
  min-width: 10px;
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  background: linear-gradient(135deg, #ffffff, #fff3c4 45%, #ffd24f);
  clip-path: polygon(50% 0, 55% 45%, 100% 50%, 55% 55%, 50% 100%, 45% 55%, 0 50%, 45% 45%);
}
.temple-win-glints span:nth-child(3n) { --g-w: 0.7; }
.temple-win-glints span:nth-child(3n + 1) { --g-w: 1.2; }
/* Traced on the island sprites' foam line (island-box %), --o outward. */
.temple-win-glints span:nth-child(1) { left: 50.17%; top: 82.6%; --o: 0; }
.temple-win-glints span:nth-child(2) { left: 60.51%; top: 81.96%; --o: 1; }
.temple-win-glints span:nth-child(3) { left: 39.83%; top: 81.96%; --o: 2; }
.temple-win-glints span:nth-child(4) { left: 70.32%; top: 80.09%; --o: 3; }
.temple-win-glints span:nth-child(5) { left: 30.02%; top: 80.09%; --o: 4; }
.temple-win-glints span:nth-child(6) { left: 79.1%; top: 77.2%; --o: 5; }
.temple-win-glints span:nth-child(7) { left: 21.24%; top: 77.2%; --o: 6; }
.temple-win-glints span:nth-child(8) { left: 86.43%; top: 73.54%; --o: 7; }
.temple-win-glints span:nth-child(9) { left: 13.91%; top: 73.54%; --o: 8; }
.temple-win-glints span:nth-child(10) { left: 91.61%; top: 69.75%; --o: 9; }
.temple-win-glints span:nth-child(11) { left: 8.73%; top: 69.75%; --o: 10; }
.temple-win-glints span:nth-child(12) { left: 95.18%; top: 65.59%; --o: 11; }
.temple-win-glints span:nth-child(13) { left: 5.16%; top: 65.59%; --o: 12; }
.temple-win-glints span:nth-child(14) { left: 97.08%; top: 60.49%; --o: 13; }
#character-wrap[data-win] ~ .temple-win-glints span:nth-child(-n + 6),
#character-wrap[data-win="2"] ~ .temple-win-glints span:nth-child(-n + 10),
#character-wrap:is([data-win="3"], [data-win="4"]) ~ .temple-win-glints span {
  animation: temple-water-glint 240ms ease-out calc(280ms + var(--o) * 15ms) both;
}
@keyframes temple-water-glint {
  0% { opacity: 0; transform: scale(0.3) rotate(0deg); }
  40% { opacity: 1; transform: scale(1) rotate(10deg); }
  100% { opacity: 0; transform: scale(0.2) rotate(20deg); }
}
.game-layout:has(#character-wrap:is([data-win="3"], [data-win="4"])) .temple-win-ripple span {
  animation: temple-win-ripple 600ms 0.08s ease-out 2 both;
}

/* The wallet pays the stake at a round start: the balance counts down and a
   cream "−$stake" tag (never red) drops out of the pill. */
.temple-spend {
  position: absolute;
  left: 14px;
  top: calc(100% + 4px);
  padding: 2px 9px;
  border: 1px solid #fff5d42e;
  border-radius: 999px;
  background: #0a2a24c7;
  color: #d9ead6;
  font-family: "Fredoka", sans-serif;
  font-size: 16px;
  font-weight: 700;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  pointer-events: none;
}
body[data-character="temple"] .wallet.is-spending {
  animation: temple-wallet-dip 200ms ease-out;
}
body[data-character="temple"] .wallet.is-spending .temple-spend {
  animation: temple-spend 900ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
@media (max-width: 600px) {
  /* Under the pill's right end, clear of the DEMO chip on its left. */
  .temple-spend {
    left: auto;
    right: 4px;
  }
}
@keyframes temple-wallet-dip {
  0%, 100% { transform: none; }
  45% { transform: scale(0.97); }
}
@keyframes temple-spend {
  0% { opacity: 0; transform: none; }
  25% { opacity: 1; transform: translateY(6px); }
  70% { opacity: 1; transform: translateY(9px); }
  100% { opacity: 0; transform: translateY(14px); }
}
/* It catches every coin: a small tick per collector, the $ spins like a coin
   and a gold arc runs once round the pill as the count ends. */
body[data-character="temple"] .wallet .currency {
  display: inline-block;
}
body[data-character="temple"] .wallet strong {
  font-variant-numeric: tabular-nums;
}
body[data-character="temple"] .wallet.is-collecting .currency {
  animation: temple-wallet-coin 480ms ease-in-out 60ms both;
}
/* It flips like a coin by narrowing to its edge and back (never through
   180 deg, which would show a mirrored $). */
@keyframes temple-wallet-coin {
  0% { transform: scaleX(1); }
  25% { transform: scaleX(0.08); color: #b7780f; }
  50% { transform: scaleX(1); }
  75% { transform: scaleX(0.08); color: #b7780f; }
  100% { transform: scaleX(1); }
}
.temple-wallet-arc {
  position: absolute;
  inset: -1px;
  padding: 2px;
  border-radius: inherit;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.temple-wallet-arc::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 300%;
  aspect-ratio: 1;
  translate: -50% -50%;
  background: conic-gradient(#ffd24f00 0deg, #ffd24f 30deg, #fff3c4 45deg, #ffd24f00 70deg);
}
body[data-character="temple"] .wallet.is-collecting .temple-wallet-arc {
  animation: temple-wallet-arc 600ms linear 860ms both;
}
body[data-character="temple"] .wallet.is-collecting .temple-wallet-arc::before {
  animation: temple-wallet-arc-turn 600ms linear 860ms both;
}
@keyframes temple-wallet-arc {
  0%, 100% { opacity: 0; }
  20%, 75% { opacity: 1; }
}
@keyframes temple-wallet-arc-turn {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* The bet button arms, ripens and pays out. The dark PICK A TOOTH tablet
   flips face up into CASH OUT on the first safe tooth. */
body[data-character="temple"] #bet-button.is-arming {
  transform-origin: 50% 100%;
  animation: temple-arm 320ms cubic-bezier(0.3, 0.7, 0.4, 1.3);
}
body[data-character="temple"] #bet-button.is-arming::after {
  background: linear-gradient(105deg, #fff0 30%, #ffe9a0cc 47%, #fff0 64%);
  animation: temple-sweep 420ms ease-out 200ms;
}
@keyframes temple-arm {
  0% { transform: perspective(500px) rotateX(-80deg); }
  70% { transform: perspective(500px) rotateX(8deg); }
  100% { transform: none; }
}
/* CASH OUT ripens from green to gold with the tension, and its sheen
   quickens. */
body[data-character="temple"] #bet-button.cashing:not(.is-arming) {
  transition: background-color 500ms, box-shadow 500ms;
}
/* The lock and unlock of each pick switch at once; only the ripening between
   tension tiers fades (below). */
body[data-character="temple"] #bet-button.cashing:is(:disabled, .is-arming) {
  transition: none;
}
.game-layout:has(#character-wrap[data-tension="1"]) #bet-button.cashing {
  --sheen: 5s;
}
.game-layout:has(#character-wrap[data-tension="2"]) #bet-button.cashing {
  --sheen: 3.5s;
  background-color: #bddb6a;
  box-shadow: inset 0 -3px 0 #7fa03e, inset 0 1px 0 #dcefa0, 0 10px 22px -10px #010a09b3;
}
.game-layout:has(#character-wrap[data-tension="3"]) #bet-button.cashing {
  --sheen: 2.5s;
  background-color: #d3d862;
  box-shadow: inset 0 -3px 0 #a3993a, inset 0 1px 0 #ecefa6, inset 0 0 0 2px #f6dc8a66, 0 10px 22px -10px #010a09b3;
}
.game-layout:has(#character-wrap[data-tension="4"]) #bet-button.cashing {
  --sheen: 1.8s;
  background-color: #e8cf55;
  box-shadow: inset 0 -3px 0 #c8912d, inset 0 1px 0 #fbe9a4, inset 0 0 0 2px #f6dc8a66, 0 10px 22px -10px #010a09b3;
}
.game-layout:has(#character-wrap[data-tension="2"]) #bet-button.cashing:hover:enabled {
  background-color: #bddb6a;
  filter: brightness(1.05);
}
.game-layout:has(#character-wrap[data-tension="3"]) #bet-button.cashing:hover:enabled {
  background-color: #d3d862;
  filter: brightness(1.05);
}
.game-layout:has(#character-wrap[data-tension="4"]) #bet-button.cashing:hover:enabled {
  background-color: #e8cf55;
  filter: brightness(1.05);
}
.game-layout:has(#character-wrap[data-tension]) #bet-button.cashing:enabled::before {
  opacity: 0.45;
  background: linear-gradient(105deg, #fff0 30%, #fff4c8a6 47%, #fff0 64%);
  animation: temple-sheen var(--sheen, 5s) ease-in-out 0.6s infinite;
}
/* BET AGAIN: a gold coin (two from tier 3) rolls in from the left, stops
   left of the label (level with it, at most 30 px, so it fits the tall
   desktop button), flips once and fades; a light sweeps across and the
   button gives a deep tap. */
.temple-bet-coin {
  position: absolute;
  left: 10px;
  top: 50%;
  height: min(55%, 30px);
  aspect-ratio: 1;
  translate: 0 -50%;
  opacity: 0;
  pointer-events: none;
  animation:
    temple-bet-coin-roll 520ms cubic-bezier(0.2, 0.7, 0.3, 1) both,
    temple-fade-out 200ms 760ms forwards;
}
.temple-bet-coin.is-second {
  animation-delay: 120ms, 880ms;
}
.temple-bet-coin b {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 30%, #fffbe0 0 7%, #fffbe000 24%),
    radial-gradient(circle, #ffd95e 0 48%, #c98a1c 51% 57%, #ffd24f 60% 84%, #a86a12 89% 100%);
  animation: temple-bet-coin-flip 200ms ease-in-out 520ms;
}
.temple-bet-coin.is-second b {
  animation-delay: 640ms;
}
.temple-bet-coin b::after {
  content: "";
  position: absolute;
  left: -10%;
  top: -10%;
  width: 60%;
  aspect-ratio: 1;
  background: linear-gradient(135deg, #fff, #fff6d0);
  clip-path: polygon(50% 0, 56% 44%, 100% 50%, 56% 56%, 50% 100%, 44% 56%, 0 50%, 44% 44%);
  opacity: 0;
  animation: temple-coin-glint 400ms ease-out 480ms;
}
.temple-bet-coin.is-second b::after {
  animation-delay: 600ms;
}
@keyframes temple-bet-coin-roll {
  0% { opacity: 0; transform: translateX(-120%) rotate(-540deg); }
  12% { opacity: 1; }
  100% { opacity: 1; transform: translateX(var(--stop)) rotate(0deg); }
}
@keyframes temple-bet-coin-flip {
  0%, 100% { transform: scaleX(1); }
  50% { transform: scaleX(0.1); }
}
@keyframes temple-fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
body[data-character="temple"] #bet-button.is-rewarded {
  animation: temple-tap-deep 420ms cubic-bezier(0.3, 0.7, 0.4, 1) 760ms;
}
body[data-character="temple"] #bet-button.is-rewarded::after {
  background: linear-gradient(105deg, #fff0 30%, #ffe9a0d9 47%, #fff0 64%);
  animation: temple-sweep 520ms ease-out 700ms;
}

/* ---------- Batch 6: facet light, arrival and between-round touches ---------- */
/* Facet light. The open head carries a gold map of its low-poly planes
   (temple-croc-gild.webp, each facet one value, teeth, pads, cavity, eyes and
   nostrils left out) and the shut head a sunset sheen map
   (temple-croc-sheen-closed.webp, lit ridges and sun-facing planes). A 30 %
   stripe, skewed 20 deg, crosses the frame; its inner element holds the
   frame-sized map and moves back by the same amount (0.3 x the stripe's
   percentages, same easing), so the light stays on the facets while the
   stripe travels. Normal blending, never over the teeth, the eyes or the
   readout (they are in front). The maps load once the poses are ready. */
.temple-gild,
.temple-sheen {
  position: absolute;
  left: 0;
  top: 0;
  width: 30%;
  height: 100%;
  overflow: hidden;
  transform-origin: 0 0;
  opacity: 0;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
}
.temple-gild i,
.temple-sheen i {
  position: absolute;
  left: 0;
  top: 0;
  width: calc(100% / 0.3);
  height: 100%;
  transform-origin: 0 0;
  background: url("/assets/temple-croc-gild.webp") 0 0 / 100% 100% no-repeat;
}
.temple-sheen i {
  background-image: url("/assets/temple-croc-sheen-closed.webp");
}
.temple-gild-hold {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  background: url("/assets/temple-croc-gild.webp") 0 0 / 100% 100% no-repeat;
}
#character-wrap:not(.poses-ready) :is(.temple-gild, .temple-gild-hold, .temple-sheen) {
  display: none;
}
/* Cash-out: a band of gold crosses from the lower-left cheek to the upper-right
   brow, each facet flashing as a whole (tier 1 at 0.75, from 2x at 0.9);
   tiers 3-4 leave a faint warm afterglow (0.35) for 1.2 s, so the head stays
   jade. The band is drawn over the eye composites and rigs; the gold map is
   clear in the eye openings, so the eyes and lids keep their jade. */
#character-wrap {
  --gild-o: 0.75;
}
#character-wrap:is([data-gild="2"], [data-gild="3"], [data-gild="4"]) {
  --gild-o: 0.9;
}
#character-wrap[data-gild] .temple-gild {
  animation: temple-gild-band 650ms ease-in-out 80ms both;
}
#character-wrap[data-gild] .temple-gild i {
  animation: temple-gild-counter 650ms ease-in-out 80ms both;
}
#character-wrap:is([data-gild="3"], [data-gild="4"]) .temple-gild-hold {
  animation: temple-gild-hold 1200ms ease-out 700ms both;
}
/* Between rounds (the idle director's 'sheen'): warm sunlight runs over the
   shut head from the right, peak 0.85. The head never moves. */
#character-wrap.is-sheening .temple-sheen {
  animation: temple-sheen-band 1400ms ease-in-out both;
}
#character-wrap.is-sheening .temple-sheen i {
  animation: temple-sheen-counter 1400ms ease-in-out both;
}
@keyframes temple-gild-band {
  0% { opacity: var(--gild-o); transform: translateX(-245%) skewX(20deg); }
  90% { opacity: var(--gild-o); }
  100% { opacity: 0; transform: translateX(340%) skewX(20deg); }
}
@keyframes temple-gild-counter {
  0% { transform: skewX(-20deg) translateX(73.5%); }
  100% { transform: skewX(-20deg) translateX(-102%); }
}
@keyframes temple-gild-hold {
  0% { opacity: 0; }
  20% { opacity: 0.35; }
  45% { opacity: 0.35; }
  100% { opacity: 0; }
}
@keyframes temple-sheen-band {
  0% { opacity: 0.85; transform: translateX(340%) skewX(-20deg); }
  90% { opacity: 0.85; }
  100% { opacity: 0; transform: translateX(-245%) skewX(-20deg); }
}
@keyframes temple-sheen-counter {
  0% { transform: skewX(20deg) translateX(-102%); }
  100% { transform: skewX(20deg) translateX(73.5%); }
}

/* Arrival (first load, .is-arriving on the layout for 1.7 s): the island, the
   head, its contact shadow and Deep's rim rise together out of the water by
   0.12 head widths, so the seating never changes and the jaw never crosses
   the waterline (--isle-drop is 0.18 or more). A mask cuts the island and the
   rim at the screen's waterline while they rise (the rim's clip-path stays):
   --cut is the rise plus the sprite's own water band below its foam line
   (--foam of its height), scaled with the rise, so it is 0 at rest. */
@property --rise {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}
body[data-character="temple"] .game-layout {
  --foam: 0.82;
}
body[data-isle] .game-layout {
  --foam: 0.83;
}
/* The rise itself animates translate (on the compositor); only the island
   and the rim, which cut at the waterline, animate --rise, which does not
   inherit, so no other element restyles on each frame. */
.game-layout.is-arriving .character-space {
  animation: temple-rise-move 900ms cubic-bezier(0.22, 0.8, 0.3, 1) both;
}
@keyframes temple-rise-move {
  from { translate: 0 calc(var(--croc-w) * 0.12); }
  to { translate: 0 0; }
}
.game-layout.is-arriving :is(.temple-island, .temple-rim) {
  animation: temple-rise 900ms cubic-bezier(0.22, 0.8, 0.3, 1) both;
  --cut: calc(var(--rise) * (1 + (1 - var(--foam)) * 2.34875 * var(--isle-scale)));
  -webkit-mask-image: linear-gradient(to top, transparent var(--cut), #000 calc(var(--cut) + 6px));
  mask-image: linear-gradient(to top, transparent var(--cut), #000 calc(var(--cut) + 6px));
}
@keyframes temple-rise {
  from { --rise: calc(var(--croc-w) * 0.12); }
  to { --rise: 0px; }
}
/* Until the poses are ready the island waits hidden, so it never sits at rest
   and then jumps down to rise (the 4 s fallback reveal still applies). */
@media (prefers-reduced-motion: no-preference) {
  .game-layout:not(.is-still) .character-space:has(> .character-wrap:not(.poses-ready)) :is(.temple-island, .temple-rim) {
    opacity: 0;
  }
}
/* The rings spread from the rising island, water runs off the lip, the idle
   readout fades in above the head once it has risen, and the panel's rows
   rise one after another (never .bet-panel itself). */
.game-layout.is-arriving .temple-bite-ripples span {
  animation: temple-bite-ripple 0.9s 0.35s ease-out both;
}
.game-layout.is-arriving .temple-bite-ripples span:nth-child(2) {
  animation-delay: 0.55s;
}
.game-layout.is-arriving .croc-splash span {
  animation: temple-shed 600ms 500ms ease-in both;
}
/* They start on the shut jaw's lip (its seam is at 64.7 % of the frame),
   at uneven heights and moments, so they read as water running off it
   rather than two rows of drops. */
.game-layout.is-arriving .croc-splash span:nth-child(1) { top: 66%; animation-delay: 540ms; }
.game-layout.is-arriving .croc-splash span:nth-child(2) { top: 70.5%; animation-delay: 650ms; }
.game-layout.is-arriving .croc-splash span:nth-child(3) { top: 74%; animation-delay: 580ms; }
.game-layout.is-arriving .croc-splash span:nth-child(4) { top: 72.5%; animation-delay: 700ms; }
.game-layout.is-arriving .croc-splash span:nth-child(5) { top: 68.5%; animation-delay: 520ms; }
.game-layout.is-arriving .croc-splash span:nth-child(6) { top: 65.5%; animation-delay: 620ms; }
.game-layout.is-arriving .temple-readout {
  animation: temple-fade-in 250ms 900ms both;
}
.game-layout.is-arriving .bet-controls > * {
  animation: temple-panel-in 420ms cubic-bezier(0.2, 0.8, 0.3, 1) calc(200ms + var(--pi, 0) * 60ms) both;
}
@keyframes temple-shed {
  0% { opacity: 0; transform: translateY(0); }
  15% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(calc(var(--croc-w) * 0.06)); }
}
@keyframes temple-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes temple-panel-in {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: none; }
}

/* A new risk level between rounds (temple-character.js, only at idle on the
   shut head): Easy breathes out (.is-exhaling), Medium gives a sharp double
   sniff from the shut nostrils, Hard sniffs and leans in about the jaw and
   back. The hint flips over and the Next tooth figure counts to its value. */
.is-sniffing .temple-snort {
  --o: 0.7;
  animation: temple-puff 640ms cubic-bezier(0.08, 0.8, 0.3, 1) var(--d) both;
}
body[data-character="temple"] .is-leaning #character-motion {
  animation: temple-lean 280ms ease-out;
}
body[data-character="temple"] #risk-hint.is-flipping {
  display: inline-block;
  animation: temple-hint-flip 200ms ease-out;
}
@keyframes temple-lean {
  0% { transform: none; }
  40% { transform: translateY(-0.8%) scale(1.012); }
  100% { transform: none; }
}
@keyframes temple-hint-flip {
  0% { transform: rotateX(90deg); }
  100% { transform: none; }
}

/* The logo's crocodile echoes the big one: it chomps on hover, chomps and
   squashes just after a bite lands, and winks as a cash-out's coins fly past
   to the wallet. */
body[data-character="temple"] .brand svg :is(path, circle) {
  transform-box: fill-box;
  transform-origin: 50% 100%;
}
@media (hover: hover) {
  body[data-character="temple"] .brand:hover svg path:nth-of-type(3) {
    animation: temple-mini-chomp 260ms ease-in-out 2;
  }
}
body[data-character="temple"] .game-layout:has(#character-wrap.is-impact) .brand svg path:nth-of-type(3) {
  animation: temple-mini-chomp 220ms ease-out 290ms;
}
body[data-character="temple"] .game-layout:has(#character-wrap.is-impact) .brand svg path:nth-of-type(1) {
  animation: temple-mini-squash 220ms ease-out 290ms;
}
body[data-character="temple"] .game-layout:has(#character-wrap:is([data-win], [data-gild])) .brand svg circle:nth-of-type(2) {
  transform-origin: 50% 50%;
  animation: temple-mini-wink 180ms ease-in-out 700ms;
}
@keyframes temple-mini-chomp {
  0%, 100% { transform: none; }
  50% { transform: translateY(-2px); }
}
@keyframes temple-mini-squash {
  0%, 100% { transform: none; }
  50% { transform: scale(1.03, 0.94); }
}
@keyframes temple-mini-wink {
  0%, 100% { transform: none; }
  50% { transform: scaleY(0.15); }
}

/* Far-water life (temple-life.js): a scenery layer right after the far-water
   specks, masked off the island, so the island, the head, the readout and the
   top bar are all in front. It is a size container over the picture (1cqw /
   1cqh = 1 % of it). Everything starts and ends at opacity 0, so the pause,
   which freezes it, never leaves a creature half-drawn at its start. */
.temple-fauna {
  position: absolute;
  inset: 0;
  container-type: size;
  overflow: hidden;
  pointer-events: none;
  transition: opacity 300ms ease-out;
  -webkit-mask-image: var(--island-hole);
  mask-image: var(--island-hole);
}
/* A creature still crossing when a bite winds up dims for the drama, so
   the crocodile keeps the eye. */
.temple-fauna.is-hushed {
  opacity: 0.3;
}
.temple-fauna svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
/* Carp: 2 % of the picture, leaping out of the water and back in 720 ms on
   split axes (outer x linear, inner y eased up then down, innermost the
   pitch), flicking its tail four times. It is cut at the water surface. */
.temple-leap {
  position: absolute;
  width: 0;
  height: 0;
  transform: scaleX(var(--dir, 1));
}
.temple-leap-clip {
  position: absolute;
  left: -5cqw;
  bottom: 0;
  width: 10cqw;
  height: 9cqh;
  overflow: hidden;
}
.temple-leap-x {
  position: absolute;
  left: calc(50% - 1cqw);
  bottom: 0;
  width: 2cqw;
  height: 1cqw;
  opacity: 0;
  animation: temple-leap-x 720ms linear 120ms both;
}
.temple-leap-y {
  width: 100%;
  height: 100%;
  animation: temple-leap-y 720ms 120ms both;
}
.temple-leap-r {
  width: 100%;
  height: 100%;
  transform-origin: 60% 52%;
  animation: temple-leap-r 720ms ease-in-out 120ms both;
}
.temple-leap .temple-carp-tail {
  animation: temple-carp-flick 180ms ease-in-out 120ms 4;
}
@keyframes temple-leap-x {
  0% { opacity: 1; transform: translateX(-1.6cqw); }
  99% { opacity: 1; }
  100% { opacity: 0; transform: translateX(1.6cqw); }
}
@keyframes temple-leap-y {
  0% { transform: translateY(1.7cqw); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  45.8% { transform: translateY(-3.6cqh); animation-timing-function: cubic-bezier(0.6, 0, 0.8, 0.3); }
  100% { transform: translateY(1.7cqw); }
}
@keyframes temple-leap-r {
  0% { transform: rotate(-40deg); }
  100% { transform: rotate(50deg); }
}
@keyframes temple-carp-flick {
  0%, 100% { transform: scaleX(1); }
  50% { transform: scaleX(0.8); }
}
/* Teardrops: three burst up as the carp breaks the surface, a crown of seven
   where it falls back, each thrown up and pulled down again. */
.temple-drop-fly {
  position: absolute;
  left: calc(var(--x0) - 0.14cqw);
  top: -0.4cqw;
  width: 0.28cqw;
  opacity: 0;
  /* forwards, not both: the drops wait at their base opacity 0 until the
     splash instead of sitting on the water from the start of the leap. */
  animation: temple-drop-arc var(--t) var(--d) forwards;
}
@keyframes temple-drop-arc {
  0% { opacity: 0.95; transform: translate(0, 0) rotate(var(--r)); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  45% { transform: translate(calc(var(--dx) * 0.55), calc(-1 * var(--h))) rotate(var(--r)); animation-timing-function: cubic-bezier(0.6, 0, 0.9, 0.4); }
  75% { opacity: 0.85; }
  100% { opacity: 0; transform: translate(var(--dx), calc(var(--h) * 0.25)) rotate(calc(var(--r) * 2)); }
}
/* Two thin foam crescents widen where it falls back in (never a ring). */
.temple-foam-arc {
  position: absolute;
  left: 0.2cqw;
  top: -0.3cqw;
  width: 2.8cqw;
  opacity: 0;
  transform-origin: 50% 25%;
  animation: temple-foam-arc 600ms ease-out 840ms forwards;
}
.temple-foam-arc.is-second {
  left: 0.6cqw;
  top: 0.1cqw;
  width: 2cqw;
  animation: temple-foam-arc-late 600ms ease-out 960ms forwards;
}
@keyframes temple-foam-arc {
  0% { opacity: 0.8; transform: scaleX(0.4); }
  100% { opacity: 0; transform: scaleX(1.2); }
}
@keyframes temple-foam-arc-late {
  0% { opacity: 0.7; transform: scaleX(0.4); }
  100% { opacity: 0; transform: scaleX(1.15); }
}
/* Egrets (a loose V of four) or three fruit bats cross the sky from right to
   left, high above the head and the idle readout: 14 s, bats 9 s. Egret wings
   beat 380 ms a stroke with a 900 ms glide every 2.5 s, the far wing 40 ms
   behind; bats beat deep and fast on a jittery path. */
.temple-flock {
  position: absolute;
  left: 100%;
  width: 12cqw;
  height: 6cqh;
  opacity: 0;
  animation: temple-flock-cross var(--t) linear both;
}
.temple-bird {
  position: absolute;
  animation: temple-bird-bob 2.6s ease-in-out var(--beat) infinite alternate;
}
.temple-flock .temple-egret-near {
  animation: temple-egret-beat 2.5s ease-in-out var(--beat) infinite;
}
.temple-flock .temple-egret-far {
  animation: temple-egret-beat 2.5s ease-in-out calc(var(--beat) + 40ms) infinite;
}
.temple-flock.is-bats .temple-bird {
  animation: temple-bat-jitter 1.3s ease-in-out var(--beat) infinite;
}
.temple-flock .temple-bat-left {
  animation: temple-bat-left 440ms ease-in-out var(--beat) infinite;
}
.temple-flock .temple-bat-right {
  animation: temple-bat-right 440ms ease-in-out var(--beat) infinite;
}
@keyframes temple-flock-cross {
  0% { opacity: 0; transform: translate(0, 0); }
  3% { opacity: 1; }
  97% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-100cqw - 16cqw), var(--dy)); }
}
@keyframes temple-bird-bob {
  0% { transform: translateY(0); }
  100% { transform: translateY(0.6cqh); }
}
@keyframes temple-egret-beat {
  0% { transform: rotate(0deg); }
  7.6% { transform: rotate(-32deg); }
  22.8% { transform: rotate(32deg); }
  38% { transform: rotate(-32deg); }
  53.2% { transform: rotate(32deg); }
  64% { transform: rotate(0deg); }
  100% { transform: rotate(0deg); }
}
@keyframes temple-bat-left {
  0%, 100% { transform: rotate(38deg); }
  50% { transform: rotate(-30deg); }
}
@keyframes temple-bat-right {
  0%, 100% { transform: rotate(-38deg); }
  50% { transform: rotate(30deg); }
}
@keyframes temple-bat-jitter {
  0%, 100% { transform: translate(0, 0); }
  23% { transform: translate(-0.3cqw, -0.9cqh); }
  41% { transform: translate(0.2cqw, 0.4cqh); }
  67% { transform: translate(-0.2cqw, -0.5cqh); }
  84% { transform: translate(0.3cqw, 0.7cqh); }
}
/* Portrait: the island is wider than the screen, so no carp leaps. */
@media (orientation: portrait) {
  .temple-leap {
    display: none;
  }
}

/* ---------- Still: scenery pause, reduced motion, hidden tab ---------- */
/* temple-character.js mirrors its still() on the layout as .is-still and
   starts none of the reactions above then; these rules also stop any a class
   change would start. The pressed tooth falls back to the plain 150 ms sink.
   Heat colours and ember rims are states and stay. */
.game-layout.is-still :is(.tooth.just-picked, .is-rattling .tooth, .is-rearming .tooth, .tooth:not(.is-trap):active) .tooth-sprite,
.game-layout.is-still .temple-head,
.game-layout.is-still .temple-readout :is(#current-multiplier, .next-multiplier, #next-multiplier),
.game-layout.is-still .temple-ember,
.game-layout.is-still .temple-pick-ripples span,
.game-layout.is-still .is-opening #character-motion,
.game-layout.is-still .is-nodding:not(.biting) .character-breathe,
.game-layout.is-still .is-shining .tooth:not(.picked, .is-trap) .tooth-sprite,
.game-layout.is-still :is(.tooth-shine, .tooth-spark),
.game-layout.is-still :is(.jungle-background, .character-space),
.game-layout.is-still.is-jolted :is(.bet-controls, .quick-bets button),
.game-layout.is-still .temple-readout .scoreboard,
.game-layout.is-still .snap-word :is(span, .snap-crack),
.game-layout.is-still .is-chewing #character-motion,
.game-layout.is-still .temple-huff,
.game-layout.is-still :is(.temple-sigh, .temple-snort, .temple-jet, .croc-splash span),
.game-layout.is-still :is(.vein-seg, .vein-tip, .temple-veins),
.game-layout.is-still #bet-button.is-inviting::after {
  animation: none !important;
}
.game-layout.is-still .temple-flare {
  display: none;
}
/* The hover and focus preview lifts and underlines the next value at once
   (the readout keeps its pose-swap delay). */
body[data-character="temple"] .game-layout.is-still .game-board.playing #next-multiplier {
  transition: all 0s 90ms, transform 0s, color 0s;
}
.game-layout.is-still #next-multiplier::after {
  transition: none !important;
}
/* The bite drama's layers (turning still also removes .is-impact). */
.game-layout.is-still :is(.temple-chips, .temple-crushed, .temple-drips, .tooth-crack) {
  display: none !important;
}
/* Batch 4: the grit, the seat, the glints, the dust and the crowns are
   effect layers; the veins appear without growing. */
.game-layout.is-still :is(.tooth-grit, .tooth-seat, .temple-glint, .temple-fang-glint, .temple-dust, .temple-splashes) {
  display: none;
}
/* The eye rig (batch 5): the painted eyes stay; no sweat, no pfft. */
.game-layout.is-still :is(.temple-rig, .temple-sweat, .temple-pfft) {
  display: none;
}
/* Batch 6: the facet light is hidden; the risk reactions, the hint flip and
   the logo hold still. The far-water life is scenery: the pause freezes it. */
.game-layout.is-still :is(.temple-gild, .temple-gild-hold, .temple-sheen) {
  display: none;
}
.game-layout.is-still :is(.is-leaning #character-motion, .is-sniffing .temple-snort, #risk-hint, .brand svg *) {
  animation: none !important;
}
/* Batch 3: no data-win is set while still, and turning still removes it
   (the hop keeps its data-hop, see above); the $ and the bet button's
   sheens hold still, and the new layers are hidden. */
.game-layout.is-still #bet-button,
.game-layout.is-still #bet-button::before,
.game-layout.is-still #bet-button::after,
.game-layout.is-still .wallet .currency {
  animation: none !important;
}
.game-layout.is-still :is(.temple-ring, .temple-win-glints, .temple-coin[data-w], .temple-gem, .temple-coin-far, .temple-coin-splash, .temple-bet-coin, .temple-spend, .temple-wallet-arc) {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .temple-loop {
    display: none;
  }
  body[data-character="temple"] .temple-open,
  body[data-character="temple"] .temple-closed,
  body[data-character="temple"] .temple-bite,
  body[data-character="temple"] .temple-reflection-poses img,
  body[data-character="temple"] .temple-readout,
  body[data-character="temple"] .temple-readout *,
  body[data-character="temple"] .tooth-sprite,
  body[data-character="temple"] .tooth-pad,
  .temple-eye {
    transition: none !important;
  }
  body[data-character="temple"] .temple-contact,
  .temple-head,
  body[data-character="temple"] .tooth-sprite {
    animation: none !important;
  }
  .temple-steam,
  .temple-coins,
  .temple-rays,
  .tooth-spark {
    display: none;
  }
  body[data-character="temple"] :is(.bet-panel, .topbar) button,
  body[data-character="temple"] .risk-options span,
  body[data-character="temple"] #bet-button::before,
  body[data-character="temple"] #bet-button::after {
    animation: none !important;
  }
  body[data-character="temple"] .wallet,
  body[data-character="temple"] .wallet strong,
  body[data-character="temple"] #current-multiplier {
    animation: none !important;
  }
  /* The tooth-pick reactions: the flare is hidden, the next-tooth line and
     its hover underline hold still (the heat colours and embers stay). */
  .temple-flare {
    display: none;
  }
  body[data-character="temple"] .next-multiplier,
  body[data-character="temple"] #next-multiplier,
  body[data-character="temple"] .temple-ember {
    animation: none !important;
    transition: none !important;
  }
  body[data-character="temple"] #next-multiplier::after {
    transition: none !important;
  }
  /* The shine's stripes never show (the shine does not start when still). */
  .tooth-shine {
    display: none;
  }
  /* The bite drama: no thump, cowering, jolt or letter slam, and none of its
     layers (styles.css shows CHOMP! still, in the jade letters). */
  body[data-character="temple"] :is(.jungle-background, .character-space),
  body[data-character="temple"] .temple-readout .scoreboard,
  body[data-character="temple"] .bet-controls,
  body[data-character="temple"] .snap-word :is(span, .snap-crack) {
    animation: none !important;
  }
  .temple-chips,
  .temple-crushed,
  .temple-drips,
  .tooth-crack {
    display: none !important;
  }
  /* Batch 4: no grit, seat, glints, dust or crowns; the veins appear
     without growing, flickering or melting. */
  .tooth-grit,
  .tooth-seat,
  .temple-glint,
  .temple-fang-glint,
  .temple-dust,
  .temple-splashes {
    display: none;
  }
  .vein-seg,
  .vein-tip,
  .temple-veins {
    animation: none !important;
  }
  /* The eye rig (batch 5): the painted eyes, no sweat drop. */
  .temple-rig,
  .temple-sweat {
    display: none;
  }
  /* Batch 6: no facet light, no far-water life, no risk reactions and a
     still logo (the arrival never starts). */
  .temple-gild,
  .temple-gild-hold,
  .temple-sheen,
  .temple-fauna {
    display: none;
  }
  body[data-character="temple"] .brand svg *,
  body[data-character="temple"] #risk-hint,
  body[data-character="temple"] .is-leaning #character-motion,
  .is-sniffing .temple-snort {
    animation: none !important;
  }
  /* Batch 3: the new cash-out layers are hidden and the wallet's $ and the
     bet button hold still (the ripened colours stay). */
  .temple-win-glints,
  .temple-bet-coin,
  .temple-spend,
  .temple-wallet-arc {
    display: none;
  }
  body[data-character="temple"] .wallet .currency,
  body[data-character="temple"] #bet-button {
    animation: none !important;
    transition: none !important;
  }
}
