/* =============================================================================
   _casino.css — THE FLOOR (2026-08-10)

   _term.css owns the world: ground, frame, type scale, ink stacks, panels.
   _seq.css owns the header cluster and the sound switch. NOTHING here restates
   a token either of them already defines.

   THE COLOUR LAW IS HIS, AND A CASINO DOES NOT GET AN EXEMPTION.
   Headings, names and values are #79D9FF over #4BB4FC over #2C84EE. Never
   near-white. Green is ONLINE-class state, amber is caution, red is a refusal.
   So on this floor:
       green   a win, a safe locus, a kill — a good state, not a colour of money
       amber   live and at risk: a chase in flight, an open strand, a pot up
       red     a loss, a lethal allele, the moment the prey breaks away
   There is no gold and no felt green. A casino that looked like a casino would
   look like a different website.

   MOTION IS TRANSFORM AND OPACITY ONLY, so nothing here costs layout, and every
   animation has a `prefers-reduced-motion` answer that is STILL LEGIBLE — a
   reduced-motion player must be told the result, not shown a still frame of it.
   ========================================================================= */

/* ---------- the rail ------------------------------------------------------ */
.cas-rail{display:flex;align-items:stretch;gap:0;margin:0 var(--pad) 14px;
  border:1px solid var(--rule);background:rgba(1,4,10,.62);
  box-shadow:inset 3px 0 0 rgba(75,180,252,.55)}
.cas-rail > *{display:flex;flex-direction:column;justify-content:center;gap:3px;
  padding:9px 16px;border-right:1px solid rgba(30,111,224,.4);min-width:0}
.cas-rail > *:last-child{border-right:0}
.cas-rail .lab{font-family:var(--pixel);font-size:10.5px;letter-spacing:.14em;
  color:var(--blue-dim);text-shadow:var(--sh-micro)}
.cas-rail b{font-family:var(--mono);font-weight:400;font-size:19px;color:#79D9FF;
  text-shadow:var(--sh-body);letter-spacing:.02em;font-variant-numeric:tabular-nums}
.rail-bal{position:relative}
.rail-bal b{font-size:26px;line-height:1.05}
/* the delta floats off the balance so a win is felt, not merely reported */
.rail-bal .delta{position:absolute;right:10px;top:4px;font-family:var(--pixel);
  font-size:12px;letter-spacing:.06em;opacity:0;pointer-events:none;
  text-shadow:var(--sh-micro)}
.rail-bal .delta.up{color:var(--green)}
.rail-bal .delta.down{color:var(--red)}
.rail-bal .delta.show{animation:deltafly 1.15s cubic-bezier(.2,.8,.2,1) forwards}
@keyframes deltafly{
  0%{opacity:0;transform:translateY(6px)}
  18%{opacity:1;transform:translateY(0)}
  70%{opacity:1;transform:translateY(-8px)}
  100%{opacity:0;transform:translateY(-16px)}}
/* the balance itself ticks when it changes, so the eye is drawn to the number */
.rail-bal b.tick{animation:baltick .42s ease-out}
@keyframes baltick{0%{transform:scale(1)}38%{transform:scale(1.09)}100%{transform:scale(1)}}
.rail-band b{font-size:14px;color:var(--blue)}
.rail-fair{margin-left:auto;background:transparent;border:0;border-left:1px solid rgba(30,111,224,.4);
  cursor:pointer;text-align:left;font:inherit;transition:background .15s linear}
.rail-fair:hover{background:rgba(30,111,224,.12)}
.rail-fair b{font-size:12.5px;color:var(--blue);letter-spacing:.06em}
.rail-fair .lab{color:var(--green)}

@media(max-width:760px){
  .cas-rail{flex-wrap:wrap}
  .cas-rail > *{border-right:0;border-bottom:1px solid rgba(30,111,224,.28);flex:1 1 46%}
  .rail-fair{margin-left:0;border-left:0;flex-basis:100%}
}

