/* Cells board (shared by grid-pipeline games): a field of cells placed and moved by transform only and faded by opacity
   only (64 cells stay smooth), a layer over it for floaters and the modules' overlays (presenters), and per-cell badges
   that ride with their cell. Every animated property is transform or opacity; glows and rings are static paint whose
   opacity changes. Colours and decoration come from the game's skin: --window-bg, --window-radius, --reel-sep (the cell
   lines), --sym-size, --cluster-radius, --win-ring, --win-glow, --hot-ring, --land-ring, --tease-glow, --fs-ring,
   --fall-ease, --badge-bg, --badge-ink, --float-ink, --float-stroke. cells.js sets --cs-pop and --cs-recode (turbo, and
   at once when a tap hurries the spin). The message line needs no spacing rule: cells.js puts real spaces between its
   parts (a flex message drops them and keeps its gap; an inline one shows them). */
.cells-board{position:relative;width:calc(var(--cell)*var(--cols,6));height:calc(var(--cell)*var(--rows,6))}
.cells-board .cs-field{position:absolute;inset:0;overflow:hidden;contain:layout paint;border-radius:var(--window-radius,10px);background:var(--window-bg,rgba(0,0,0,.6))}
/* the cell lines: one line at the right edge of every column and row (static) */
.cells-board .cs-field::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,transparent calc(var(--cell) - 1px),var(--reel-sep,rgba(255,255,255,.06)) 0) 0 0/var(--cell) 100%,
    linear-gradient(180deg,transparent calc(var(--cell) - 1px),var(--reel-sep,rgba(255,255,255,.04)) 0) 0 0/100% var(--cell)}
.cells-board.feature .cs-field{box-shadow:inset 0 0 0 2px var(--fs-ring,transparent)}
.cells-board .cell{position:absolute;left:0;top:0;width:var(--cell);height:var(--cell);display:flex;align-items:center;justify-content:center;will-change:transform;backface-visibility:hidden}
/* fixed cells (blockers, held cells) while a collapse slides, and the cells presenters hold through a spin's drop
   (cells.js hold hook): the cells passing them go behind */
.cells-board .cell.stay{z-index:1}
.cells-board .face{position:relative;width:var(--sym-size,88%);height:var(--sym-size,88%);transition:transform .2s,opacity .2s}
.cells-board .face>.sym{position:relative;width:100%;height:100%}
.cells-board .sym img{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none;-webkit-user-drag:none}
/* a winning cell: a ring that breathes (opacity) and a slightly larger symbol; marking dims the cells that do not pay */
.cells-board .cell.win{z-index:2}
.cells-board .cell.win::before,.cells-board .cell.hot::before{content:"";position:absolute;inset:4%;border-radius:var(--cluster-radius,16%);pointer-events:none}
.cells-board .cell.win::before{border:2px solid var(--win-ring,var(--primary-hi,#fff));box-shadow:0 0 12px var(--win-glow,var(--primary,#f5c542)),inset 0 0 10px var(--win-glow,var(--primary,#f5c542));will-change:opacity;animation:cs-ring .45s ease-in-out infinite alternate}
.cells-board .cell.hot:not(.win)::before{box-shadow:inset 0 0 0 2px var(--hot-ring,var(--accent,#fff))}
.cells-board .cell.win .face{transform:scale(1.08)}
.cells-board.marking .cell:not(.win) .face{opacity:.4}
/* the cells a step empties (their badges go with them) */
.cells-board .cell.pop{z-index:2}
.cells-board .cell.pop::before{display:none}
.cells-board .cell.pop .face,.cells-board .cell.pop .badge{transform:scale(1.35);opacity:0;transition:transform var(--cs-pop,.26s) ease-out,opacity var(--cs-pop,.26s) ease-out}
/* one-shot: a recoded symbol grows in, a still-mode cell fades in, a landed scatter pulses once with a halo */
.cells-board .cell.recode .face{animation:cs-recode var(--cs-recode,.28s) cubic-bezier(.2,1.3,.4,1)}
.cells-board .cell.fadein .face{animation:cs-fade .12s linear}
.cells-board .cell.land .face{animation:cs-land .5s ease-out}
.cells-board .cell.land::after{content:"";position:absolute;inset:6%;border-radius:50%;border:2px solid var(--land-ring,var(--accent,#fff));opacity:0;pointer-events:none;animation:cs-halo .6s ease-out}
/* the scatter tease: an inner glow over the field (opacity only) */
.cells-board .cs-field::after{content:"";position:absolute;inset:0;z-index:4;pointer-events:none;border-radius:inherit;box-shadow:inset 0 0 calc(var(--cell)*.45) var(--tease-glow,var(--accent,#ffd86a));opacity:0;transition:opacity .25s;will-change:opacity}
.cells-board.tease .cs-field::after{opacity:1;animation:cs-tease .6s ease-in-out infinite alternate}
/* per-cell badges (presenters): placed by the game's skin per layer (.b-<layer>); a plain default, top right */
.cells-board .badge{position:absolute;z-index:3;pointer-events:none}
:where(.cells-board .badge){right:3%;top:3%;min-width:28%;padding:0 .28em;border-radius:999px;display:grid;place-items:center;
  font:800 calc(var(--cell)*.17)/1.35 var(--ui,system-ui);color:var(--badge-ink,#fff);background:var(--badge-bg,rgba(0,0,0,.75));font-variant-numeric:tabular-nums}
/* the layer over the field: floaters and the presenters' overlays (placed by transform, sized by --cell) */
.cells-board .cs-over{position:absolute;inset:0;z-index:5;pointer-events:none}
.cells-board .cs-layer{position:absolute;inset:0}
.cells-board .cs-layer>*{position:absolute;left:0;top:0}
.cells-board .cs-float{position:absolute;transform:translate(-50%,-50%);white-space:nowrap;font:800 calc(var(--cell)*.3)/1 var(--ui,system-ui);color:var(--float-ink,#fff);
  -webkit-text-stroke:calc(var(--cell)*.02) var(--float-stroke,#000);paint-order:stroke fill;text-shadow:0 0 12px var(--win-glow,var(--primary,#f5c542));animation:cs-float 1.2s cubic-bezier(.2,.8,.3,1) forwards}
.cells-board .cs-float.m{font-size:calc(var(--cell)*.42)}
@keyframes cs-ring{from{opacity:.55}to{opacity:1}}
@keyframes cs-recode{0%{opacity:0;transform:scale(.6)}100%{opacity:1;transform:none}}
@keyframes cs-fade{from{opacity:0}to{opacity:1}}
@keyframes cs-land{0%{transform:scale(1.25)}100%{transform:none}}
@keyframes cs-halo{0%{opacity:.9;transform:scale(.7)}100%{opacity:0;transform:scale(1.35)}}
@keyframes cs-tease{from{opacity:.6}to{opacity:1}}
@keyframes cs-float{0%{opacity:0;transform:translate(-50%,-30%) scale(.6)}18%{opacity:1;transform:translate(-50%,-50%) scale(1.1)}70%{opacity:1}100%{opacity:0;transform:translate(-50%,-110%) scale(1)}}
/* reduced motion: nothing pulses, grows, bounces or rises — changes fade (≤ 120 ms); cells.js moves nothing either.
   shell.css caps every animation and transition on top of this */
body.still .cells-board .cell.win::before,body.still .cells-board.tease .cs-field::after{animation:none}
body.still .cells-board .face,body.still .cells-board .cs-field::after{transition-duration:.12s}
body.still .cells-board .cell.win .face{transform:none}
body.still .cells-board .cell.pop .face,body.still .cells-board .cell.pop .badge{transform:none;transition:opacity .12s linear}
body.still .cells-board .cell.recode .face,body.still .cells-board .cell.land .face,body.still .cells-board .cs-float{animation:cs-fade .12s linear}
body.still .cells-board .cell.land::after{display:none}
@media (prefers-reduced-motion:reduce){
  .cells-board .cell.win::before,.cells-board.tease .cs-field::after{animation:none}
  .cells-board .face,.cells-board .cs-field::after{transition-duration:.12s}
  .cells-board .cell.win .face{transform:none}
  .cells-board .cell.pop .face,.cells-board .cell.pop .badge{transform:none;transition:opacity .12s linear}
  .cells-board .cell.recode .face,.cells-board .cell.land .face,.cells-board .cs-float{animation:cs-fade .12s linear}
  .cells-board .cell.land::after{display:none}
}