/* ---------- signed out ---------------------------------------------------- */
.cas-gate{margin:0 var(--pad) 18px;padding:26px 20px;border:1px solid var(--rule);
  background:rgba(1,4,10,.62);display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.cas-gate p{margin:0;color:var(--blue);font-size:var(--t-body);text-shadow:var(--sh-body)}

/* ---------- the picker: two families -------------------------------------- */
.cas-pick{display:flex;gap:14px;margin:0 var(--pad) 16px;flex-wrap:wrap}
.fam{flex:1 1 340px;min-width:0;border:1px solid var(--rule);background:rgba(1,4,10,.5);
  padding:9px 10px 10px;position:relative}
.famlab{display:block;font-family:var(--pixel);font-size:10.5px;letter-spacing:.2em;
  color:var(--blue-dim);text-shadow:var(--sh-micro);margin:0 0 8px 2px}
.fam[data-fam="fight"]{box-shadow:inset 3px 0 0 rgba(255,90,90,.45)}
.fam[data-fam="mutation"]{box-shadow:inset 3px 0 0 rgba(91,255,166,.4)}
.tiles{display:flex;gap:8px}
.tiles button{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;
  gap:6px;padding:11px 6px 9px;cursor:pointer;background:transparent;
  border:1px solid rgba(75,180,252,.28);color:var(--blue-dim);
  box-shadow:0 0 0 1px rgba(1,5,11,.9);position:relative;
  transition:border-color .15s linear,color .15s linear,transform .18s cubic-bezier(.2,.8,.2,1)}
.tiles button:hover{border-color:#79D9FF;color:#79D9FF;transform:translateY(-2px)}
.tiles button[aria-selected="true"]{border-color:#79D9FF;color:#79D9FF;
  background:rgba(30,111,224,.14)}
/* the selected tile grows a bracket, the same mark every other control uses */
.tiles button[aria-selected="true"]::before,
.tiles button[aria-selected="true"]::after{content:"";position:absolute;width:7px;height:7px;
  border:1px solid var(--blue-hot)}
.tiles button[aria-selected="true"]::before{left:-1px;top:-1px;border-right:0;border-bottom:0}
.tiles button[aria-selected="true"]::after{right:-1px;bottom:-1px;border-left:0;border-top:0}
.tiles b{font-family:var(--pixel);font-size:11px;letter-spacing:.09em;font-weight:400;
  text-shadow:var(--sh-micro);white-space:nowrap;color:inherit}
.tiles em{font-style:normal;font-family:var(--mono);font-size:10px;letter-spacing:.05em;
  color:var(--blue-dim);opacity:.85}
/* ★ MEASURED, NOT GUESSED: the `filter: drop-shadow()` that used to sit here
   cost ~4% OF A CORE while anything animated under it. The five tiles now carry
   ANIMATED marks (`js/gameicons.mjs`), so the filter was recompositing five
   permanently-moving elements every frame for a 1.2px halo.
   The separation it was buying is bought instead by a STATIC plate painted
   behind the art — one paint, never re-evaluated, and darker than the filter
   ever managed. The general rule the same measurement gave, which everything
   on this page now follows: transform and opacity are effectively free (0.2%);
   an animated filter, a `stroke-dashoffset` (9.9% for ONE dashed line, 26%
   overall) and a `url(#…)` reference are not. */
.tiles .cf-art{width:46px;height:30px;display:block;color:inherit;
  background:radial-gradient(62% 74% at 50% 54%,rgba(1,5,11,.96),rgba(1,5,11,0) 74%)}
.tiles .cf-art svg{width:100%;height:100%;display:block;overflow:visible}
.tiles button.shut{opacity:.4;pointer-events:none}

@media(max-width:560px){
  .tiles{flex-wrap:wrap}
  .tiles button{flex:1 1 46%}
}


/* ---------- the drawn animals --------------------------------------------
   `dinoart.mjs` emits the SAME `.gs` / `.gf` parts `map-markers` uses, and
   those rules live in map.html's own <style> block - which THIS page does not
   load. Without them every silhouette fell back to the SVG default of a solid
   black fill, and six dinosaurs rendered as six black smudges on a black
   ground. The parts are declared here, UNSCOPED, for the same reason the map
   learned to declare them unscoped: a shared drawing needs shared rules, and
   scoping them to one parent is how the map's legend once drew eleven
   invisible symbols. */
.gs{fill:none;stroke:currentColor;stroke-width:2.2;stroke-linejoin:round;stroke-linecap:round}
.gf{fill:currentColor;stroke:none}

/* ---------- the stage ----------------------------------------------------- */
.cas-wrap{margin:0 var(--pad) 18px}
.cf-stage{display:flex;gap:14px;align-items:stretch}
.cf-stage[hidden]{display:none !important}
.board{flex:1 1 auto;min-width:0;position:relative;border:1px solid var(--rule);
  background:radial-gradient(120% 90% at 50% 8%,rgba(6,26,64,.55),rgba(1,4,10,.86) 62%);
  box-shadow:inset 3px 0 0 rgba(75,180,252,.55);overflow:hidden;
  min-height:clamp(320px,44vh,520px)}
.board canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.side{flex:0 0 296px;display:flex;flex-direction:column;gap:10px;min-width:0}

@media(max-width:900px){
  .cf-stage{flex-direction:column}
  .side{flex:1 1 auto;width:100%}
}

/* ---------- the control block --------------------------------------------- */
.ctl{border:1px solid var(--rule);background:rgba(1,4,10,.62);padding:11px 12px 12px;
  display:flex;flex-direction:column;gap:9px}
.ctl-row{display:flex;flex-direction:column;gap:5px}
.ctl-row > span{font-family:var(--pixel);font-size:10.5px;letter-spacing:.14em;
  color:var(--blue-dim);text-shadow:var(--sh-micro)}
.ctl input[type=number],.ctl input[type=text]{width:100%;box-sizing:border-box;
  font-family:var(--mono);font-size:16px;color:#79D9FF;background:rgba(1,5,11,.72);
  border:1px solid rgba(75,180,252,.4);padding:7px 9px;letter-spacing:.03em;
  font-variant-numeric:tabular-nums;transition:border-color .15s linear}
.ctl input:focus{outline:none;border-color:#79D9FF}
/* the browser's spinner is a different design language. It goes. */
.ctl input[type=number]::-webkit-outer-spin-button,
.ctl input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.ctl input[type=number]{-moz-appearance:textfield;appearance:textfield}

.chips{display:flex;gap:5px}
.chips button,.segs button{flex:1 1 0;min-width:0;cursor:pointer;background:transparent;
  border:1px solid rgba(75,180,252,.28);color:var(--blue-dim);padding:6px 4px;
  font-family:var(--pixel);font-size:10.5px;letter-spacing:.08em;
  box-shadow:0 0 0 1px rgba(1,5,11,.9);
  transition:border-color .13s linear,color .13s linear,background .13s linear}
.chips button:hover,.segs button:hover{border-color:#79D9FF;color:#79D9FF}
.segs{display:flex;gap:5px}
.segs.wide button{padding:7px 4px}
.segs button.cf-on{border-color:#79D9FF;color:#79D9FF;background:rgba(30,111,224,.18)}
.ctl-row.seg{flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
.ctl-row.seg > span{flex:0 0 auto}
.ctl-row.seg .segs{flex:1 1 auto}

.payline{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding:6px 0 1px;border-top:1px solid rgba(30,111,224,.32)}
.payline span{font-family:var(--pixel);font-size:10.5px;letter-spacing:.14em;color:var(--blue-dim)}
.payline b{font-family:var(--mono);font-weight:400;font-size:17px;color:var(--green);
  text-shadow:var(--sh-body);font-variant-numeric:tabular-nums}

/* THE ONE BUTTON THAT MATTERS. It is the biggest thing in the column, it never
   moves, and it says what it will do rather than "OK". */
.go{position:relative;cursor:pointer;width:100%;padding:13px 12px;margin-top:2px;
  font-family:var(--pixel);font-size:13px;letter-spacing:.13em;color:#A8E7FF;
  background:linear-gradient(180deg,rgba(30,111,224,.28),rgba(30,111,224,.1));
  border:1px solid #4BB4FC;text-shadow:var(--sh-body);
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 0 22px -12px rgba(120,220,255,.9);
  transition:border-color .14s linear,color .14s linear,transform .12s cubic-bezier(.2,.8,.2,1),
             box-shadow .18s linear}
.go:hover:not(:disabled){border-color:#A8E7FF;color:#DFF6FF;
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 0 30px -10px rgba(150,230,255,1),
             0 0 34px -14px rgba(75,180,252,.9)}
.go:active:not(:disabled){transform:translateY(1px)}
.go:disabled{opacity:.42;cursor:not-allowed}
.go.busy{color:var(--amber);border-color:var(--amber)}
/* the take/bank button is a DIFFERENT colour because it is a different decision:
   green is the safe state, and the whole game is whether you press it in time */
.go.take{background:linear-gradient(180deg,rgba(91,255,166,.2),rgba(91,255,166,.06));
  border-color:var(--green);color:#C9FFE4}
.go.take:hover:not(:disabled){border-color:#C9FFE4;color:#EAFFF4;
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 0 30px -10px rgba(120,255,190,1),
             0 0 34px -14px rgba(91,255,166,.85)}
.go.take b{font-weight:400;color:#fff0;background:none}
.go.take b::before{content:attr(data-v);color:#EAFFF4}

.auto{display:flex;align-items:center;gap:7px;font-family:var(--pixel);font-size:10.5px;
  letter-spacing:.09em;color:var(--blue-dim);cursor:pointer;user-select:none}
.auto input{accent-color:#4BB4FC;width:13px;height:13px}

.note{margin:0;min-height:2.4em;font-family:var(--mono);font-size:12.5px;line-height:1.5;
  color:var(--blue-dim);text-shadow:var(--sh-micro);padding:0 2px}
.note.good{color:var(--green)}
.note.bad{color:var(--red)}
.note.warn{color:var(--amber)}

/* ---------- shared board furniture ---------------------------------------- */
.hud{position:absolute;left:14px;top:12px;pointer-events:none;z-index:3}
.hud.right{left:auto;right:14px;text-align:right}
.hudx{font-family:var(--mono);font-size:clamp(30px,5.4vw,54px);line-height:1;color:#79D9FF;
  text-shadow:var(--sh-mark);font-variant-numeric:tabular-nums;letter-spacing:.01em}
.hudx.small{font-size:clamp(18px,2.6vw,26px);color:var(--blue)}
.hudlab{font-family:var(--pixel);font-size:10px;letter-spacing:.18em;color:var(--blue-dim);
  text-shadow:var(--sh-micro);margin-top:3px}
.hudx.live{color:var(--amber)}
.hudx.won{color:var(--green)}
.hudx.lost{color:var(--red)}

/* the verdict is the loudest thing on the board and it only exists for a moment */
.verdict{position:absolute;inset:auto 0 0 0;padding:11px 14px;z-index:4;
  font-family:var(--pixel);font-size:14px;letter-spacing:.11em;text-align:center;
  color:#79D9FF;text-shadow:var(--sh-lead);background:linear-gradient(0deg,rgba(1,5,11,.92),transparent);
  opacity:0;transform:translateY(8px);transition:opacity .22s linear,transform .28s cubic-bezier(.2,.8,.2,1);
  pointer-events:none}
.verdict.cf-on{opacity:1;transform:translateY(0)}
.verdict.win{color:var(--green)}
.verdict.lose{color:var(--red)}

/* ---------- THE CHASE ----------------------------------------------------- */
.chaseboard .quarry{position:absolute;right:14px;bottom:44px;z-index:3;text-align:right;
  font-family:var(--pixel);font-size:10.5px;letter-spacing:.1em;color:var(--blue-dim);
  text-shadow:var(--sh-micro)}
.chaseboard .quarry b{display:block;font-size:13px;color:var(--blue);font-weight:400;
  letter-spacing:.06em;margin-top:2px}
.cf-tape{display:flex;gap:5px;flex-wrap:wrap;padding:2px 1px}
.cf-tape i{font-style:normal;font-family:var(--mono);font-size:11px;padding:3px 6px;
  border:1px solid rgba(75,180,252,.26);color:var(--blue-dim);
  font-variant-numeric:tabular-nums;box-shadow:0 0 0 1px rgba(1,5,11,.9)}
/* ★ THE CHIPS ARE TIERED BY THE SAME LADDER THE LIVE NUMBER CLIMBS - see the
   `data-tier` block in ROUND 4. The donor's two-state `.hi`/`.lo` pair said
   only "big" and "small", so the tape and the multiplier spoke two different
   languages about the same run. */

/* ---------- THE PIT ------------------------------------------------------- */
.pitboard{display:flex;flex-direction:column}
.pitboard .arena{flex:1 1 auto;display:flex;align-items:center;justify-content:center;
  gap:clamp(10px,4vw,48px);padding:16px 14px 6px;min-height:0}
.fighter{flex:0 1 210px;min-width:0;display:flex;flex-direction:column;align-items:center;gap:7px;
  text-align:center}
.fighter .sil{width:100%;max-width:200px;height:clamp(84px,15vh,132px);color:var(--blue)}
.fighter .sil svg{width:100%;height:100%;display:block;overflow:visible;
  filter:drop-shadow(0 0 1.4px rgba(1,5,11,.98))}
.fighter .cf-nm{font-family:var(--pixel);font-size:11px;letter-spacing:.08em;color:var(--blue);
  text-shadow:var(--sh-micro)}
.fighter .sz{font-family:var(--mono);font-size:26px;color:#79D9FF;text-shadow:var(--sh-body);
  line-height:1;font-variant-numeric:tabular-nums}
.fighter.held .sil{color:var(--green)}
.fighter.next .sil{color:var(--amber)}
.fighter.next.hidden .sil{opacity:.22}
.fighter.beat .sil{color:var(--red)}
/* the challenger walks in rather than appearing: an animal that pops into
   existence reads as a number, one that arrives reads as an opponent */
.fighter.next.enter{animation:pitenter .42s cubic-bezier(.2,.8,.2,1)}
@keyframes pitenter{0%{opacity:0;transform:translateX(28px) scale(.9)}
  100%{opacity:1;transform:translateX(0) scale(1)}}
.fighter.held.hit{animation:pithit .38s cubic-bezier(.3,.9,.3,1)}
@keyframes pithit{0%,100%{transform:translateX(0)}
  25%{transform:translateX(-7px)}60%{transform:translateX(5px)}}
.pitboard .versus{font-family:var(--pixel);font-size:12px;letter-spacing:.2em;
  color:var(--blue-dim);text-shadow:var(--sh-micro);align-self:center}
.pitboard .ladder{display:flex;gap:4px;flex-wrap:wrap;padding:8px 14px 44px;
  border-top:1px solid rgba(30,111,224,.3)}
.ladder i{font-style:normal;font-family:var(--mono);font-size:11px;padding:3px 7px;
  border:1px solid rgba(91,255,166,.4);color:var(--green);
  font-variant-numeric:tabular-nums;box-shadow:0 0 0 1px rgba(1,5,11,.9)}
.ladder i.now{border-color:#79D9FF;color:#79D9FF;background:rgba(30,111,224,.16)}
.calls{display:flex;flex-direction:column;gap:6px}
.calls button{cursor:pointer;background:transparent;border:1px solid rgba(75,180,252,.4);
  color:var(--blue);padding:9px 10px;text-align:left;display:flex;flex-direction:column;gap:2px;
  box-shadow:0 0 0 1px rgba(1,5,11,.9);
  transition:border-color .14s linear,color .14s linear,background .14s linear}
.calls button:hover{border-color:#79D9FF;color:#79D9FF;background:rgba(30,111,224,.14)}
.calls b{font-family:var(--pixel);font-size:11px;letter-spacing:.09em;font-weight:400}
.calls em{font-style:normal;font-family:var(--mono);font-size:12px;color:var(--green);
  font-variant-numeric:tabular-nums}

/* ---------- THE CLASH ----------------------------------------------------- */
.clashboard{min-height:clamp(280px,38vh,440px)}

/* ---------- GENE DRIFT ---------------------------------------------------- */
.driftboard .pheno{position:absolute;left:0;right:0;bottom:0;display:flex;gap:2px;
  padding:0 6px 6px;z-index:3;pointer-events:none}
.pheno span{flex:1 1 0;min-width:0;text-align:center;font-family:var(--mono);font-size:10px;
  padding:4px 1px;color:var(--blue-dim);border-top:2px solid rgba(75,180,252,.3);
  font-variant-numeric:tabular-nums;text-shadow:var(--sh-micro);
  transition:color .18s linear,border-color .18s linear,transform .2s cubic-bezier(.2,.8,.2,1)}
.pheno span.rare{color:var(--blue);border-top-color:rgba(75,180,252,.55)}
.pheno span.apex{color:var(--green);border-top-color:rgba(91,255,166,.6)}
.pheno span.lit{color:#DFF6FF;border-top-color:#79D9FF;transform:translateY(-4px)}
.pheno span.lit.good{color:#EAFFF4;border-top-color:var(--green)}
.driftboard .fly{position:absolute;z-index:5;pointer-events:none;font-family:var(--pixel);
  font-size:15px;letter-spacing:.06em;text-shadow:var(--sh-lead);color:var(--green);
  animation:phenofly 1.15s cubic-bezier(.2,.8,.2,1) forwards}
@keyframes phenofly{0%{opacity:0;transform:translate(-50%,4px) scale(.85)}
  20%{opacity:1;transform:translate(-50%,-6px) scale(1.06)}
  70%{opacity:1;transform:translate(-50%,-26px) scale(1)}
  100%{opacity:0;transform:translate(-50%,-44px) scale(.98)}}

/* ---------- THE STRAND ---------------------------------------------------- */
.strandboard{display:flex;align-items:center;justify-content:center;padding:16px 14px 46px}
.loci{display:grid;grid-template-columns:repeat(5,1fr);gap:7px;
  width:min(100%,clamp(260px,42vh,400px));aspect-ratio:1/1}
.loci button{position:relative;cursor:pointer;background:rgba(1,5,11,.55);
  border:1px solid rgba(75,180,252,.3);color:var(--blue-dim);padding:0;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:clamp(11px,2.1vw,15px);
  box-shadow:0 0 0 1px rgba(1,5,11,.9);
  transition:border-color .13s linear,background .13s linear,transform .14s cubic-bezier(.2,.8,.2,1),
             color .13s linear}
.loci button:hover:not(:disabled){border-color:#79D9FF;color:#79D9FF;transform:translateY(-2px)}
.loci button:disabled{cursor:default}
/* a read locus keeps its base pair: the grid becomes a record of the run */
.loci button.safe{border-color:rgba(91,255,166,.55);color:var(--green);
  background:rgba(91,255,166,.09);animation:locusflip .34s cubic-bezier(.2,.8,.2,1)}
.loci button.lethal{border-color:rgba(255,90,90,.7);color:var(--red);
  background:rgba(255,90,90,.14);animation:locusboom .46s cubic-bezier(.2,.9,.3,1)}
.loci button.shown{opacity:.5}
.loci button.cf-dim{opacity:.32}
@keyframes locusflip{0%{transform:rotateY(78deg) scale(.94)}100%{transform:rotateY(0) scale(1)}}
@keyframes locusboom{0%{transform:scale(1)}30%{transform:scale(1.16)}
  55%{transform:scale(.96)}100%{transform:scale(1)}}
@media(prefers-reduced-motion:reduce){
  .loci button.safe,.loci button.lethal{animation:none}
  .fighter.next.enter,.fighter.held.hit{animation:none}
  .rail-bal .delta.show{animation:none;opacity:1}
  .rail-bal b.tick{animation:none}
  .driftboard .fly{animation:none;opacity:1}
}

/* ---------- THE MUTAGEN --------------------------------------------------- */
.mutaboard{display:flex;align-items:center;justify-content:center}
.mutaboard canvas{position:relative;inset:auto;width:min(100%,clamp(240px,40vh,380px));
  height:auto;aspect-ratio:1/1}
/* ★ THE CSS POINTER IS GONE AND THE PAWL IS DRAWN ON THE CANVAS INSTEAD.
   `.wpoint` positioned itself at `calc(50% - clamp(120px,20vh,190px))` - a
   CONSTANT standing in for the drum's radius, which the drawing computes from
   the canvas box. The two never agreed at any width, so the pointer hung in
   space above a rim it was supposed to be touching. A pawl belongs to the
   instrument that decides where its own rim is. */
.oddscard{border:1px solid var(--rule);background:rgba(1,4,10,.62);padding:9px 11px}
.oddscard .or{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:3px 0;font-family:var(--mono);font-size:12px;color:var(--blue-dim);
  font-variant-numeric:tabular-nums}
.oddscard .or b{color:var(--blue);font-weight:400}
.oddscard .or.apex b{color:var(--green)}
.oddscard .or .bar{flex:1 1 auto;height:3px;background:rgba(30,111,224,.22);position:relative}
.oddscard .or .bar i{position:absolute;left:0;top:0;bottom:0;background:var(--blue-dim);display:block}
.oddscard .or.apex .bar i{background:var(--green)}

/* ---------- the log ------------------------------------------------------- */
.cas-log{margin:0 var(--pad) 16px;border:1px solid var(--rule);background:rgba(1,4,10,.55)}
.cas-log .lh{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:8px 12px;border-bottom:1px solid rgba(30,111,224,.35);
  font-family:var(--pixel);font-size:11px;letter-spacing:.11em;color:var(--blue-dim)}
.cas-log .lmeta{color:var(--blue)}
.lrows{display:flex;flex-direction:column;max-height:200px;overflow:auto}
/* 2026-08-18: three columns - game, stake, what the hand ADDED. The old third
   column was the TOTAL return, the number that made a 2.05x total read as
   "paid 1.05x" beside the net. One convention, one number. */
.lrow{display:grid;grid-template-columns:1.4fr .9fr .9fr;gap:10px;padding:6px 12px;
  font-family:var(--mono);font-size:12px;color:var(--blue-dim);
  border-bottom:1px solid rgba(30,111,224,.16);font-variant-numeric:tabular-nums}
.lrow:last-child{border-bottom:0}
.lrow .cf-g{color:var(--blue);letter-spacing:.04em}
.lrow .cf-n{text-align:right}
.lrow .cf-n.up{color:var(--green)}
.lrow .cf-n.down{color:var(--red)}
.lrow.fresh{animation:logfresh .5s ease-out}
@keyframes logfresh{0%{background:rgba(75,180,252,.16)}100%{background:transparent}}
.lempty{padding:14px 12px;font-family:var(--mono);font-size:12.5px;color:var(--blue-dim)}

/* ---------- the fairness drawer ------------------------------------------- */
.fairdlg{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  padding:20px;background:rgba(0,2,8,.78);backdrop-filter:blur(3px)}
.fairdlg[hidden]{display:none !important}
.fd{width:min(640px,100%);max-height:86vh;overflow:auto;border:1px solid var(--rule-hot);
  background:rgba(1,6,16,.97);box-shadow:0 0 60px -20px rgba(61,155,255,.8)}
.fdh{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;
  border-bottom:1px solid var(--rule);font-family:var(--pixel);font-size:12px;
  letter-spacing:.12em;color:var(--blue)}
.fdh button{background:transparent;border:0;cursor:pointer;font:inherit;color:var(--blue-dim);
  letter-spacing:.1em}
.fdh button:hover{color:#79D9FF}
.fdb{padding:14px}
.fdb p{margin:0 0 12px;font-family:var(--mono);font-size:13px;line-height:1.6;color:var(--blue);
  text-shadow:var(--sh-micro)}
.fdb p.fnote{color:var(--blue-dim);font-size:12.5px}
.frow{display:flex;align-items:baseline;gap:10px;padding:5px 0;
  border-bottom:1px solid rgba(30,111,224,.2)}
.frow span{flex:0 0 128px;font-family:var(--pixel);font-size:10px;letter-spacing:.13em;
  color:var(--blue-dim)}
.frow code{flex:1 1 auto;min-width:0;font-family:var(--mono);font-size:11.5px;color:#79D9FF;
  word-break:break-all}
.fcheck{display:flex;gap:6px;margin-top:6px}
.fcheck input{flex:1 1 auto;min-width:0;font-family:var(--mono);font-size:12px;color:#79D9FF;
  background:rgba(1,5,11,.72);border:1px solid rgba(75,180,252,.4);padding:8px 9px}
.fcheck input:focus{outline:none;border-color:#79D9FF}
.fcheck button{cursor:pointer;background:transparent;border:1px solid rgba(75,180,252,.5);
  color:#79D9FF;font-family:var(--pixel);font-size:11px;letter-spacing:.1em;padding:8px 14px}
.fcheck button:hover{border-color:#79D9FF;background:rgba(30,111,224,.16)}
.fout{margin:10px 0 0;padding:10px;border:1px solid rgba(30,111,224,.35);
  background:rgba(1,5,11,.6);font-family:var(--mono);font-size:11.5px;line-height:1.55;
  color:var(--blue);white-space:pre-wrap;word-break:break-all;max-height:220px;overflow:auto}
.fout.good{border-color:rgba(91,255,166,.5);color:var(--green)}
.fout.bad{border-color:rgba(255,90,90,.5);color:var(--red)}


/* ═══════════════════════════════════════════════════════════════════════════
   ROUND 2 — the species fights, the record readout and the plain games.
   His call: "i want actual specie animations. like rex vs trike."
   ═══════════════════════════════════════════════════════════════════════ */

/* the rail gains the player's own record, because it is what prices the pit */
.rail-rec b{font-size:15px;color:var(--green)}

/* ---------- the species pickers ------------------------------------------ */
.pick{width:100%;box-sizing:border-box;font-family:var(--mono);font-size:14px;
  color:#79D9FF;background:rgba(1,5,11,.78);border:1px solid rgba(75,180,252,.4);
  padding:7px 9px;letter-spacing:.02em;cursor:pointer;
  -webkit-appearance:none;appearance:none;
  /* the caret is drawn, so the control cannot arrive wearing the OS's own
     widget in the middle of a terminal */
  background-image:linear-gradient(45deg,transparent 50%,rgba(121,217,255,.75) 50%),
                   linear-gradient(135deg,rgba(121,217,255,.75) 50%,transparent 50%);
  background-position:calc(100% - 15px) 52%,calc(100% - 10px) 52%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
  transition:border-color .15s linear}
.pick:hover,.pick:focus{outline:none;border-color:#79D9FF}
.pick option{background:#01050B;color:#79D9FF}
.tiernote{margin:-2px 0 2px;font-family:var(--mono);font-size:11.5px;line-height:1.45;
  color:var(--blue-dim);text-shadow:var(--sh-micro)}
.recnote{margin:0;font-family:var(--mono);font-size:11.5px;line-height:1.5;
  color:var(--blue-dim);text-shadow:var(--sh-micro);padding:0 2px}

/* ---------- the fight board ---------------------------------------------- */
/* The 3D stage paints onto ONE shared canvas pinned over the page and scissored
   to each host's rect, so this box must NOT try to clip or transform it - the
   scissor follows the host, and `overflow:hidden` here would clip nothing while
   a transform would make a stacking context the fixed canvas sits under. */
.fightboard{min-height:clamp(300px,46vh,540px)}
.fightview{position:absolute;inset:0;z-index:1}
.fightboard .hud{z-index:6}
.fightboard .verdict{z-index:7}

/* the three exchanges of THE PIT, lit one at a time as each is played */
.calls3{position:absolute;left:50%;bottom:52px;transform:translateX(-50%);
  display:flex;gap:10px;z-index:6;pointer-events:none}
.calls3 i{width:34px;height:5px;background:rgba(75,180,252,.22);
  box-shadow:0 0 0 1px rgba(1,5,11,.9);display:block;
  transition:background .2s linear,transform .2s cubic-bezier(.2,.8,.2,1)}
.calls3 i.won{background:var(--green);transform:scaleY(1.8)}
.calls3 i.lost{background:var(--red);transform:scaleY(1.8)}

/* ═══════════════════════════════════════════════════════════════════════════
   THE THROWN COIN AND THE RUNNING CURVE — 2026-08-10

   HIS WORDS: "for the crash have it be more animated, its horrible. la isla
   nublar style but our theme. coin flip better animated. goes from top to the
   bottom like a real coin flip."

   ★ THE MOTION IS THE FRAMEWORK'S. `js/casinofx.mjs` is a derived copy of the
   fleet's casino motion engine (`theisle-framework/webcore/frontend/js/
   casinofx.mjs`, contract in `docs/CASINO_MOTION.md`). Its own sheet,
   `webcore/frontend/css/casinofx.css`, is deliberately UNSCOPED and carries
   paint for ten hooks this page has no use for, so only the rules for the
   hooks this room actually arms were brought across — the coin's three-part
   structure and `[data-shake]` — and they are marked below.

   ★ "BUT OUR THEME" — RETHEMED THROUGH THE ENGINE'S OWN FOUR TOKENS, NEVER BY
   EDITING ITS COLOURS. The framework sheet paints everything out of
   `--fx-hot`, `--fx-cold`, `--fx-ink` and `--fx-line`, whose stock values are
   the donor room's GOLD. They are set here to this site's law, so if the whole
   sheet is ever mounted it arrives already wearing our palette:
       --fx-hot   #5BFFA6  good news (a win) — never gold
       --fx-cold  #FF5A5A  bad news (a bust, a refusal)
       --fx-ink   #79D9FF  the copy/value colour — never near-white
       --fx-line  the frame hairline this page already rules with
   The CURVE is a canvas and has no cascade to read, so its five colours are
   handed to the engine by `js/casino.mjs` (`ink()`), read out of _term.css.

   ★ MOTION IS TRANSFORM AND OPACITY ONLY, everywhere below. Measured on this
   page: transform/opacity ~0.2% of a core, an animated `filter` ~4%, a single
   `stroke-dashoffset` 9.9%. There is no animated filter and no dash animation
   here, and every animation has a reduced-motion answer that is the FINISHED
   PICTURE rather than a shorter one.
   ═══════════════════════════════════════════════════════════════════════ */
:root{
  --fx-hot:91,255,166;
  --fx-cold:255,90,90;
  --fx-ink:121,217,255;
  --fx-line:rgba(30,111,224,.4);
}

/* ---------- the coin ------------------------------------------------------
   THREE PARTS, and the split is what makes it a throw rather than a spin:
   `.coinboard` is the room, `.cointable` is what it lands on, `.coin` is the
   AIR above the table (it holds the perspective and never moves, so the ground
   shadow stays put), and `.coininner` is the disc the engine drives.
   The coin rests LOW and is thrown UP — `js/casino.mjs` measures the board at
   throw time and hands the engine the height, so the arc fills whatever board
   the viewport gave it instead of a constant that overshoots a phone. */
.coinboard{display:flex;align-items:flex-end;justify-content:center;
  min-height:clamp(260px,36vh,420px);padding-bottom:clamp(52px,7vh,76px)}
/* the table line: the coin's ground, and the thing that takes the impact */
.cointable{position:absolute;left:50%;bottom:clamp(44px,6.2vh,66px);
  width:clamp(150px,27vh,240px);height:2px;transform:translateX(-50%);
  background:linear-gradient(90deg,rgba(30,111,224,0),rgba(75,180,252,.55),rgba(30,111,224,0));
  pointer-events:none;z-index:1}
.cointable::after{content:"";position:absolute;left:50%;top:-1px;width:34%;height:4px;
  transform:translateX(-50%) scaleX(.4);opacity:0;
  background:radial-gradient(60% 100% at 50% 50%,rgba(var(--fx-ink),.85),rgba(var(--fx-ink),0) 72%)}

/* brought from casinofx.css — the engine writes --spin/--lift/--pop on the
   disc and --shadow on the air, and NOTHING here may transition or animate
   `transform` on `.coininner`: two animations on one property is not a
   layering, it is a race, and the picture loses. */
.coin{position:relative;width:clamp(96px,17vh,150px);aspect-ratio:1/1;
  perspective:760px;z-index:2}
.coin::after{content:"";position:absolute;left:50%;bottom:-14px;width:78%;height:9px;
  transform:translateX(-50%) scale(var(--shadow,1));opacity:calc(var(--shadow,1) * .7);
  background:radial-gradient(50% 50% at 50% 50%,rgba(1,5,11,.95),rgba(1,5,11,0) 70%);
  pointer-events:none}
.coininner{position:absolute;inset:0;border-radius:50%;transform-style:preserve-3d;
  transform:translateY(var(--lift,0px)) scale(var(--pop,1)) rotateX(var(--spin,0deg))}
.coinface{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  border:2px solid #4BB4FC;border-radius:50%;
  background:radial-gradient(120% 120% at 32% 26%,rgba(30,111,224,.42),rgba(1,5,11,.92));
  font-family:var(--pixel);font-size:clamp(26px,4.4vh,36px);color:#79D9FF;
  text-shadow:var(--sh-lead);letter-spacing:.04em;
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 0 26px -8px rgba(120,220,255,.75)}
.coinface-b{transform:rotateX(180deg)}
/* WITHOUT 3D, WHICH FACE LANDED IS STILL PLAIN STATE. `data-landed` is written
   before the throw and survives every frozen animation. */
@supports not (transform-style:preserve-3d){
  .coinface-b{transform:none}
  .coin[data-landed="a"] .coinface-b,
  .coin[data-landed="b"] .coinface-a{opacity:0}
}

@media(prefers-reduced-motion:no-preference){
  /* the table takes the hit where the coin lands — opacity + transform only */
  @keyframes coinland{
    0%{opacity:.9;transform:translateX(-50%) scaleX(.4)}
    100%{opacity:0;transform:translateX(-50%) scaleX(1.9)}}
  .cointable[data-land]::after{animation:coinland .4s cubic-bezier(.2,.8,.2,1) 1}
  /* brought from casinofx.css: the board takes a hit. The engine arms this. */
  @keyframes fx-shake-hard{
    0%,100%{transform:translate(0,0)}
    14%{transform:translate(-6px,2px)}28%{transform:translate(6px,-2px)}
    42%{transform:translate(-5px,-2px)}56%{transform:translate(4px,3px)}
    72%{transform:translate(-3px,1px)}88%{transform:translate(2px,-1px)}}
  [data-shake="hard"]{animation:fx-shake-hard .58s ease-in-out 1}
  @keyframes fx-shake-soft{
    0%,100%{transform:translateX(0)}
    22%{transform:translateX(-3px)}44%{transform:translateX(3px)}
    68%{transform:translateX(-2px)}86%{transform:translateX(1px)}}
  [data-shake="soft"]{animation:fx-shake-soft .36s ease-in-out 1}

  /* ---------- the running curve ------------------------------------------
     The canvas is the engine's. What the SHEET owns is the number and the
     board around it: a live run leans, a settled one lands, and a bust throws
     the board's own red across it once. */
  /* the MULTIPLIER only — the cash-out readout beside it is a setting, not a
     state, and a setting that pulses is a setting nobody stops looking at */
  /* the number is CENTRED on the plot now, so it grows about its own middle -
     a `0 50%` origin on a centred readout swings it sideways as it pulses */
  @keyframes crashlean{0%,100%{transform:scale(1)}50%{transform:scale(1.045)}}
  .crashboard[data-run] [data-crash-x]{animation:crashlean .9s ease-in-out infinite;
    transform-origin:50% 50%}
  @keyframes crashland{0%{transform:scale(1.16)}100%{transform:scale(1)}}
  .crashboard[data-state] [data-crash-x]{animation:crashland .34s cubic-bezier(.2,.8,.2,1) 1;
    transform-origin:50% 50%}
  /* THE BUST HAS TO BREAK SOMETHING. One flood across the whole board, thrown
     from the top-right where the head was when it snapped, then gone. Opacity
     only - the gradient itself is static and is never re-evaluated. */
  @keyframes crashbreak{0%{opacity:.85}62%{opacity:.28}100%{opacity:0}}
  .crashboard[data-state="bust"]::after{content:"";position:absolute;inset:0;z-index:2;
    pointer-events:none;opacity:0;
    background:
      radial-gradient(60% 46% at 84% 24%,rgba(var(--fx-cold),.5),rgba(var(--fx-cold),0) 70%),
      radial-gradient(130% 100% at 78% 26%,rgba(var(--fx-cold),.22),rgba(var(--fx-cold),0) 64%),
      linear-gradient(180deg,rgba(var(--fx-cold),0) 0%,rgba(var(--fx-cold),.10) 100%);
    animation:crashbreak .62s ease-out 1}
  /* the number lands hard on a bust: one snap, no bounce */
  @keyframes crashsnap{0%{transform:scale(1.3)}44%{transform:scale(.97)}100%{transform:scale(1)}}
  .crashboard[data-state="bust"] [data-crash-x]{animation:crashsnap .38s cubic-bezier(.3,.9,.3,1) 1}
}

@media(prefers-reduced-motion:reduce){
  .calls3 i{transition:none}
}


/* ★ HIS CALL: "for the text there have it be more top not in the middle since
   its covered by the dinos." On a fight board the animals stand on the lower
   half and their legs, tails and the ground reflection sit exactly where a
   bottom-anchored caption goes. So on the FIGHT boards every piece of overlay
   text moves to the top band and the animals get the floor to themselves. */
.fightboard .verdict{inset:auto 0 auto 0;top:0;
  background:linear-gradient(180deg,rgba(1,5,11,.94),transparent);
  padding:10px 14px 16px;transform:translateY(-8px)}
.fightboard .verdict.cf-on{transform:translateY(0)}
/* the three exchange lamps ride under the top band, still clear of the animals */
.fightboard .calls3{bottom:auto;top:64px}
/* the stage's own species captions are drawn inside the view; lift them out of
   the animals' feet and onto the top band beside the readouts */
.fightboard .fightview [class*="caption"],
.fightboard .fightview figcaption{top:34px !important;bottom:auto !important}

/* the two readouts sit at the very top corners and never overlap the middle */
.fightboard .hud{top:8px}
.fightboard .hud .hudx{font-size:clamp(26px,4.4vw,44px)}


/* ═══════════════════════════════════════════════════════════════════════════
   ROUND 3 — THE GROUND, AND THE THREE PLAIN GAMES BUILT AS OBJECTS.
   ═══════════════════════════════════════════════════════════════════════════

   ★★ THE ROOT DEFECT, AND IT WAS ONE LINE IN TWO PLACES.
   The theme paints a fixed, busy, high-contrast photograph behind the whole
   document, and the screen above it is transparent. Every working surface on
   this floor - board, rail, picker tile, control block, odds card, log - was
   painted at 50-86% alpha over that photograph, so EVERY PIECE OF DATA ON THIS
   PAGE WAS BEING READ THROUGH A PICTURE. That is why the wheel looked like a
   wireframe, the crash graph looked empty and the coin looked like a circle
   somebody had drawn with a compass: the surfaces had no ground of their own,
   so the eye could not tell a drawn thing from the photo behind it.

   THE PICTURE IS NOT THE PROBLEM AND IT IS NOT DIMMED. It still frames the
   page in the margins, behind the header, in the section gutters and between
   every block. What changes is that a surface CARRYING DATA now stands on an
   opaque field of its own - a near-black ground, a shallow vertical wash so it
   reads as lit from above, and a rim light on its top edge so it reads as a
   panel sitting ON something rather than a rectangle cut OUT of something.

   WHY THE LAST BACKGROUND LAYER IS A FLAT COLOUR AND NOT MORE ALPHA. An alpha
   wash over an unknown picture is a gamble whose odds change with the picture:
   the same 86% black that hides an alley reads as a smear over a bright sign.
   The opaque layer at the bottom of the stack ends the gamble - what is on top
   of it is the only thing that can be seen, at every width and on every plate a
   host site might swap in.

   ONE PAINT, NEVER RE-EVALUATED. Every ground below is a static background on a
   static element. Nothing here animates a gradient, a filter or a shadow: the
   measured cost of an animated filter on this page is ~4% of a core, and the
   same measurement is why the tiles lost their drop-shadow. */
:root{
  /* the opaque floor every data surface stands on */
  --cas-ink:#01040A;
  /* the light that falls on the top of a panel, and the rim it catches */
  --cas-lit:rgba(121,217,255,.13);
  /* the ruled ground of an instrument: one hairline every 44px, both ways */
  --cas-grid:
    repeating-linear-gradient(90deg,rgba(30,111,224,.055) 0 1px,transparent 1px 44px),
    repeating-linear-gradient(0deg,rgba(30,111,224,.045) 0 1px,transparent 1px 44px);
}

/* THE PANEL GROUND. One recipe, so a rail, a card and a control block are
   plainly the same material. The `inset 3px 0 0` spine each surface already
   carried is kept - it is this floor's own mark - and joined by a top rim
   light and a bottom shade, which is what makes a flat rectangle read as a
   physical plate. */
.cas-rail,.ctl,.oddscard,.cas-log,.cas-gate,.fam{
  background:
    linear-gradient(180deg,rgba(16,52,116,.34) 0%,rgba(4,14,34,.16) 34%,rgba(0,2,8,.5) 100%),
    var(--cas-ink);
}
.cas-rail{box-shadow:inset 3px 0 0 rgba(75,180,252,.55),inset 0 1px 0 var(--cas-lit),
  inset 0 -1px 0 rgba(1,5,11,.9)}
.ctl,.oddscard,.cas-log,.cas-gate{box-shadow:inset 0 1px 0 var(--cas-lit),
  inset 0 -1px 0 rgba(1,5,11,.9)}
.fam{box-shadow:inset 0 1px 0 var(--cas-lit)}
.fam[data-fam="fight"]{box-shadow:inset 3px 0 0 rgba(255,90,90,.45),inset 0 1px 0 var(--cas-lit)}
.fam[data-fam="games"]{box-shadow:inset 3px 0 0 rgba(75,180,252,.5),inset 0 1px 0 var(--cas-lit)}

/* THE TILES. A game you are choosing between four others has to be a THING,
   and a transparent rectangle over a photograph is not one. */
.tiles button{background:linear-gradient(180deg,rgba(12,40,92,.5),rgba(0,2,8,.62)),var(--cas-ink)}
.tiles button:hover{background:linear-gradient(180deg,rgba(20,64,140,.6),rgba(0,2,8,.6)),var(--cas-ink)}
.tiles button[aria-selected="true"]{
  background:linear-gradient(180deg,rgba(30,111,224,.42),rgba(2,10,26,.7)),var(--cas-ink);
  box-shadow:0 0 0 1px rgba(1,5,11,.9),inset 0 1px 0 rgba(121,217,255,.35)}

/* THE BOARD IS A LIT TABLE. A lamp over the top edge, a ruled instrument
   ground under it, and an opaque floor under that. `--cas-grid` is what turns
   an empty box into a surface with a scale on it, which is most of why the
   crash canvas used to look like nothing was there. */
.board{
  background:
    radial-gradient(120% 78% at 50% -6%,rgba(30,111,224,.30),rgba(30,111,224,0) 60%),
    var(--cas-grid),
    linear-gradient(180deg,rgba(10,34,78,.42) 0%,rgba(1,6,16,.3) 38%,rgba(0,2,8,.72) 100%),
    var(--cas-ink);
  box-shadow:inset 3px 0 0 rgba(75,180,252,.55),inset 0 1px 0 var(--cas-lit),
    inset 0 -28px 44px -30px rgba(0,0,0,.9)}
/* the instrument's own inner frame: a second hairline inside the first, the
   same doubled rule the rest of the site draws its chrome with. It is drawn
   UNDER everything (first child pseudo, no z-index) so a canvas, a 3D view and
   every readout sit on top of it. */
.board::before{content:"";position:absolute;inset:7px;pointer-events:none;
  border:1px solid rgba(30,111,224,.26)}
/* the fight boards mount a scissored WebGL canvas; nothing may be laid over
   their middle, so they keep the ground and lose the inner frame */
.fightboard::before{display:none}


/* ═══════════════════════════════════════════════════════════════════════════
   ROUND 4 — THE THREE GAMES AS OBJECTS. 2026-08-11
   ═══════════════════════════════════════════════════════════════════════════

   HIS CALL: the three GAMES "looks bad". They did, and all three failed the
   same way: each was a DIAGRAM OF ITS GAME rather than the thing itself. A
   circle with a letter in it is a diagram of a coin. A hairline over an empty
   grid is a diagram of a curve. Seven outlined slices with the labels standing
   on their heads is a diagram of a wheel. A diagram tells you what the game is
   called; an object tells you what it is worth being nervous about.

   WHAT IS ACTUALLY NEW HERE, AND WHAT IS THE THEME'S ALREADY
   ---------------------------------------------------------
   Nothing below invents a control the theme already ships. The choice between
   HEADS and TAILS is the theme's own `.segs` with the two faces put ON it; the
   readouts are `.hud`/`.hudx`/`.hudlab`; the wheel's legend is `.oddscard` with
   the drum's own colours keyed into it; the panel ground, the board lamp and
   the ruled instrument field are ROUND 3's and are not restated. What is new is
   the METAL on the coin, the INSTRUMENT furniture on the crash board, and the
   drum's own chrome - and every one of those is a static paint.

   THE FOUR CONSTRAINTS EVERY RULE BELOW OBEYS
     · Motion is TRANSFORM AND OPACITY ONLY, each animated selector named
       individually, each with a reduced-motion answer that is the FINISHED
       PICTURE and not a shorter one.
     · No animated filter, no `stroke-dashoffset`, no `url(#…)`. Measured on
       this page: transform/opacity ~0.2% of a core, an animated filter ~4%, one
       dashed line 9.9%. The coin's stamped marks are drawn as a dark copy under
       a bright copy - geometry, not a `drop-shadow` over a spinning disc.
     · Every new class is `cas-` prefixed and was checked against `_term.css`,
       `_seq.css` and `_fx.css` before it was written. Eight names have already
       collided once on this exact page and `.stage` grew every board to 960px
       with no error anywhere.
     · No `border-radius` on anything rectangular. The coin's discs and the
       wheel's rings are CIRCLES - that is the shape of the object, not a
       rounded corner, and the `50%` on `.coinface` predates this round.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---------------------------------------------------------------------------
   COIN FLIP — a struck object over a lit table
   ---------------------------------------------------------------------------
   The disc is bigger than it was, because the whole read is the METAL and metal
   needs area: a milled rim, a bevel, a raised inner field and a mark stamped
   into it. All four are ONE static background stack on an element that already
   existed - the engine still drives `.coininner` and nothing here touches its
   transform, which is the documented race in this file. */
.coinboard{padding-bottom:clamp(58px,8vh,84px)}
.coin{width:clamp(118px,23vh,206px)}

/* THE RIM, AS FIVE STATIC LAYERS ON ONE ELEMENT.
   ★ EVERY CIRCLE HERE IS `closest-side`, AND THAT IS THE WHOLE FIX. The first
   cut sized the field with a bare `radial-gradient(circle at 38% 30%, …)`,
   which defaults to `farthest-corner` - measured from an OFF-CENTRE point, so
   the "80%" stop landed outside the disc on one side and well inside it on the
   other, and the milling read as a lopsided starburst rather than a rim. A
   circle whose radius is half the box is the only one that gives a rim of the
   same width all the way round; the LIGHT is a separate layer over it, which is
   how a lit object works anyway. */
.coinface{
  border-color:#3D97DE;
  background:
    /* the light on the raised field */
    radial-gradient(circle closest-side at 34% 26%,
      rgba(160,224,255,.34), rgba(160,224,255,.06) 46%, rgba(160,224,255,0) 66%),
    /* the raised inner field, and its hard edge against the rim */
    radial-gradient(circle closest-side at 50% 50%,
      rgba(32,96,182,.7) 0%, rgba(11,40,90,.97) 46%,
      rgba(4,18,44,1) 74%, rgba(3,13,32,1) 77.5%, rgba(0,0,0,0) 78%),
    /* the milling: 50 reeds, half-transparent so the bevel beneath still tells
       the rim which way the light is coming from */
    repeating-conic-gradient(from -6deg,
      rgba(140,214,255,.46) 0deg 3.2deg, rgba(3,14,34,.5) 3.2deg 7.2deg),
    /* the bevel under the reeding: bright top-left, dark bottom-right */
    conic-gradient(from 200deg,
      rgba(150,220,255,.62), rgba(24,76,150,.4) 26%,
      rgba(1,6,16,.72) 52%, rgba(52,130,220,.46) 78%, rgba(150,220,255,.62)),
    radial-gradient(circle closest-side at 50% 50%, rgba(8,30,70,.96), rgba(1,5,11,.99));
  box-shadow:
    0 0 0 1px rgba(1,5,11,.92),
    inset 0 0 0 1px rgba(150,220,255,.30),          /* the rim's own bright wire */
    inset 0 2px 7px -3px rgba(180,235,255,.55),     /* light catching the top edge */
    inset 0 -4px 12px -6px rgba(0,0,0,.95),         /* the shade under it */
    inset 0 0 30px -10px rgba(120,220,255,.5)}
/* the step where the raised field meets the bevel: one hairline, and it is what
   makes the middle read as PROUD of the rim rather than printed on it */
.coinface::before{content:"";position:absolute;inset:19%;border-radius:50%;
  border:1px solid rgba(146,216,255,.34);
  box-shadow:inset 0 3px 9px -5px rgba(190,240,255,.6),
             inset 0 -3px 10px -5px rgba(0,0,0,.9);
  pointer-events:none}
/* THE SPECULAR. A band across the disc that only exists while the coin is in
   the air - a permanent highlight on a resting coin is a sticker. */
.coinface::after{content:"";position:absolute;inset:0;border-radius:50%;
  pointer-events:none;opacity:0;
  background:linear-gradient(118deg,
    rgba(200,244,255,0) 34%, rgba(200,244,255,.34) 47%,
    rgba(200,244,255,.06) 55%, rgba(200,244,255,0) 62%)}
/* a child of a hidden backface is not reliably hidden with it, and a mark
   bleeding through from the far side of a turning coin is the one artefact
   nobody would be able to name but everybody would see */
.coinface > *{backface-visibility:hidden;-webkit-backface-visibility:hidden}
.cas-face{position:relative;z-index:1;width:56%;height:56%;display:block;
  overflow:visible;color:#8FDCFF}
/* THE STAMP, WITHOUT A FILTER. The dark copy sits down-and-right of the bright
   one, which is what a die pressed into metal looks like from a light above
   left. Two paths instead of a `drop-shadow` on a disc that is turning at seven
   revolutions a throw. */
.cas-face .cas-die{color:#01050B;opacity:.92}
.cas-face .cas-hi{color:inherit}
/* the legend struck round the bottom of the field, the way a coin carries its
   own denomination */
.cas-word{position:absolute;left:0;right:0;bottom:16%;z-index:1;text-align:center;
  font-family:var(--pixel);font-style:normal;font-size:clamp(9px,1.35vh,12px);
  letter-spacing:.22em;color:#A8E7FF;text-shadow:var(--sh-micro)}

/* the winning face takes the light for a moment when it settles */
.coin[data-flare] .cas-face{color:#DFF6FF}
.coin[data-flare] .coinface{box-shadow:
  0 0 0 1px rgba(1,5,11,.92),
  inset 0 0 0 1px rgba(190,240,255,.6),
  inset 0 2px 7px -3px rgba(210,248,255,.7),
  inset 0 -4px 12px -6px rgba(0,0,0,.95),
  inset 0 0 34px -6px rgba(150,235,255,.85),
  0 0 42px -12px rgba(120,220,255,.9)}

/* THE CALL, COMMITTED. The readout is the theme's own, tinted to the face the
   player took so the board and the control agree without a second word. */
.coinboard .hud{top:14px;left:16px}
.coinboard .hud.right{left:auto;right:16px}
.coinboard .hudx{font-size:clamp(26px,3.6vw,40px)}
.coinboard .hudx.small{font-size:clamp(17px,2vw,24px);color:var(--green)}

/* YOUR OWN LAST FLIPS. Colour is the OUTCOME, which the page knows for every
   hand in its history; the letter is the FACE, which it only knows for the ones
   it watched land. A face it never saw prints a dash - because a reading you do
   not have is a dash, never a guess dressed as a fact. */
.cas-streak{position:absolute;left:16px;right:16px;bottom:14px;z-index:3;
  display:flex;align-items:center;gap:5px;flex-wrap:wrap;pointer-events:none;
  padding-top:6px;border-top:1px solid rgba(30,111,224,.26)}
.cas-streak .cas-tk{flex:0 0 auto;margin-right:3px}
.cas-streak i{font-style:normal;font-family:var(--pixel);font-size:10px;line-height:1;
  width:19px;height:19px;display:flex;align-items:center;justify-content:center;
  border:1px solid rgba(75,180,252,.3);color:var(--blue-dim);
  box-shadow:0 0 0 1px rgba(1,5,11,.9);text-shadow:var(--sh-micro)}
.cas-streak i.cas-w{border-color:rgba(91,255,166,.55);color:var(--green);
  background:rgba(91,255,166,.1)}
.cas-streak i.cas-l{border-color:rgba(255,90,90,.5);color:var(--red);
  background:rgba(255,90,90,.1)}
.cas-streak i.cas-now{box-shadow:0 0 0 1px rgba(1,5,11,.9),0 0 14px -3px rgba(121,217,255,.9)}
.cas-streak .cas-none{font-family:var(--mono);font-size:11.5px;color:var(--blue-dim);
  text-shadow:var(--sh-micro)}

/* the two faces ON the choice, so HEADS and TAILS are two OBJECTS and not two
   grey words. `.segs` is the theme's control; this only dresses it. */
.segs.cas-callseg button{display:flex;align-items:center;justify-content:center;gap:7px;
  padding:9px 5px}
.segs.cas-callseg button svg{flex:0 0 auto;width:14px;height:14px;display:block;
  overflow:visible;color:inherit;opacity:.9}
.segs.cas-callseg button.cf-on svg{opacity:1}

/* the impact. TWO rings, because one ring reads as a ripple and two read as a
   thing that hit something: a hard flash under the coin and a wide ring off it.
   Both are opacity + transform on a pseudo that is otherwise invisible. */
.cointable::before{content:"";position:absolute;left:50%;top:-4px;width:46%;height:9px;
  transform:translateX(-50%) scale(.3);opacity:0;pointer-events:none;
  border:1px solid rgba(var(--fx-ink),.7)}

@media(prefers-reduced-motion:no-preference){
  @keyframes coinring{
    0%{opacity:.85;transform:translateX(-50%) scale(.25)}
    100%{opacity:0;transform:translateX(-50%) scale(2.3)}}
  .cointable[data-land]::before{animation:coinring .5s cubic-bezier(.2,.8,.2,1) 1}
  /* the disc rocks itself flat. It is on `.coin` - the AIR - and never on
     `.coininner`, whose transform belongs to the engine and to nothing else.
     Two animations on one property is not a layering, it is a race. */
  @keyframes coinwob{
    0%{transform:rotate(0deg)}18%{transform:rotate(3.2deg)}
    42%{transform:rotate(-2.1deg)}66%{transform:rotate(1.1deg)}
    86%{transform:rotate(-.4deg)}100%{transform:rotate(0deg)}}
  .coin[data-wob]{animation:coinwob .58s cubic-bezier(.25,.8,.35,1) 1}
  /* the highlight sweeps only while the coin is in the air */
  @keyframes coinsheen{
    0%{opacity:0;transform:translateX(-58%)}
    16%{opacity:1}84%{opacity:1}
    100%{opacity:0;transform:translateX(58%)}}
  .coinboard[data-throw] .coinface::after{animation:coinsheen 1.15s linear 1}
  /* the winning face flares once and lets go */
  @keyframes coinflare{0%{opacity:0}22%{opacity:1}100%{opacity:0}}
  .coin[data-flare] .coinface::after{animation:coinflare .6s ease-out 1;opacity:0}
}

/* ---------------------------------------------------------------------------
   CRASH — the board becomes an instrument
   ---------------------------------------------------------------------------
   
   recent breaks, the area fill under the curve, ONE huge multiplier whose
   colour steps by tier, and the fairness line along the bottom edge. Left
   behind: their palette, their rounded glass, and their entire live-multiplayer
   half - a betting countdown, a player list and a jackpot pool. Ours is instant
   and solo and was already rolled by the server before the first frame, so a
   list of other players would be a list this floor would have had to invent. */
.crashboard .hudlab{letter-spacing:.3em}
/* ★ THE PLOT ENDS WHERE THE FURNITURE STARTS. The canvas fills the board by
   default, so the engine drew its baseline and its bottom graticule straight
   through the fairness footer and its tape row through the top strip. Insetting
   the CANVAS rather than moving the furniture is the right way round: the
   engine measures its own box every run, so the plot simply becomes the part of
   the board that is plot. */
/* ★ THE SIZE IS WRITTEN OUT, NOT LEFT TO THE INSETS. A `<canvas>` is a REPLACED
   element: with `width:auto` it takes its INTRINSIC size — the bitmap's own
   `width` attribute — and the `right`/`bottom` insets are simply dropped. That
   is not a small mistake here, because the engine writes that attribute from
   the box it measured, so auto sizing feeds the canvas its own last answer and
   the plot collapses to nothing. Measured on the board: the whole curve, grid
   and axis vanished and only the bust flood was left. The two `calc()`s are the
   same numbers as the insets, said in the way a replaced element listens to. */
.crashboard canvas{inset:44px 10px 44px 10px;
  width:calc(100% - 20px);height:calc(100% - 88px)}

/* THE TAPE, ON THE PLOT. It was in the side column, below the fold of the eye,
   while the thing it explains was on the board. */
.crashboard .cas-ontape{position:absolute;left:16px;right:16px;top:14px;z-index:3;
  display:flex;align-items:center;gap:10px;pointer-events:none;
  padding-bottom:7px;border-bottom:1px solid rgba(30,111,224,.3)}
.cas-tk{flex:0 0 auto;font-family:var(--pixel);font-size:9.5px;letter-spacing:.18em;
  color:var(--blue-dim);text-shadow:var(--sh-micro);white-space:nowrap}
.crashboard .cas-ontape .cf-tape{flex:1 1 auto;min-width:0;gap:4px;padding:0;
  flex-wrap:nowrap;overflow:hidden}
.crashboard .cas-ontape .cf-tape i{flex:0 0 auto}
.cf-tape .cas-none{font-family:var(--mono);font-size:11px;color:var(--blue-dim);
  text-shadow:var(--sh-micro)}

/* ★ ONE LADDER, TWO PLACES. The chip you read after the round and the number
   you watch during it step through the SAME four colours, so the tape is a
   history of the thing the big number is doing. The ladder is the site's own
   law and not a new palette: three tiers of blue for a run that is behaving,
   and AMBER for the exceptional one. Green is reserved for a WIN and red for a
   refusal, and neither is a size of number. */
.cf-tape i[data-tier="0"]{border-color:rgba(44,132,238,.45);color:var(--blue-dim)}
.cf-tape i[data-tier="1"]{border-color:rgba(75,180,252,.5);color:var(--blue)}
.cf-tape i[data-tier="2"]{border-color:rgba(121,217,255,.55);color:#79D9FF;
  background:rgba(30,111,224,.14)}
.cf-tape i[data-tier="3"]{border-color:rgba(255,180,84,.6);color:var(--amber);
  background:rgba(255,180,84,.1)}
.crashboard [data-crash-x][data-tier="0"]{color:var(--blue-dim)}
.crashboard [data-crash-x][data-tier="1"]{color:var(--blue)}
.crashboard [data-crash-x][data-tier="2"]{color:#79D9FF}
.crashboard [data-crash-x][data-tier="3"]{color:var(--amber)}

/* THE NUMBER IS THE BOARD. Centred over the plot, as big as the box will carry,
   with the ink stack doing the separating - not a panel behind it. */
.crashboard .cas-mid{position:absolute;left:50%;top:50%;z-index:3;
  transform:translate(-50%,-54%);text-align:center;pointer-events:none;
  width:min(94%,560px)}
.crashboard .cas-mid .hudx{font-size:clamp(46px,7.4vw,90px);line-height:.94;
  letter-spacing:-.005em}
.crashboard .cas-mid .hudlab{margin-top:6px}
/* WHAT THE RUN MEANS FOR THE STAKE ON THE TABLE - and it is NOT what the donor
   board prints. Theirs is a live cash-out, so `bet x the number on screen` is a
   payout somebody can actually take. OURS IS PRE-COMMITTED: the server pays
   `floor(bet x YOUR TARGET)` and nothing else, so printing `bet x the live
   multiplier` would be quoting a payout this game cannot make. It counts the
   GAP to your line instead, and the instant the curve crosses it, it prints the
   real return. */
.cas-would{margin-top:10px;min-height:1.5em;font-family:var(--mono);
  font-size:clamp(12.5px,1.35vw,16px);letter-spacing:.04em;color:var(--blue-dim);
  text-shadow:var(--sh-body);font-variant-numeric:tabular-nums}
.cas-would b{font-weight:400;color:#79D9FF}
.cas-would.cas-lock{color:var(--green)}
.cas-would.cas-lock b{color:var(--green)}
/* a run that ended short says so in the same place it was counting down in.
   Red, because it is the refusal, and it is the only thing on the board that
   has to be read after the number itself. */
.cas-would.cas-miss{color:var(--red)}
.cas-would.cas-miss b{color:var(--red)}

/* THE HONESTY ALONG THE BOTTOM EDGE. The commit is the hash the server showed
   before a chip moved; after the roll the same cell carries the SEED that hash
   was of, and the round number is the seed chain's own nonce. Nothing here is
   computed by this page. */
.crashboard .cas-fair{position:absolute;left:16px;right:16px;bottom:12px;z-index:3;
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;pointer-events:none;
  padding-top:6px;border-top:1px solid rgba(30,111,224,.3)}
.cas-fk{font-family:var(--pixel);font-size:9.5px;letter-spacing:.16em;
  color:var(--blue-dim);text-shadow:var(--sh-micro);white-space:nowrap}
.cas-fv{font-family:var(--mono);font-size:11px;color:var(--blue);letter-spacing:.02em;
  text-shadow:var(--sh-micro);font-variant-numeric:tabular-nums;
  max-width:34ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cas-fend{margin-left:auto}
.cas-fair[data-armed] [data-crash-fairk]{color:var(--amber)}
.cas-fair[data-revealed] [data-crash-fairk]{color:var(--green)}
.cas-fair[data-revealed] [data-crash-fairv]{color:var(--green)}
/* the verdict clears the footer instead of landing on top of it */
.crashboard .verdict{inset:auto 0 30px 0}

@media(prefers-reduced-motion:no-preference){
  /* THE SEAL CLOSING. Theatre made out of the one honest thing on the board:
     a scan crosses the fairness line while the roll is in flight. It is a
     translate on a pseudo and it is over in 620ms. */
  @keyframes casarm{
    0%{transform:translateX(-104%);opacity:0}
    14%{opacity:1}84%{opacity:1}
    100%{transform:translateX(104%);opacity:0}}
  .cas-fair[data-armed]::after{content:"";position:absolute;left:0;right:0;top:2px;bottom:0;
    pointer-events:none;
    background:linear-gradient(90deg,rgba(121,217,255,0),rgba(121,217,255,.3) 46%,
      rgba(121,217,255,0));
    animation:casarm .62s linear 1}
}

/* ---------------------------------------------------------------------------
   SPIN THE WHEEL — a drum and its legend, one object read two ways
   ---------------------------------------------------------------------------
   The drum is sized off the board's OWN height (`align-self:stretch` against a
   basis in the same `vh` the board's `min-height` uses), so it comes out square
   at every width instead of being a small circle adrift in a wide box. */
.wheelboard{display:flex;align-items:center;justify-content:center;
  gap:clamp(10px,2vw,28px);min-height:clamp(340px,60vh,620px);
  padding:clamp(12px,2vh,20px) clamp(14px,2vw,24px) 46px}
/* THE DRUM IS SQUARE BECAUSE ITS BASIS AND ITS HEIGHT ARE THE SAME MEASUREMENT.
   `align-self:stretch` gives it the board's content height and the basis is the
   same `vh` expression less the board's own padding, so the box it is drawn in
   is square at every width — which is the whole reason the circle stopped
   floating in the middle of a letterbox. */
.cas-drum{position:relative;flex:0 1 clamp(240px,54vh,556px);align-self:stretch;
  min-width:0}
.wheelboard canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.oddscard.cas-leg{flex:0 1 clamp(172px,21vw,306px);align-self:center;min-width:0;
  padding:10px 12px;border-color:rgba(30,111,224,.5);
  background:linear-gradient(180deg,rgba(16,52,116,.32),rgba(0,2,8,.5));
  box-shadow:inset 0 1px 0 var(--cas-lit),inset 0 -1px 0 rgba(1,5,11,.9)}
.oddscard.cas-leg .cas-tk{display:block;margin:0 0 7px}
.oddscard.cas-leg .or{gap:8px;padding:4px 0}
/* THE LEGEND IS KEYED TO THE DRUM. Every row wears the exact fill its wedge
   wears, so the card is not a table beside a picture - it is the same object
   sorted a different way. `--cas-c` is written per row by `js/casino.mjs` from
   the one ladder the drawing reads. */
.cas-sw{flex:0 0 9px;width:9px;height:9px;display:block;
  background:var(--cas-c,var(--blue-dim));
  box-shadow:0 0 0 1px rgba(1,5,11,.92),0 0 9px -2px var(--cas-c,transparent)}
.oddscard.cas-leg .or b{flex:0 0 3.6em;text-align:right;color:var(--cas-c,var(--blue))}
.oddscard.cas-leg .or .bar{height:4px;background:rgba(30,111,224,.2);
  box-shadow:inset 0 0 0 1px rgba(1,5,11,.7)}
.oddscard.cas-leg .or .bar i{background:var(--cas-c,var(--blue-dim))}
.oddscard.cas-leg .or > span:last-child{flex:0 0 3.6em;text-align:right}
/* the row the drum stopped on holds lit with its wedge */
.oddscard.cas-leg .or.cas-hit{color:#79D9FF;
  background:linear-gradient(90deg,rgba(121,217,255,.14),rgba(121,217,255,0));
  box-shadow:inset 2px 0 0 var(--cas-c,#79D9FF)}
.oddscard.cas-leg .or.cas-hit b{color:#DFF6FF}
.oddscard.cas-leg .or.cas-hit .cas-sw{box-shadow:0 0 0 1px rgba(1,5,11,.92),
  0 0 14px -1px var(--cas-c,transparent)}
.oddscard.cas-leg .or.cas-hit .bar{background:rgba(121,217,255,.18)}
/* the wheel's verdict has no footer under it, so it keeps the bottom edge */
.wheelboard .verdict{z-index:5}

@media(max-width:1180px){
  .oddscard.cas-leg{flex:0 1 clamp(150px,17vw,226px)}
}
/* ★ A SEVEN-PIXEL BAR IS NOT A SMALL BAR, IT IS A WRONG ONE. Squeezed beside a
   drum on a narrow board the legend's tracks collapsed until 32.8% and 0.2%
   drew the same stub — a reading that says nothing while looking like it says
   something, which is the failure the site's own "unknown is not zero" law is
   about. Below this width the bar comes OFF and the swatch and the printed
   percentage carry the row; the drum next to it is still the picture of the
   weights, so nothing is lost but the crushed copy of it. */
@media(max-width:880px){
  .oddscard.cas-leg .or .bar{display:none}
  .oddscard.cas-leg .or{justify-content:flex-start}
  .oddscard.cas-leg .or > span:last-child{margin-left:auto}
}
/* THE PICKER'S THREE-TILE FAMILY NEEDS THE WHOLE ROW BEFORE IT NEEDS TO WRAP.
   Two families side by side at ~760px gave the GAMES family about 350px for
   three tiles, and "SPIN THE WHEEL" is wider than its third of that - the name
   of a game ran out of the button a player is meant to press it with. */
@media(max-width:960px){
  .cas-pick .fam{flex:1 1 100%}
}
/* Under ~640px the drum and its legend stop being side by side: a 150px card
   beside a 150px wheel is two things nobody can read rather than one they can. */
@media(max-width:640px){
  .wheelboard{flex-direction:column;align-items:stretch;gap:12px;
    min-height:0;padding-bottom:44px}
  .cas-drum{flex:0 0 auto;align-self:center;width:min(100%,320px);aspect-ratio:1/1}
  .oddscard.cas-leg{flex:0 0 auto;align-self:stretch}
}

/* Narrow boards: the crash furniture must not eat the plot, and the coin's
   streak must not push its own table off the bottom. */
@media(max-width:560px){
  .crashboard .cas-ontape,.crashboard .cas-fair,.cas-streak{left:11px;right:11px}
  .cas-fend{margin-left:0}
  /* the footer wraps to TWO rows on a phone — the commit is twenty characters
     and "YOUR LINE" cannot sit beside it — so the plot gives up the room the
     second row needs rather than being drawn under it */
  .crashboard canvas{inset:40px 8px 64px 8px;
    width:calc(100% - 16px);height:calc(100% - 104px)}
  .crashboard .cas-mid{width:96%}
  .coinboard .hudx{font-size:clamp(21px,6vw,28px)}
  .coinboard .hudx.small{font-size:clamp(15px,4.4vw,20px)}
}

@media(prefers-reduced-motion:reduce){
  /* THE FINISHED PICTURE, NOT A SHORTER ONE. Every state below is the state
     these selectors END in, so a player who never sees a frame of motion still
     sees the impact ring gone, the sheen gone, and the flare shown as a
     STANDING highlight on the face that won - which is the information the
     animation existed to carry. */
  .cointable[data-land]::before{animation:none;opacity:0}
  .coin[data-wob]{animation:none}
  .coinboard[data-throw] .coinface::after{animation:none;opacity:0}
  .coin[data-flare] .coinface::after{animation:none;opacity:.5}
  .cas-fair[data-armed]::after{animation:none;content:none}
  .crashboard[data-state="bust"] [data-crash-x]{animation:none}
}

/* ══════════════════════════════════════════════════════════════════════════
   THE TWO NEW CONTROLS — 2026-08-15
   Owner: "wheel crash and coin flip seem bad and not very interactive."
   Both of these are the ANSWER to that: a stake the wheel never had, and a
   throw the coin never had. Neither touches an outcome.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- THE WHEEL'S STAKE --------------------------------------------------
   It wears the theme's own segmented control, so it is the same object as
   crash's quick-target row and nobody has to learn a second one. It is HIDDEN
   (not empty) on a floor whose ceiling is 1x — an empty control is a control
   that looks broken. */
[data-wheel-stake][hidden]{display:none}
[data-wheel-stake] button{font-variant-numeric:tabular-nums}

/* ---- THE COIN'S WIND-UP -------------------------------------------------
   ★ THE BAR IS DRAWN WITH A TRANSFORM, NOT A WIDTH. `--charge` is written by
   rAF on every frame of the hold; animating `width` would lay out and paint
   the whole button sixty times a second for a decoration. A scaled pseudo
   element is composited and costs nothing.
   ★ AND IT SITS UNDER THE LABEL. The button still says FLIP the whole time —
   a control whose text is replaced by its own progress is a control the player
   cannot read while they are using it. */
.go[data-charging]{border-color:#A8E7FF;color:#DFF6FF}
.go::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  transform-origin:left center;
  transform:scaleX(var(--charge,0));
  background:linear-gradient(90deg,rgba(75,180,252,.10),rgba(121,217,255,.30));
  transition:opacity .18s linear;opacity:0;
}
.go[data-charging]::before{opacity:1}
/* the leading edge, so a part-wound throw has a position and not just a wash */
.go[data-charging]::after{
  content:"";position:absolute;top:0;bottom:0;width:2px;pointer-events:none;
  left:calc(var(--charge,0) * 100%);
  background:#A8E7FF;box-shadow:0 0 8px rgba(168,231,255,.9);
}

@media (prefers-reduced-motion: reduce){
  /* THE HOLD DOES NOT EXIST UNDER REDUCED MOTION — the toss is already the
     finished picture there, so a wind-up would be a control with nothing on
     the other end of it. The JS does not arm it; this makes sure a stale
     attribute cannot paint one either. */
  .go::before,.go[data-charging]::before,.go[data-charging]::after{
    display:none;
  }
}
