/* RAEKON CASINO — makeover stylesheet (2027 direction): type + micro + bento + icons + chip + crest + vault enter.
   Loaded AFTER the inline <style>; :root tokens live in index.html. */

/* ============ TYPE ============ */
/* ============================================================================
   RAEKON CASINO — TYPOGRAPHY SYSTEM
   "A Raekwon record you gamble inside — velvet vault, one gold stroke."

   FOUR VOICES, NO MORE:
     wordmark  Cinzel Decorative 700 .. the crest. RAEKON CASINO, and nothing else.
     display   Libre Bodoni 700 ...... screen + section titles. High-contrast serif.
     body      Cormorant Garamond ..... lore, prose, track titles. Editorial.
     ui        Oswald 500 ............. every number, label, button, chrome.

   INTEGRATION: this file MUST load AFTER the inline <style> block in index.html.
   It deliberately re-declares --display and --body on :root so nothing breaks,
   then re-routes every selector that used the OLD condensed --display for
   numbers/chrome onto the new --ui. Load it earlier and the numbers go serif.

   Comp chips only. No currency glyphs anywhere in this file.
   ============================================================================ */


/* ============================================================================
   1. @FONT-FACE — self-hosted, lib/fonts/*.woff2
   ============================================================================ */

/* --- the crest: Cinzel Decorative 700 (caps only, generous tracking) --- */
@font-face{
  font-family:"Cinzel Decorative";
  src:url("lib/fonts/cinzel-decorative-700.woff2") format("woff2");
  font-weight:700;
  font-style:normal;
  font-display:swap;
}

/* --- titles: Libre Bodoni 700 --- */
@font-face{
  font-family:"Libre Bodoni";
  src:url("lib/fonts/libre-bodoni-700.woff2") format("woff2");
  font-weight:700;
  font-style:normal;
  font-display:swap;
}

/* --- body / lore: Cormorant Garamond 400 + 600 --- */
@font-face{
  font-family:"Cormorant Garamond";
  src:url("lib/fonts/cormorant-400.woff2") format("woff2");
  font-weight:400;
  font-style:normal;
  font-display:swap;
}
@font-face{
  font-family:"Cormorant Garamond";
  src:url("lib/fonts/cormorant-600.woff2") format("woff2");
  font-weight:600;
  font-style:normal;
  font-display:swap;
}

/* --- numbers / labels / chrome: Oswald 500 --- */
@font-face{
  font-family:"Oswald";
  src:url("lib/fonts/oswald-500.woff2") format("woff2");
  font-weight:500;
  font-style:normal;
  font-display:swap;
}

/* --- METRIC-MATCHED FALLBACKS ------------------------------------------------
   font-display:swap means the system face paints first. These three synthetic
   families re-scale the local fallback so the swap does not jolt the layout.
   Values are hand-tuned against iOS 17 system faces; nudge only if you see a
   reflow pop on a cold load.                                                  */
@font-face{
  font-family:"Cormorant Fallback";
  src:local("Iowan Old Style"),local("Georgia"),local("Times New Roman");
  size-adjust:88%;          /* Cormorant runs small-on-the-body vs Georgia */
  ascent-override:92%;
  descent-override:26%;
  line-gap-override:0%;
}
@font-face{
  font-family:"Bodoni Fallback";
  src:local("Bodoni 72"),local("Didot"),local("Times New Roman");
  size-adjust:97%;
  ascent-override:95%;
  descent-override:24%;
  line-gap-override:0%;
}
@font-face{
  font-family:"Oswald Fallback";
  src:local("Avenir Next Condensed"),local("Helvetica Neue Condensed"),local("Arial Narrow");
  size-adjust:104%;         /* Oswald is narrower + taller x-height */
  ascent-override:104%;
  descent-override:26%;
  line-gap-override:0%;
}


/* ============================================================================
   2. ROLE TOKENS
   --display and --body keep their existing names so every legacy rule in
   index.html keeps resolving. --ui and --wordmark are new.
   ============================================================================ */

:root{
  /* ---- families -------------------------------------------------------- */
  --wordmark:"Cinzel Decorative","Bodoni Fallback","Bodoni 72",Didot,"Hoefler Text",Georgia,"Times New Roman",serif;
  --display:"Libre Bodoni","Bodoni Fallback","Bodoni 72",Didot,"Hoefler Text",Georgia,"Times New Roman",serif;
  --body:"Cormorant Garamond","Cormorant Fallback","Iowan Old Style","Hoefler Text",Georgia,"Times New Roman",serif;
  --ui:"Oswald","Oswald Fallback","Avenir Next Condensed","Helvetica Neue Condensed","Arial Narrow",
       -apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif;

  /* the old condensed sans, kept addressable in case a one-off needs it */
  --legacy-condensed:"Arial Narrow","Helvetica Neue Condensed",Impact,"Avenir Next Condensed",sans-serif;

  /* ---- modular scale — base 15px, ratio 1.185 (a hair under a minor third)
         Values are hand-rounded to whole/half pixels so hairline serifs land
         on the pixel grid at 2x/3x. ---------------------------------------- */
  --fs-1:10px;      /* micro caps: legal, tags, live badges              */
  --fs-2:11.5px;    /* labels, ticker, tab chrome                        */
  --fs-3:13px;      /* small UI, secondary buttons, paytable rows        */
  --fs-4:15px;      /* UI base, section heads, primary button text       */
  --fs-5:17.5px;    /* body copy, cabinet names, readout numbers         */
  --fs-6:21px;      /* card / hero titles                                */
  --fs-7:clamp(25px,6.6vw,33px);      /* screen titles, modal H2         */
  --fs-8:clamp(48px,14.6vw,84px);     /* the crest wordmark              */

  /* ---- line heights ---------------------------------------------------- */
  --lh-crest:0.94;  /* Cinzel caps, no descenders to clear               */
  --lh-title:1.08;  /* Bodoni display                                    */
  --lh-ui:1.16;     /* Oswald — tall x-height, keep it tight             */
  --lh-body:1.52;   /* Cormorant needs air to read                       */
  --lh-lore:1.64;   /* long-form lore paragraphs                         */

  /* ---- tracking (letter-spacing) --------------------------------------- */
  --ls-crest:0.12em;      /* Cinzel wants generous air                   */
  --ls-crest-wide:0.26em; /* the second crest line, spaced-out           */
  --ls-title:0.008em;     /* Bodoni mixed case — near zero               */
  --ls-title-caps:0.05em; /* Bodoni all-caps needs a touch               */
  --ls-body:0;            /* Cormorant sets itself                       */
  --ls-ui:0.035em;        /* Oswald default — tight                      */
  --ls-ui-tight:0.012em;  /* Oswald on buttons/large chrome              */
  --ls-num:0.01em;        /* numerals — almost none, tabular does the job */
  --ls-label:0.17em;      /* micro caps labels                           */

  /* engraved gradient band height — MUST equal the element's line-height
     so multi-line engraved text gets a fresh gradient on every line */
  --engrave-band:1.08em;
}


/* ============================================================================
   3. GLOBAL BASELINE
   ============================================================================ */

html{
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}

body{
  font-family:var(--body);
  font-weight:400;
  font-size:var(--fs-5);
  line-height:var(--lh-body);
  letter-spacing:var(--ls-body);
  /* only 400/600 of Cormorant and 700 of Bodoni/Cinzel exist — never let the
     rasteriser invent a bold or an oblique, it destroys the hairlines */
  font-synthesis:none;
  font-synthesis-weight:none;
  font-synthesis-style:none;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
}

/* body{font-family:inherit} on button in index.html means every unstyled
   control would inherit Cormorant. Controls are chrome — they are Oswald. */
button,input,select,textarea,optgroup{
  font-family:var(--ui);
  font-weight:500;
  letter-spacing:var(--ls-ui);
  font-synthesis:none;
}

/* Cormorant 700 does not exist; map strong emphasis to the 600 we shipped. */
b,strong{font-weight:600;}
.trk .tn,.ro b,.drop b,.bar-earn b,#fairModal .fv-hand b,.vp-pay .pr b{font-weight:500;}

/* Bodoni and Cinzel ship a single 700 weight. Legacy rules ask for 900;
   with font-synthesis:none that renders 700 anyway — say it out loud. */
.rc-title,.rc-title small,.cab .cab-name,.slot-top .mname,.bar-hero h2,
.bj-msg span,#bigwin h1,.bar-art{font-weight:700;}


/* ============================================================================
   4. NUMERIC SURFACES — tabular everywhere, digit jitter dies here
   Any element that shows a changing number gets fixed-advance lining figures.
   ============================================================================ */

.chip-wallet,.chip-wallet b,
.ro b,.ro b *,
.stake-box .sv b,
.bj-score,
.bj-chip,
.bj-read .ro b,
.vp-pay .pr .px,
.vp-pay .pr b,
.drop b,
.bar-earn b,
.trk .tn,
.scrub time,
#bigwin .bw-amt,
#rulesModal td.p,
#fairModal .fv-hand b,
.earn-card h4,
.odometer,
.odometer .odometer-digit,
.odometer .odometer-value,
.odometer .odometer-digit-spacer,
.tabnum{
  font-variant-numeric:tabular-nums lining-nums;
  /* belt + braces for older WebKit that ignores font-variant-numeric */
  font-feature-settings:"tnum" 1,"lnum" 1,"kern" 1;
  -webkit-font-feature-settings:"tnum" 1,"lnum" 1,"kern" 1;
  font-variant-ligatures:none;
}


/* ============================================================================
   5. THE SIGNATURE MOVE — .engraved (antique brass) / .win-flare (flex gold)

   Rebuilt for Libre Bodoni. A high-contrast serif has hairlines roughly 1/8th
   the width of its stems; a gradient that runs all the way to --oldgold-lo
   simply erases them. So:
     - the pale specular occupies the TOP THIRD, where the hairlines live
     - the dark stop is pulled in to 100% and lightened
     - the gradient repeats once per line (background-size:100% var(--engrave-band))
     - solid --oldgold is the BASE, the gradient is the ENHANCEMENT.
       Painting it in this order means a browser without background-clip:text
       shows readable brass instead of invisible text.
   ============================================================================ */

/* --- base state: always readable, no clipping involved -------------------
   .sec-h is folded in here on purpose: index.html declares its gradient +
   color:transparent inline with NO fallback, so on a browser without
   background-clip:text every section head is currently invisible.        */
.engraved,.sec-h{
  display:inline-block;              /* iOS background-clip:text guard */
  background:none;
  color:var(--oldgold);
  -webkit-text-fill-color:currentColor;
  filter:none;
}
.win-flare{
  display:inline-block;              /* iOS background-clip:text guard */
  background:none;
  color:var(--gold);
  -webkit-text-fill-color:currentColor;
  filter:none;
}

/* --- enhancement: only where the clip actually works --------------------- */
@supports ((-webkit-background-clip:text) or (background-clip:text)){

  .engraved,.sec-h{
    background-image:linear-gradient(
      180deg,
      var(--gold2)      0%,
      #efe0ab          14%,
      var(--oldgold)   44%,
      #a87f21          72%,
      var(--oldgold-lo) 100%
    );
    background-size:100% var(--engrave-band);
    background-repeat:repeat-y;
    background-position:0 0;
    -webkit-background-clip:text;
    background-clip:text;
    color:transparent;
    /* -webkit-text-fill-color is the property WebKit actually honours here;
       leaving `color` set as well keeps selection + fallback sane. */
    -webkit-text-fill-color:transparent;
    filter:drop-shadow(0 1px 0 rgba(0,0,0,.6));
  }

  /* small engraved text (<=15px): hairlines are sub-pixel, so drop the dark
     half of the ramp entirely or the letterforms break up. */
  .engraved.sm,
  .sec-h,
  .cab .cab-tag.engraved,
  .bj-zone .z-label.engraved{
    background-image:linear-gradient(
      180deg,
      var(--gold2)    0%,
      #e4d296        38%,
      var(--oldgold) 100%
    );
    filter:drop-shadow(0 1px 0 rgba(0,0,0,.7));
  }

  .win-flare{
    background-image:linear-gradient(
      180deg,
      #fffbe8         0%,
      var(--gold2)   18%,
      var(--gold)    52%,
      #e0a92c        78%,
      var(--gold3)  100%
    );
    background-size:100% var(--engrave-band);
    background-repeat:repeat-y;
    background-position:0 0;
    -webkit-background-clip:text;
    background-clip:text;
    color:transparent;
    -webkit-text-fill-color:transparent;
    filter:drop-shadow(0 0 14px rgba(245,197,66,.34));
  }
}

/* iOS 15-17 paints the element's background RECTANGLE instead of the glyphs
   when a clipped-text node is inside a compositing layer that GSAP has just
   promoted. Forcing our own layer, with a transparent backdrop, wins. */
.engraved,.win-flare,.sec-h{
  -webkit-transform:translateZ(0);
  transform:translateZ(0);
  background-color:transparent !important;
}

/* one-shot specular sweep for a landed win — never a loop, never a scan line */
.win-flare.sweep{
  background-size:100% var(--engrave-band),220% 100%;
  animation:rc-flare 900ms cubic-bezier(.22,.61,.36,1) 1 both;
}
@keyframes rc-flare{
  0%  {filter:drop-shadow(0 0 6px  rgba(245,197,66,.15));}
  38% {filter:drop-shadow(0 0 22px rgba(245,197,66,.55));}
  100%{filter:drop-shadow(0 0 14px rgba(245,197,66,.34));}
}


/* ============================================================================
   6. HEADING BALANCE
   ============================================================================ */
@supports (text-wrap:balance){
  .rc-title,.rc-sub,.sec-h,.cab .cab-name,.slot-top .mname,.bar-hero h2,
  .earn-card h4,#bigwin h1,#fairModal h2,#fairModal h3,
  #rulesModal h2,#rulesModal h3,.bj-msg span,.vp-msg,.winbar{
    text-wrap:balance;
  }
}
@supports (text-wrap:pretty){
  #fairModal p,#rulesModal p,.earn-card p,.lore{text-wrap:pretty;}
}


/* ============================================================================
   7. SELECTOR MAP — ENTER SCREEN (#scr-enter)
   The crest. This is the only screen where Cinzel is allowed to speak.
   ============================================================================ */

.eyebrow{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  line-height:var(--lh-ui);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

.rc-title{
  font-family:var(--wordmark);
  font-weight:700;
  font-size:var(--fs-8);
  line-height:var(--lh-crest);
  letter-spacing:var(--ls-crest);
  text-transform:uppercase;
  /* centred + letterspaced text carries a phantom trailing space; pull it back
     or the wordmark sits visibly off-centre in the marquee */
  margin-right:calc(var(--ls-crest) * -1);
  font-variant-ligatures:none;
}
.rc-title small{
  display:block;
  font-family:var(--wordmark);
  font-weight:700;
  font-size:clamp(26px,7.8vw,42px);
  line-height:1.02;
  letter-spacing:var(--ls-crest-wide);
  text-transform:uppercase;
  margin-right:calc(var(--ls-crest-wide) * -1);
  margin-top:.06em;
}

.rc-sub{
  font-family:var(--wordmark);
  font-weight:700;
  font-size:12.5px;
  line-height:1.35;
  letter-spacing:.24em;
  text-transform:uppercase;
  margin-right:-.24em;
}

/* the one gold CTA on the screen. Action = Oswald, always. */
.btn-enter{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-6);
  line-height:1;
  letter-spacing:.14em;
  text-transform:uppercase;
}
/* opt-in variant if the integrator wants the CTA to read as part of the crest */
.btn-enter.crest{
  font-family:var(--wordmark);
  font-size:var(--fs-4);
  letter-spacing:var(--ls-crest);
  margin-right:calc(var(--ls-crest) * -1);
}

.fineprint{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  line-height:1.55;
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
  /* the legal line is information, not decoration — never gold, never loud */
  color:var(--dim);
}


/* ============================================================================
   8. SELECTOR MAP — FLOOR (#scr-floor)
   ============================================================================ */

.chip-wallet{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-4);
  line-height:1;
  letter-spacing:var(--ls-num);
}
.chip-wallet b{font-family:var(--ui);font-weight:500;}

.tb-btn{font-family:var(--ui);font-weight:500;letter-spacing:var(--ls-ui);}
.tb-btn.hq{
  font-family:var(--ui);
  font-size:var(--fs-2);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

.floor-marquee .rc-title{
  font-size:clamp(28px,8vw,42px);
  letter-spacing:var(--ls-crest);
  margin-right:calc(var(--ls-crest) * -1);
}
.floor-marquee .rc-title small{
  font-size:clamp(15px,4.4vw,21px);
  letter-spacing:var(--ls-crest-wide);
  margin-right:calc(var(--ls-crest-wide) * -1);
}

.ticker span{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  line-height:var(--lh-ui);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
  font-variant-numeric:tabular-nums lining-nums;
}

/* SECTION HEADS — engraved Bodoni. The one place brass touches the floor. */
.sec-h{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-4);
  line-height:1.08;
  --engrave-band:1.08em;
  letter-spacing:var(--ls-title-caps);
  text-transform:uppercase;
  display:inline-block;
  margin:16px 2px 9px;
}

/* CABINETS */
.cab .cab-name{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-5);
  line-height:1.1;
  letter-spacing:var(--ls-title);
  text-transform:none;      /* Bodoni mixed case reads as a record sleeve */
  color:var(--cream);
}
.cab .cab-tag{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  line-height:1.3;
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}
.cab .cab-cta{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  line-height:1;
  letter-spacing:.11em;
  text-transform:uppercase;
}
.cab.live::before{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
}

/* DROPS RAIL */
.drop{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  line-height:1.2;
  letter-spacing:var(--ls-ui);
  text-transform:uppercase;
}
.drop b{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:var(--ls-num);
}

/* THE CAGE */
.earn-card h4{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  line-height:var(--lh-ui);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}
.earn-card p{
  font-family:var(--body);
  font-weight:400;
  font-size:var(--fs-4);
  line-height:var(--lh-body);
  letter-spacing:var(--ls-body);
  text-transform:none;
}
.earn-card .go{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:.11em;
  text-transform:uppercase;
}


/* ============================================================================
   9. SELECTOR MAP — SLOTS (#scr-slot)
   ============================================================================ */

.slot-top .back,.slot-top .rules{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:var(--ls-ui);
  text-transform:uppercase;
}

.slot-top .mname{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-6);
  line-height:1.06;
  letter-spacing:var(--ls-title);
  text-transform:none;
}

.winbar{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-4);
  line-height:var(--lh-title);
  letter-spacing:var(--ls-title-caps);
  text-transform:uppercase;
}
.winbar.hot{font-size:var(--fs-5);}

/* READOUTS — label is Oswald micro-caps, value is Oswald tabular */
.ro label,.stake-box .sv label{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  line-height:1.4;
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}
.ro b{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-6);
  line-height:1.05;
  letter-spacing:var(--ls-num);
}
.stake-box .sv b{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-6);
  line-height:1.05;
  letter-spacing:var(--ls-num);
}
.stake-box .sb{font-family:var(--ui);font-weight:500;}

.btn-spin{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-6);
  line-height:1;
  letter-spacing:.1em;
  text-transform:uppercase;
}

.comp-btn{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:.11em;
  text-transform:uppercase;
}


/* ============================================================================
   10. SELECTOR MAP — BLACKJACK (#scr-table)
   ============================================================================ */

.bj-zone .z-label{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  line-height:1.3;
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

.bj-score{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  line-height:1;
  letter-spacing:var(--ls-num);
}

.bj-chip{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-4);
  line-height:1;
  letter-spacing:var(--ls-num);
}

.bj-btn{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-4);
  line-height:1;
  letter-spacing:.09em;
  text-transform:uppercase;
}
.bj-btn.ghost{font-size:var(--fs-3);letter-spacing:.1em;}

.bj-msg span{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-6);
  line-height:var(--lh-title);
  letter-spacing:var(--ls-title-caps);
  text-transform:uppercase;
}

.bj-insure .q{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-4);
  line-height:var(--lh-title);
  letter-spacing:var(--ls-title);
  text-transform:none;
}

/* the felt "DEALER STANDS ON 17" strip etc. */
.bj-table .rule-strip,
.bj-table > .felt-note{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}


/* ============================================================================
   11. ODOMETER — must beat the legacy `!important` rule in index.html
   `.bj-read .ro b .odometer{font-family:var(--display)!important}` would drag
   the rolling balance into Bodoni. Same-specificity + later + !important wins;
   the #scr-table variant is the guaranteed override.
   ============================================================================ */

.odometer,
.odometer.odometer-auto-theme,
.odometer.odometer-theme-default,
.ro b .odometer,
.bj-read .ro b .odometer,
#scr-table .bj-read .ro b .odometer,
#scr-slot .ro b .odometer{
  font-family:var(--ui) !important;
  font-weight:500 !important;
  letter-spacing:var(--ls-num) !important;
  font-variant-numeric:tabular-nums lining-nums;
  font-feature-settings:"tnum" 1,"lnum" 1;
}
/* keep the rolling digits the same optical size as a static readout */
.bj-read .ro b .odometer,
#scr-table .bj-read .ro b .odometer{font-size:var(--fs-6) !important;}

/* the odometer ribbon stacks digit spans; a proportional face would make the
   column breathe on every tick. Lock the advance. */
.odometer .odometer-digit,
.odometer .odometer-value,
.odometer .odometer-digit-spacer{
  font-family:var(--ui) !important;
  font-weight:500 !important;
  font-variant-numeric:tabular-nums lining-nums;
}


/* ============================================================================
   12. SELECTOR MAP — VIDEO POKER (#scr-vp)
   ============================================================================ */

.vp-pay .pr{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  line-height:1.25;
  letter-spacing:var(--ls-ui);
  text-transform:uppercase;
}
.vp-pay .pr b{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:var(--ls-ui);
}
.vp-pay .pr .px{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:var(--ls-num);
}
.vp-pay .maxnote{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

/* HOLD badge on a card */
.vp-card .hold,
.vp-card .badge{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

.vp-msg{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-4);
  line-height:var(--lh-title);
  letter-spacing:var(--ls-title-caps);
  text-transform:uppercase;
}
.vp-msg.hot{font-size:var(--fs-6);}

.btn-vpdeal{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-5);
  line-height:1;
  letter-spacing:.1em;
  text-transform:uppercase;
}


/* ============================================================================
   13. SELECTOR MAP — THE ALBUM BAR (#scr-bar)
   Track titles are the one place the record's own voice speaks: Cormorant.
   ============================================================================ */

.bar-art{
  font-family:var(--wordmark);
  font-weight:700;
  font-size:34px;
  line-height:1;
  letter-spacing:.04em;
  text-transform:uppercase;
  /* Cinzel's caps are wide; pull the phantom trailing space in the centred box */
  text-indent:.04em;
}

.bar-hero h2{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-6);
  line-height:1.06;
  letter-spacing:var(--ls-title);
  text-transform:none;
}
.bar-hero .bh-a{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  line-height:1.3;
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}
.bar-hero .bh-p{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  line-height:1.35;
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

.bar-earn b{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:var(--ls-num);
}
.bar-earn span{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

.bar-now .bn-title{
  font-family:var(--body);
  font-weight:600;
  font-size:var(--fs-5);
  line-height:1.25;
  letter-spacing:var(--ls-body);
}

.scrub time{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  letter-spacing:var(--ls-num);
  min-width:38px;   /* tabular figures need one extra px of gutter at this size */
}

/* TRACK LIST */
.trk .tn{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  letter-spacing:var(--ls-num);
  min-width:24px;
}
.trk .tt{
  font-family:var(--body);
  font-weight:600;
  font-size:var(--fs-5);
  line-height:1.3;
  letter-spacing:var(--ls-body);
}
.trk .ts{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}
/* the playing row gets weight, not just colour */
.trk.now .tt{font-weight:600;}

/* MINI PLAYER */
#miniBar .mb-t{
  font-family:var(--body);
  font-weight:600;
  font-size:var(--fs-4);
  line-height:1.25;
  letter-spacing:var(--ls-body);
}
#miniBar .mb-open{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}


/* ============================================================================
   14. SELECTOR MAP — MODALS, BIG WIN, TOAST
   ============================================================================ */

#fairModal h2,#rulesModal h2{
  font-family:var(--display);
  font-weight:700;
  font-size:var(--fs-7);
  line-height:var(--lh-title);
  letter-spacing:var(--ls-title);
  text-transform:none;
}
#fairModal h3,#rulesModal h3{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  line-height:var(--lh-ui);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}
#fairModal p,#rulesModal p{
  font-family:var(--body);
  font-weight:400;
  font-size:var(--fs-5);
  line-height:var(--lh-lore);
  letter-spacing:var(--ls-body);
  /* Cormorant (and the Georgia/Iowan fallback) default to OLD-STYLE figures —
     lovely in prose, wrong in copy that quotes seeds, nonces and multipliers.
     Modal prose is the one --body surface that carries real numbers. */
  font-variant-numeric:lining-nums;
  font-feature-settings:"lnum" 1;
}
#fairModal code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:var(--fs-2);
  letter-spacing:0;
  font-variant-ligatures:none;
}
#fairModal input{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-4);
  letter-spacing:var(--ls-ui-tight);
}
#fairModal .fv-hand{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-2);
  letter-spacing:var(--ls-ui);
}
#fairModal .fm-btn,#rulesModal .rm-close{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-4);
  letter-spacing:.11em;
  text-transform:uppercase;
}
#rulesModal table{font-family:var(--ui);font-weight:500;font-size:var(--fs-3);letter-spacing:var(--ls-ui);}
#rulesModal td.p{font-family:var(--ui);font-weight:500;letter-spacing:var(--ls-num);}

#bigwin h1{
  font-family:var(--display);
  font-weight:700;
  font-size:clamp(42px,12.5vw,80px);
  line-height:1.0;
  --engrave-band:1em;
  letter-spacing:.03em;
  text-transform:uppercase;
}
#bigwin .bw-amt{
  font-family:var(--ui);
  font-weight:500;
  font-size:clamp(30px,9.2vw,52px);
  line-height:1.05;
  --engrave-band:1.05em;
  letter-spacing:var(--ls-num);
}
#bigwin .bw-tap{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-1);
  letter-spacing:var(--ls-label);
  text-transform:uppercase;
}

#toast{
  font-family:var(--ui);
  font-weight:500;
  font-size:var(--fs-3);
  line-height:var(--lh-ui);
  letter-spacing:var(--ls-ui);
}


/* ============================================================================
   15. UTILITIES — for the new components landing in the makeover
   ============================================================================ */

.t-wordmark{font-family:var(--wordmark);font-weight:700;letter-spacing:var(--ls-crest);
  text-transform:uppercase;line-height:var(--lh-crest);}
.t-title   {font-family:var(--display);font-weight:700;letter-spacing:var(--ls-title);
  line-height:var(--lh-title);}
.t-title-caps{font-family:var(--display);font-weight:700;letter-spacing:var(--ls-title-caps);
  text-transform:uppercase;line-height:var(--lh-title);}
.t-body    {font-family:var(--body);font-weight:400;letter-spacing:var(--ls-body);
  line-height:var(--lh-body);}
.t-lore    {font-family:var(--body);font-weight:400;font-size:var(--fs-5);
  line-height:var(--lh-lore);letter-spacing:var(--ls-body);color:var(--dim);}
.t-ui      {font-family:var(--ui);font-weight:500;letter-spacing:var(--ls-ui);
  line-height:var(--lh-ui);}
.t-label   {font-family:var(--ui);font-weight:500;font-size:var(--fs-1);
  letter-spacing:var(--ls-label);text-transform:uppercase;line-height:1.4;color:var(--dim);}
.t-num     {font-family:var(--ui);font-weight:500;letter-spacing:var(--ls-num);
  font-variant-numeric:tabular-nums lining-nums;
  font-feature-settings:"tnum" 1,"lnum" 1;}

/* a hairline rule that reads as engraved brass, for section heads */
.t-rule{
  height:1px;border:0;margin:10px 0 14px;
  background:linear-gradient(90deg,var(--oldgold-lo),var(--oldgold) 22%,transparent 88%);
  opacity:.55;
}


/* ============================================================================
   16. ACCESSIBILITY + MOTION
   ============================================================================ */

@media (prefers-reduced-motion:reduce){
  .win-flare.sweep{animation:none;filter:drop-shadow(0 0 12px rgba(245,197,66,.3));}
}

/* Cormorant is beautiful and thin. When the OS asks for more contrast, or the
   viewport is tiny, trade elegance for legibility — restraint includes this. */
@media (prefers-contrast:more){
  body{font-weight:600;}
  .earn-card p,#fairModal p,#rulesModal p,.t-body,.t-lore{font-weight:600;}
  .cab .cab-tag,.trk .ts,.fineprint,.t-label{color:var(--cream);}
}

@media (max-width:340px){
  :root{
    --fs-1:9.5px; --fs-2:11px; --fs-3:12.5px;
    --fs-4:14px;  --fs-5:16px; --fs-6:19px;
  }
}

/* Windows High Contrast / forced colours: the clipped-gold trick renders as
   nothing. Hand the text back to the OS. */
@media (forced-colors:active){
  .engraved,.win-flare,.sec-h,#bigwin h1,#bigwin .bw-amt{
    background:none !important;
    -webkit-text-fill-color:currentColor !important;
    color:CanvasText !important;
    filter:none !important;
  }
}

/* Never let a serif hairline get antialiased into nothing on a dark field at
   very large sizes — subpixel-off + a touch of stroke keeps Bodoni solid. */
.rc-title,#bigwin h1,.slot-top .mname{
  -webkit-font-smoothing:antialiased;
  paint-order:stroke fill;
}


/* ============ MICRO =========== */
/* ============================================================================
   RAEKON CASINO — micro.css
   The "feels expensive" layer: motion tokens, tactile press, focus rings,
   skeletons, rim-glow, unified disabled, scrollbars, toast, safe-area, grain.

   HOW THIS FILE BEHAVES
   - Colors are TOKENS ONLY. The three `*-rgb` triples below are alpha
     companions to the existing hex tokens (same colors, expressed as channels
     so rgba() can take them). They are NOT new colors.
   - Almost every rule here is written at the SAME specificity as the rule it
     supersedes in index.html, so this file MUST be pasted/linked AFTER the
     existing <style> block. Later-wins is the whole strategy — there is
     exactly one `!important` cluster (reduced-motion), by design.
   - No new backdrop-filter layers. No moving-position animations anywhere.
     Nothing in here animates a gradient's position (no scanline reading).
   ============================================================================ */

:root{
  /* ---- motion tokens ------------------------------------------------------
     dur-1  micro feedback (press, tap, hover tint) — must feel instant
     dur-2  state change    (enable/disable, badge, held, toast in/out)
     dur-3  staged reveal   (rim glow, celebration ramps, panel settle)      */
  --dur-1:120ms;
  --dur-2:220ms;
  --dur-3:420ms;

  /* ease-out   — standard decel. Leaves fast, lands soft. Default for press. */
  --ease-out:cubic-bezier(.22,.61,.36,1);
  /* ease-spring— cheap, obvious overshoot. Use for chips, badges, small pops. */
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
  /* ease-lux   — WEIGHTED. Slow to break inertia (the control point is dragged
     back toward 0), then carries past the target by ~4% and settles. This is
     the house ease: velvet rope, brass hinge, a heavy drawer closing itself.  */
  --ease-lux:cubic-bezier(.34,.02,.16,1.04);

  /* ---- alpha companions to existing hex tokens (NOT new colors) ---------- */
  --violet-rgb:139,92,246;   /* = var(--violet)  #8b5cf6 */
  --gold-rgb:245,197,66;     /* = var(--gold)    #f5c542 */
  --oldgold-rgb:207,181,59;  /* = var(--oldgold) #cfb53b */
  --risk-rgb:176,58,74;      /* = var(--risk)    #b03a4a */

  /* Shadow-ledge stop for depressible gold CTAs. The app currently inlines
     #7a5410 in five places; --oldgold-lo (#7a5c14) is the token equivalent. */
  --ledge:var(--oldgold-lo);
}

/* ============================================================================
   1. TACTILE PRESS
   Every tap target squashes and sinks 1px, then settles on --ease-out.
   The PRESS SET below is the canonical list — add new tap targets to it, or
   just put class="rc-press" on them.
   NOTE: .cab .cab-cta is deliberately NOT in the set. The tap handler lives on
   .cab itself, so pressing both would compound two scales (.97 * .97).
   ============================================================================ */

.btn-enter,.tb-btn,.cab,.drop,.earn-card .go,
.btn-spin,.stake-box .sb,
.bj-btn,.bj-chip,
.btn-vpdeal,.vp-card,
.tp,.trk,
#miniBar button,#rulesModal .rm-close,
.rc-press{
  -webkit-tap-highlight-color:transparent;
  transform-origin:50% 55%;           /* pivot slightly low = "pushed into felt" */
  transition:
    transform  var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out),
    filter     var(--dur-2) var(--ease-out),
    opacity    var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    background-color var(--dur-2) var(--ease-out);
}

/* Base squash-settle. Supersedes the ad-hoc :active rules in index.html
   (.bj-btn:active, .stake-box .sb:active, .bj-chip:active). */
.btn-enter:active,.tb-btn:active,.cab:active,.drop:active,.earn-card .go:active,
.stake-box .sb:active,
.bj-btn:active,.bj-chip:active,
.vp-card:active,
.tp:active,
#miniBar button:active,
.rc-press:active{
  transform:scale(.97) translateY(1px);
  transition-duration:var(--dur-1);
}

/* List rows want a whisper, not a squash — they are wide, so scale reads big. */
.trk:active{
  transform:scale(.994) translateY(1px);
  background:rgba(var(--violet-rgb),.07);
}

/* Round chips get a touch more squash + the spring on release. */
.bj-chip{transition-timing-function:var(--ease-spring);}
.bj-chip:active{transform:scale(.94) translateY(2px);}

/* --- Gold CTAs: the ledge collapses so the button physically depresses ------
   Each of these rests on a "0 Npx 0" ledge. On press the ledge shortens to
   ~1px AND the button travels down by the amount the ledge lost, so the top
   face moves but the bottom edge stays put — a real key-travel depress.
   Selectors are specificity-matched to the originals (.bj-btn.gold:active is
   0,3,0 — it needs the .gold in the selector to be overridden).             */

.btn-spin:active{                                    /* rests on 0 7px 0 */
  transform:translateY(6px) scale(.985);
  box-shadow:0 1px 0 var(--ledge),0 6px 16px rgba(var(--gold-rgb),.26),
             inset 0 2px 4px rgba(255,255,255,.4);
}
.bj-btn.gold:active{                                 /* rests on 0 5px 0 */
  transform:translateY(4px) scale(.985);
  box-shadow:0 1px 0 var(--ledge);
}
.tp.big:active{                                      /* rests on 0 5px 0 */
  transform:translateY(4px) scale(.985);
  box-shadow:0 1px 0 var(--ledge),0 6px 14px rgba(var(--gold-rgb),.22);
}
.btn-vpdeal:active{                                  /* rests on 0 5px 0 */
  transform:translateY(4px) scale(.985);
  box-shadow:0 1px 0 var(--ledge),0 6px 14px rgba(var(--gold-rgb),.22);
}
.btn-enter:active,
#rulesModal .rm-close:active,
.cab.live .cab-cta:active{
  transform:translateY(3px) scale(.985);
  box-shadow:0 1px 0 var(--ledge);
}

/* Desktop/trackpad only — never on touch, where :hover sticks after a tap. */
@media (hover:hover) and (pointer:fine){
  .cab:hover{
    transform:translateY(-2px);
    box-shadow:0 14px 30px rgba(0,0,0,.45);
    border-color:rgba(var(--oldgold-rgb),.34);
  }
  .trk:hover{background:rgba(255,255,255,.035);}
  .tb-btn:hover,#miniBar button:hover{background:rgba(255,255,255,.1);}
  .bj-btn:hover:not([disabled]){border-color:rgba(var(--oldgold-rgb),.4);}
}

/* ============================================================================
   2. FOCUS-VISIBLE — keyboard, Switch Control, VoiceOver, Full Keyboard Access.
   Currently missing app-wide. :focus-visible never fires on plain touch, so
   this costs the phone experience nothing.
   ============================================================================ */

:focus{outline:none;}   /* we replace it below, not remove it */

button:focus-visible,
[role="button"]:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.cab:focus-visible,.trk:focus-visible,.vp-card:focus-visible,.rc-press:focus-visible{
  outline:2px solid var(--violet);
  outline-offset:3px;
  box-shadow:0 0 0 5px rgba(var(--violet-rgb),.22);
  /* keeps the ring readable on gold faces and on the dark felt alike */
}
/* Round targets: outline follows the border-radius on all modern engines. */
.btn-spin:focus-visible,.tp.big:focus-visible,.bj-chip:focus-visible{
  outline-offset:4px;
}
/* Anything scrollable that JS gives tabindex="0" shouldn't flash a huge ring. */
.floor-scroll:focus-visible,.bar-list:focus-visible{outline-offset:-3px;}

/* ============================================================================
   3. SKELETON SHIMMER — .sk
   ONE reusable class. The gradient is STATIC-POSITION: it never translates or
   moves background-position. Only OPACITY animates, so it reads as a surface
   catching light, never as a travelling scanline.
   Usage: <div class="sk" style="height:96px"></div>, or add .sk to a real
   element (text is hidden while loading, then remove the class).
   ============================================================================ */

.sk{
  position:relative;
  overflow:hidden;
  border-radius:12px;
  background:var(--panel2);
  border:1px solid rgba(var(--oldgold-rgb),.12);
  color:transparent !important;         /* hide real text while loading */
  pointer-events:none;
}
.sk > *{visibility:hidden;}
.sk::after{
  content:"";
  position:absolute;
  inset:0;
  /* fixed diagonal sheen — position never changes */
  background:linear-gradient(104deg,
    transparent 8%,
    rgba(var(--oldgold-rgb),.14) 42%,
    rgba(var(--oldgold-rgb),.22) 50%,
    rgba(var(--oldgold-rgb),.14) 58%,
    transparent 92%);
  animation:skBreathe 1500ms ease-in-out infinite;
}
@keyframes skBreathe{
  0%,100%{opacity:.22}
  50%    {opacity:1}
}
/* Shape helpers so a skeleton can mimic what's loading. */
.sk.sk-line{height:12px;border-radius:999px;margin:7px 0;}
.sk.sk-line.short{width:52%;}
.sk.sk-cab{height:172px;}
.sk.sk-row{height:44px;border-radius:10px;margin:6px 0;}
.sk.sk-circle{border-radius:50%;}

/* ============================================================================
   4. .glow-win — rim glow utility for the celebration module.
   An ::after overlay, so it never disturbs the element's own box-shadow or
   layout. Toggle .on to raise it; add .pulse for a slow breath (opacity only).
   Compositor-friendly: opacity is the only animated property.
   ============================================================================ */

.glow-win{position:relative;isolation:isolate;}
.glow-win::after{
  content:"";
  position:absolute;
  inset:-1px;
  border-radius:inherit;
  pointer-events:none;
  z-index:3;
  box-shadow:
    inset 0 0 0 1px rgba(var(--gold-rgb),.72),
    inset 0 0 20px rgba(var(--gold-rgb),.24),
    0 0 26px rgba(var(--gold-rgb),.34),
    0 0 60px rgba(var(--gold-rgb),.14);
  opacity:0;
  transition:opacity var(--dur-3) var(--ease-lux);
}
.glow-win.on::after{opacity:1;}
.glow-win.on.pulse::after{animation:winRim 1700ms ease-in-out infinite;}
@keyframes winRim{0%,100%{opacity:.55} 50%{opacity:1}}
/* Cooler variant for non-win emphasis (dealer turn, your action) — violet,
   so FLEX gold stays reserved for actual wins. */
.glow-win.cue::after{
  box-shadow:
    inset 0 0 0 1px rgba(var(--violet-rgb),.6),
    inset 0 0 18px rgba(var(--violet-rgb),.2),
    0 0 22px rgba(var(--violet-rgb),.3);
}

/* ============================================================================
   5. DISABLED — one treatment everywhere.
   Today: .bj-btn[disabled] is opacity .35; .btn-spin[disabled] is
   grayscale(.55) brightness(.75); .bj-chip[disabled] is grayscale(.7)
   brightness(.6); .earn-card .go[disabled] swaps its background. Three
   different "off" looks. This unifies them: drained saturation + a fixed
   opacity, and any raised CTA drops onto a dead black ledge.
   Selectors are explicit (not :where) so they out-specify the originals.
   ============================================================================ */

.btn-enter[disabled],.tb-btn[disabled],.earn-card .go[disabled],.earn-card .go.done,
.btn-spin[disabled],.stake-box .sb[disabled],
.bj-btn[disabled],.bj-chip[disabled],
.btn-vpdeal[disabled],
.tp[disabled],
#miniBar button[disabled],
[aria-disabled="true"],
.is-disabled{
  opacity:.42;
  filter:saturate(.28) brightness(.84);
  pointer-events:none;
  cursor:default;
  transform:none;
  text-shadow:none;
}
/* Raised gold CTAs lose their warm ledge + glow and sit on a flat dark lip. */
.btn-spin[disabled],
.bj-btn.gold[disabled],
.btn-vpdeal[disabled],
.tp.big[disabled]{
  box-shadow:0 3px 0 rgba(0,0,0,.45);
}
/* Chips keep their disc shading, just drained — they must still read as chips. */
.bj-chip[disabled]{filter:saturate(.2) brightness(.7);box-shadow:0 2px 0 rgba(0,0,0,.4);}
/* Soft-disabled: still tappable (so it can toast "why"), but reads as inert. */
.is-locked{opacity:.55;filter:saturate(.4);}

/* ============================================================================
   6. SCROLLBARS — floor + track list. Thin, --edge track, --oldgold thumb.
   Scoped, not global: the .drops strip intentionally hides its bar.
   ============================================================================ */

.floor-scroll,.bar-list,.vp-pay,.scroll-lux{
  scrollbar-width:thin;                              /* Firefox / modern std */
  scrollbar-color:var(--oldgold-lo) var(--edge);
}
.floor-scroll::-webkit-scrollbar,
.bar-list::-webkit-scrollbar,
.vp-pay::-webkit-scrollbar,
.scroll-lux::-webkit-scrollbar{width:6px;height:6px;}

.floor-scroll::-webkit-scrollbar-track,
.bar-list::-webkit-scrollbar-track,
.vp-pay::-webkit-scrollbar-track,
.scroll-lux::-webkit-scrollbar-track{
  background:var(--edge);
  border-radius:999px;
}
.floor-scroll::-webkit-scrollbar-thumb,
.bar-list::-webkit-scrollbar-thumb,
.vp-pay::-webkit-scrollbar-thumb,
.scroll-lux::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,var(--oldgold),var(--oldgold-lo));
  border-radius:999px;
}
.floor-scroll::-webkit-scrollbar-thumb:hover,
.bar-list::-webkit-scrollbar-thumb:hover,
.scroll-lux::-webkit-scrollbar-thumb:hover{background:var(--oldgold);}
/* iOS Safari draws its own overlay bar and ignores the above — harmless. */

/* ============================================================================
   7. ::selection
   ============================================================================ */

::selection{background:var(--violet-dim);color:var(--cream);text-shadow:none;}
::-moz-selection{background:var(--violet-dim);color:var(--cream);text-shadow:none;}

/* ============================================================================
   8. #toast — engraved brass pill.
   Replaces the flat #241033 pill. Antique brass hairline, a specular top edge
   and a dark under-lip (inset shadows = the "engraved" read), sitting on the
   panel gradient. Same id specificity as the original, so paste order decides.
   ============================================================================ */

#toast{
  position:fixed;
  left:50%;
  bottom:calc(90px + env(safe-area-inset-bottom));
  transform:translateX(-50%) translateY(14px) scale(.98);
  z-index:350;
  max-width:min(88vw,420px);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  font-family:var(--display);
  font-size:13px;
  letter-spacing:1.6px;
  text-transform:uppercase;
  color:var(--cream);
  padding:11px 22px;
  border-radius:999px;
  background:
    linear-gradient(180deg,rgba(var(--oldgold-rgb),.10),rgba(var(--oldgold-rgb),0) 46%),
    linear-gradient(180deg,var(--panel2),var(--ink-2));
  border:1px solid rgba(var(--oldgold-rgb),.42);
  box-shadow:
    inset 0 1px 0 rgba(var(--oldgold-rgb),.55),   /* top specular — the bevel  */
    inset 0 -1px 0 rgba(0,0,0,.6),                /* under-lip — the engraving */
    0 10px 30px rgba(0,0,0,.55),
    0 0 0 1px rgba(0,0,0,.4);                     /* seats it off the felt     */
  opacity:0;
  pointer-events:none;
  transition:
    opacity   var(--dur-2) var(--ease-out),
    transform var(--dur-3) var(--ease-lux);
}
#toast.show{
  opacity:1;
  transform:translateX(-50%) translateY(0) scale(1);
}
/* Win-flavoured toast: the ONE place the pill is allowed flex gold. */
#toast.win{
  color:var(--gold2);
  border-color:rgba(var(--gold-rgb),.5);
  box-shadow:
    inset 0 1px 0 rgba(var(--gold-rgb),.6),
    inset 0 -1px 0 rgba(0,0,0,.6),
    0 10px 30px rgba(0,0,0,.55),
    0 0 26px rgba(var(--gold-rgb),.2);
}
#toast.bad{color:var(--red);border-color:rgba(var(--risk-rgb),.7);}
/* Raise the pill above the floor mini-player when it's on screen. */
body[data-screen="floor"] #miniBar.on ~ #toast,
body.mini-on #toast{bottom:calc(150px + env(safe-area-inset-bottom));}

/* ============================================================================
   9. SAFE-AREA HELPERS — notch / home indicator.
   Set --pad-t / --pad-b per element to control the base padding; the inset is
   added on top. constant() is the pre-iOS-11.2 spelling and must come first.
   ============================================================================ */

.pad-top-safe{
  padding-top:calc(var(--pad-t,12px) + constant(safe-area-inset-top));
  padding-top:calc(var(--pad-t,12px) + env(safe-area-inset-top));
}
.pad-bottom-safe{
  padding-bottom:calc(var(--pad-b,16px) + constant(safe-area-inset-bottom));
  padding-bottom:calc(var(--pad-b,16px) + env(safe-area-inset-bottom));
}
.pad-x-safe{
  padding-left:calc(var(--pad-x,14px) + env(safe-area-inset-left));
  padding-right:calc(var(--pad-x,14px) + env(safe-area-inset-right));
}
/* Fixed elements pinned to the bottom (mini-player, sticky CTAs). */
.pin-bottom-safe{bottom:calc(var(--pin-b,12px) + env(safe-area-inset-bottom));}
/* Landscape on a notched phone: the notch is on a SIDE, and the app is
   overflow:hidden, so screens must inset horizontally or content clips. */
@media (orientation:landscape){
  .screen > .inner{
    padding-left:env(safe-area-inset-left);
    padding-right:env(safe-area-inset-right);
  }
}

/* ============================================================================
   10. STATIC GRAIN — .grain
   ONE inline feTurbulence baked to a data-URI (~360 bytes), tiled at 160px,
   desaturated, blended over. It NEVER animates — no film-flicker, no drift.

   ! SCOPE IT. Put .grain on a container (a .marquee-sign, a .cab .art, a
   ! .bj-table, a modal) — NEVER on <body> or a full-screen .felt. A body-wide
   ! blended overlay forces iOS Safari to composite the entire viewport every
   ! paint, which is exactly the frame-budget you need for reel spins and card
   ! flips. Small boxes = free. Full screen = 10-15fps on an older iPhone.
   ============================================================================ */

.grain{position:relative;}
.grain::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:1;
  pointer-events:none;
  border-radius:inherit;
  opacity:.035;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.86' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;
}
/* If a container's own content sits above z-index 1, use .grain.grain-under
   to drop the noise behind it instead of over it. */
.grain.grain-under::after{z-index:0;}
/* Heavier pass for large flat velvet panels that band on OLED. */
.grain.grain-strong::after{opacity:.055;}

/* ============================================================================
   11. REDUCED MOTION
   Neutralizes every transition and animation defined in THIS file. Press
   feedback survives as an opacity dip, so the app still confirms taps —
   removing feedback entirely is worse for accessibility than removing motion.
   ============================================================================ */

@media (prefers-reduced-motion:reduce){

  .btn-enter,.tb-btn,.cab,.drop,.earn-card .go,
  .btn-spin,.stake-box .sb,
  .bj-btn,.bj-chip,
  .btn-vpdeal,.vp-card,
  .tp,.trk,
  #miniBar button,#rulesModal .rm-close,
  .rc-press,
  .sk,.sk::after,
  .glow-win,.glow-win::after,
  #toast{
    transition:none !important;
    animation:none !important;
  }

  /* No squash, no travel, no ledge collapse — just a legible dip. */
  .btn-enter:active,.tb-btn:active,.cab:active,.drop:active,.earn-card .go:active,
  .btn-spin:active,.stake-box .sb:active,
  .bj-btn:active,.bj-btn.gold:active,.bj-chip:active,
  .btn-vpdeal:active,.vp-card:active,
  .tp:active,.tp.big:active,.trk:active,
  #miniBar button:active,#rulesModal .rm-close:active,
  .cab.live .cab-cta:active,
  .rc-press:active{
    transform:none !important;
    opacity:.72;
  }
  @media (hover:hover) and (pointer:fine){
    .cab:hover{transform:none !important;}
  }

  /* Skeletons hold at a steady mid-tone instead of breathing. */
  .sk::after{opacity:.5 !important;}
  /* Rim glow still appears (it carries meaning) — it just doesn't pulse. */
  .glow-win.on::after{opacity:1 !important;}
  /* Toast: no slide, no scale — fade only. */
  #toast{transform:translateX(-50%) !important;}
  #toast.show{transform:translateX(-50%) !important;}
}


/* ============ BENTO FLOOR ===== */
/* ==========================================================================
   RAEKON CASINO — BENTO VELVET FLOOR
   "A Raekwon record you gamble inside — velvet vault, one gold stroke."
   --------------------------------------------------------------------------
   Scope of this file: the FLOOR screen's machine grid (.machines / .cab),
   plus three app-wide primitives that belong to the same system:
     · elevation tokens   (--e-1 / --e-2 / --e-3, one light vector)
     · spacing + radius   (--sp-* / --r-*)
     · .glass             (the ONE backdrop-filter recipe)

   Rules obeyed:
     · vanilla CSS, no build step, no CDN, no images, no canvas
     · iOS Safari primary — every tile paints ONCE and never re-paints on
       scroll (no backdrop-filter, no filter, no animation on tiles)
     · no moving vertical scan/tracking lines anywhere
     · prefers-reduced-motion honoured at the bottom of the file
     · comp chips only — no $ signs, no urgency, no countdowns, no pulsing
     · 60-30-10: 60 aubergine velvet / 30 antique brass / 10 flex gold.
       FLEX GOLD (--gold) APPEARS EXACTLY ONCE ON THIS SCREEN: the hero
       tile's CTA. Every other live CTA is violet (--violet = primary action).
   ========================================================================== */


/* ==========================================================================
   0 · TOKENS
   Only new tokens live here. Every colour comes from the existing :root set.
   ========================================================================== */
:root{

  /* ---- spacing scale (4px base, one step of 6 for optical gaps) ---------- */
  --sp-0: 2px;
  --sp-1: 4px;
  --sp-2: 6px;
  --sp-3: 8px;
  --sp-4: 12px;
  --sp-5: 16px;
  --sp-6: 24px;

  /* ---- radii: sharper reads richer. 14px was "app", 6px is "object". ----- */
  --r-1: 3px;    /* inner brass rule, micro pills                            */
  --r-2: 6px;    /* THE tile radius — cabinets, buttons, plates              */
  --r-3: 10px;   /* large containers only (marquee, modal)                   */
  --r-pill: 999px;

  /* ---- ONE LIGHT VECTOR, APP-WIDE --------------------------------------
     The lamp is above and to the LEFT (about 10 o'clock). Therefore:
       · every drop shadow offsets +x (right) and +y (down)
       · every rim highlight sits on the TOP and LEFT edges
       · every inner shade sits on the BOTTOM and RIGHT edges
     Never flip this. Consistency is what makes the floor read as one room.
     ---------------------------------------------------------------------- */
  --e-1:
    1px 1px 2px rgba(0,0,0,.30),
    2px 4px 10px rgba(0,0,0,.24);
  --e-2:
    2px 2px 4px rgba(0,0,0,.32),
    4px 10px 22px rgba(0,0,0,.30);
  --e-3:
    3px 3px 6px rgba(0,0,0,.34),
    7px 18px 42px rgba(0,0,0,.40);

  /* rim light + inner shade, matched to the vector above (use as inset) */
  --rim:   inset 1px 1px 0 rgba(255,255,255,.055);
  --shade: inset -1px -1px 0 rgba(0,0,0,.38);

  /* ---- brass frame -------------------------------------------------------
     Two rules with a gap between them = art-deco. Low alpha keeps brass at
     ~30% of the visual budget instead of screaming.                         */
  --brass-out:  rgba(207,181,59,.26);   /* outer thin rule  (--oldgold)      */
  --brass-in:   rgba(207,181,59,.17);   /* inner thick rule                  */
  --brass-tick: rgba(207,181,59,.42);   /* corner notches                    */
  --frame-gap:  4px;                    /* distance between the two rules    */

  /* ---- bento geometry ---------------------------------------------------- */
  --bento-gap: 10px;
  --cab-row:   124px;   /* one grid row. hero = 2 rows + gap = 258px          */

  /* ---- VELVET SURFACE ----------------------------------------------------
     Napped velvet in four gradient layers, painted top→bottom in this list
     (first layer = topmost). Held in a custom property so variants can
     prepend a layer (see .cab--pinstripe) without restating the recipe.

       1. NAP SHEEN  — a broad diagonal wipe, bright at the top-left corner,
                       falling to a dark toe at the bottom-right. This is the
                       "brushed against the grain" light and it MUST run with
                       the app light vector (148deg ≈ down-and-right).
       2. FIBRE      — a second, much finer counter-sheen at a near-right
                       angle to the first. Real velvet catches light twice.
       3. BLOOM      — a soft radial swell of violet near the lamp corner.
                       This is what stops the tile reading as flat plastic.
       4. FLOOR POOL — darkness pooling under the tile, bottom-centre.
       5. BASE       — the cloth itself: panel2 → panel → ink-2.
     ---------------------------------------------------------------------- */
  --velvet:
    linear-gradient(148deg,
      rgba(255,255,255,.085) 0%,
      rgba(255,255,255,.028) 22%,
      rgba(255,255,255,0)    46%,
      rgba(0,0,0,.10)        72%,
      rgba(0,0,0,.26)       100%),
    linear-gradient(62deg,
      rgba(255,255,255,.030) 0%,
      rgba(255,255,255,0)    38%,
      rgba(0,0,0,.06)       100%),
    radial-gradient(125% 95% at 18% 4%,
      rgba(139,92,246,.20), rgba(139,92,246,0) 58%),
    radial-gradient(95% 72% at 50% 116%,
      rgba(0,0,0,.42), rgba(0,0,0,0) 64%),
    linear-gradient(168deg,
      var(--panel2) 0%, var(--panel) 58%, var(--ink-2) 100%);

  /* Hero cloth: same weave, one stop richer (panel3) and a warmer bloom.    */
  --velvet-hero:
    linear-gradient(148deg,
      rgba(255,255,255,.10)  0%,
      rgba(255,255,255,.035) 20%,
      rgba(255,255,255,0)    44%,
      rgba(0,0,0,.12)        70%,
      rgba(0,0,0,.30)       100%),
    linear-gradient(62deg,
      rgba(255,255,255,.034) 0%,
      rgba(255,255,255,0)    38%,
      rgba(0,0,0,.07)       100%),
    radial-gradient(120% 90% at 16% 2%,
      rgba(139,92,246,.24), rgba(139,92,246,0) 56%),
    radial-gradient(85% 62% at 78% 96%,
      rgba(207,181,59,.10), rgba(207,181,59,0) 62%),
    radial-gradient(95% 72% at 50% 118%,
      rgba(0,0,0,.44), rgba(0,0,0,0) 64%),
    linear-gradient(168deg,
      var(--panel3) 0%, var(--panel2) 52%, var(--ink-2) 100%);

  /* ---- PINSTRIPE ---------------------------------------------------------
     A gradient's ANGLE is its axis, so stripes render perpendicular to it:
     94deg gives near-VERTICAL stripes raked 4° off plumb — a suit length
     laid slightly on the bias. Contrast is deliberately at the edge of
     visible (.035 cream); if you can "see stripes" from arm's length it is
     too strong. 1px ink every 7px.                                          */
  --pinstripe:
    repeating-linear-gradient(94deg,
      rgba(243,236,246,0)    0px,
      rgba(243,236,246,0)    6px,
      rgba(243,236,246,.038) 6px,
      rgba(243,236,246,.038) 7px);

  /* ---- corner notches ----------------------------------------------------
     Four 45° mitre ticks, one per corner of the inner rule, drawn as
     backgrounds on a single pseudo-element (no border-image, no extra DOM).
     A gradient's bands run PERPENDICULAR to its angle, so the two diagonals
     have to be mirrored or all four corners point the same way and the frame
     reads as slashed rather than mitred:
       135deg -> "/" band  -> top-LEFT and bottom-RIGHT corners
        45deg -> "\" band  -> top-RIGHT and bottom-LEFT corners             */
  --notch-a: linear-gradient(45deg,
      rgba(0,0,0,0) 44%, var(--brass-tick) 44%, var(--brass-tick) 56%,
      rgba(0,0,0,0) 56%);
  --notch-b: linear-gradient(135deg,
      rgba(0,0,0,0) 44%, var(--brass-tick) 44%, var(--brass-tick) 56%,
      rgba(0,0,0,0) 56%);
  --notch-size: 9px;
}


/* ==========================================================================
   1 · THE BENTO GRID
   Four columns always. The column count NEVER changes — only what the tiles
   span changes. That keeps the brass frames on a shared vertical rhythm at
   every width, which is the whole point of a bento.
   ========================================================================== */
.machines{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* minmax(row, auto): tiles get a guaranteed height but a long track title
     is allowed to push its own row taller rather than clipping.            */
  grid-auto-rows: minmax(var(--cab-row), auto);
  gap: var(--bento-gap);
  align-items: stretch;
  /* DOM order == reading order. No `dense` — dense reorders tiles visually
     away from tab order and would float track plates above the table games. */
  grid-auto-flow: row;
}


/* ==========================================================================
   2 · THE CABINET (base)
   Default .cab with no modifier spans 2 columns, i.e. it is safe in the old
   two-up world. Modifiers only ever widen or narrow that.
   ========================================================================== */
.cab{
  position: relative;
  grid-column: span 2;
  display: flex;
  flex-direction: column;
  min-width: 0;                 /* lets long names ellipsis instead of blow out */
  padding: 0 0 var(--sp-4);
  text-align: center;
  overflow: hidden;
  border-radius: var(--r-2);

  /* velvet surface + outer thin brass rule */
  background: var(--velvet);
  border: 1px solid var(--brass-out);

  box-shadow: var(--e-2), var(--rim), var(--shade);

  /* paint containment: the tile can never invalidate its neighbours, so a
     20-tile floor stays a single cheap layer on iOS.                        */
  contain: layout paint style;

  transition:
    transform .16s cubic-bezier(.2,.7,.3,1),
    box-shadow .16s cubic-bezier(.2,.7,.3,1),
    border-color .16s linear;
}

/* ---- 2a · ART-DECO INNER RULE + CORNER NOTCHES ---------------------------
   ::after is the inner (thicker) rule, held --frame-gap away from the outer
   one. Its own background carries the four 45° corner ticks, so the notches
   land exactly on the inner frame's corners with zero extra elements.
   (::before is reserved — it is the LIVE badge, see §5.)                    */
.cab::after{
  content: "";
  position: absolute;
  inset: var(--frame-gap);
  border: 1.5px solid var(--brass-in);
  border-radius: var(--r-1);
  pointer-events: none;
  z-index: 3;

  /* order: top-left, top-right, bottom-left, bottom-right */
  background-image: var(--notch-b), var(--notch-a), var(--notch-a), var(--notch-b);
  background-size: var(--notch-size) var(--notch-size);
  background-repeat: no-repeat;
  background-position:
    left  -1px top    -1px,
    right -1px top    -1px,
    left  -1px bottom -1px,
    right -1px bottom -1px;
}

/* ---- 2b · ART WELL ------------------------------------------------------
   The .art element carries a JS-generated inline hsl() gradient (random hue
   per machine id). We cannot override an inline background — so we glaze it.
   .art::after is an aubergine scrim that pulls every random hue back toward
   the Purple Tape palette, plus the same top-left lamp.

   IMPORTANT — WHY THE ART HEIGHT IS FIXED AND NOT flex:1
   The brass seam under the art is the strongest horizontal line on the
   floor. If .art grew to fill leftover space, a tile whose title wraps to
   three lines would have a shorter well than its neighbour and the seams
   across a row would go ragged. Fixed height per variant + margin-top:auto
   on the CTA means every seam in a row lands on the same pixel and the
   slack is absorbed invisibly above the button.                            */
.cab .art{
  position: relative;
  flex: 0 0 auto;
  height: 84px;
  min-height: 0;
  margin: 0 0 var(--sp-3);
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid rgba(207,181,59,.14);
  overflow: hidden;
}
.cab .art::after{
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* lamp */
    radial-gradient(90% 80% at 20% 0%, rgba(255,255,255,.10), rgba(255,255,255,0) 60%),
    /* aubergine glaze — this is the hue unifier */
    linear-gradient(160deg, rgba(36,16,51,.30) 0%, rgba(26,13,36,.46) 55%, rgba(18,8,20,.70) 100%),
    /* floor pool */
    radial-gradient(80% 70% at 50% 104%, rgba(0,0,0,.44), rgba(0,0,0,0) 62%);
}
.cab .art .glyph{
  position: relative;
  z-index: 1;
  font-size: 34px;
  line-height: 1;
  filter: drop-shadow(2px 4px 10px rgba(0,0,0,.62));
}
/* forward-compat: when the emoji glyphs become authored SVG marks */
.cab .art > svg{
  position: relative;
  z-index: 1;
  width: 44%;
  max-width: 64px;
  height: auto;
  filter: drop-shadow(2px 4px 10px rgba(0,0,0,.62));
}

/* ---- 2c · TYPE ---------------------------------------------------------- */
.cab .cab-name{
  position: relative;
  z-index: 2;
  font-family: var(--display);
  font-weight: 900;
  letter-spacing: 1.4px;
  font-size: 14px;
  line-height: 1.08;
  color: var(--cream);
  min-height: 0;
  padding: 0 var(--sp-4);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.cab .cab-tag{
  position: relative;
  z-index: 2;
  font-size: 8.5px;
  letter-spacing: 1.6px;
  color: var(--dim);
  text-transform: uppercase;
  margin: var(--sp-1) 0 var(--sp-3);
  padding: 0 var(--sp-4);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- 2d · CTA (base = the quiet, reserved state) ------------------------ */
.cab .cab-cta{
  position: relative;
  z-index: 2;
  display: block;
  margin: auto var(--sp-4) 0;      /* auto-top pins the CTA to the tile floor */
  padding: var(--sp-2) 0;
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: 2.2px;
  font-size: 11px;
  border-radius: var(--r-2);
  color: var(--dim);
  background: rgba(255,255,255,.045);
  border: 1px solid rgba(207,181,59,.20);
  box-shadow: var(--rim);
}


/* ==========================================================================
   3 · THE THREE TILE SIZES
   Applied by the integrator per machine kind. Nothing here changes colour —
   size and layout only, so kind and state stay orthogonal.
   ========================================================================== */

/* ---- 3a · HERO — THE CHEF'S TABLE. 2 cols × 2 rows. --------------------- */
.cab--hero{
  grid-column: span 2;
  grid-row: span 2;
  padding-bottom: var(--sp-5);
  background: var(--velvet-hero);
  border-color: rgba(207,181,59,.34);
  box-shadow: var(--e-3), var(--rim), var(--shade);
}
.cab--hero::after{ border-color: rgba(207,181,59,.26); }
/* the hero is the only tile with no same-height neighbour, so its well is
   allowed to grow into whatever the 2-row span leaves over */
.cab--hero .art{ flex: 1 1 auto; height: auto; min-height: 118px; margin-bottom: var(--sp-4); }
.cab--hero .art .glyph{ font-size: 56px; }
.cab--hero .art > svg{ width: 46%; max-width: 96px; }
.machines .cab--hero .cab-name{
  font-size: 19px;
  letter-spacing: 1.8px;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
.machines .cab--hero .cab-tag{ font-size: 9px; letter-spacing: 2px; }
.machines .cab--hero .cab-cta{ padding: var(--sp-3) 0; font-size: 12.5px; letter-spacing: 2.6px; }

/* ---- 3b · WIDE — blackjack + video poker. 2 cols × 1 row. --------------- */
.cab--wide{
  grid-column: span 2;
  grid-row: span 1;
}
/* A wide tile is 2 of 4 columns, so it is only ~half the viewport. A
   horizontal art|text|CTA strip needs about 360px of TILE width before the
   title stops truncating — which means roughly 860px of VIEWPORT. Below
   that the wide tile stays a vertical card and simply reads as a shorter
   hero. The strip is opted into at >=860px in §7c.                         */
.cab--wide .art{ height: 72px; }
.cab--wide .art .glyph{ font-size: 30px; }
.machines .cab--wide .cab-name{ font-size: 13px; -webkit-line-clamp: 2; line-clamp: 2; }

/* ---- 3c · PLATE — the 17 track machines. 1 col × 1 row (2 cols on phone). */
.cab--plate{
  grid-column: span 2;             /* mobile-first: 2-up */
  grid-row: span 1;
  padding-bottom: var(--sp-3);
  box-shadow: var(--e-1), var(--rim), var(--shade);
  --frame-gap: 3px;                /* tighter frame on a small object */
  --notch-size: 7px;
}
.cab--plate::after{ border-width: 1px; }
.cab--plate .art{ height: 56px; margin-bottom: var(--sp-2); }
.cab--plate .art .glyph{ font-size: 24px; }
.cab--plate .art > svg{ width: 40%; max-width: 38px; }
.machines .cab--plate .cab-name{
  font-size: 10.5px;
  letter-spacing: .9px;
  line-height: 1.12;
  padding: 0 var(--sp-2);
  -webkit-line-clamp: 3;
  line-clamp: 3;
}
.machines .cab--plate .cab-tag{
  font-size: 7.5px;
  letter-spacing: 1.1px;
  margin: var(--sp-0) 0 var(--sp-2);
  padding: 0 var(--sp-2);
}
.machines .cab--plate .cab-cta{
  margin: auto var(--sp-2) 0;
  padding: var(--sp-1) 0;
  font-size: 9px;
  letter-spacing: 1.6px;
  border-radius: var(--r-1);
}


/* ==========================================================================
   4 · SURFACE VARIANT — PINSTRIPE
   Opt-in. The stripe layer is PREPENDED to the velvet stack so it sits on
   top of the cloth but under the frame and the content.
   Use sparingly — pinstripe on every tile is a costume, not a suit. The
   intended use is the two table games (wide tiles).
   ========================================================================== */
.cab--pinstripe{ background: var(--pinstripe), var(--velvet); }
.cab--hero.cab--pinstripe{ background: var(--pinstripe), var(--velvet-hero); }


/* ==========================================================================
   5 · STATES
   ========================================================================== */

/* ---- 5a · LIVE ---------------------------------------------------------
   Brass, not green. Nothing pulses: a pulsing dot is urgency theatre and we
   do not do urgency. The badge is an ENGRAVED plate — dark inset pill, brass
   letterforms, a black shadow below the glyphs and a hairline highlight
   above them, exactly like the section headers.                             */
.cab.live{
  border-color: rgba(207,181,59,.40);
}
.cab.live::after{ border-color: rgba(207,181,59,.24); }

.cab.live::before{
  content: "LIVE";
  position: absolute;
  top: 9px;
  left: 9px;
  z-index: 4;

  font-family: var(--display);
  font-weight: 700;
  font-size: 8.5px;
  letter-spacing: 2.2px;
  line-height: 1;
  padding: 4px 8px 3px;

  color: var(--oldgold);
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, rgba(12,5,16,.82), rgba(12,5,16,.62));
  border: 1px solid rgba(207,181,59,.38);
  /* engraving: cut below, catch-light above */
  text-shadow:
     0 1px 0 rgba(0,0,0,.85),
     0 -1px 0 rgba(255,243,196,.10);
  box-shadow:
    inset 0 1px 0 rgba(255,243,196,.10),
    inset 0 -1px 0 rgba(0,0,0,.55),
    var(--e-1);
  animation: none;                 /* kills the inherited livePulse */
}
.machines .cab--plate.live::before{
  top: 7px; left: 7px;
  font-size: 7.5px; letter-spacing: 1.6px; padding: 3px 6px 2px;
}

/* ---- 5b · CTAs by rank -------------------------------------------------
   THE FLEX-GOLD RULE. One gold stroke per screen. On the floor that stroke
   is the hero's PLAY button and nothing else. Blackjack and video poker are
   live and important — so they get VIOLET, the primary-action colour.       */
.cab--hero.live .cab-cta{
  color: #1a1206;
  font-weight: 900;
  background: linear-gradient(180deg, var(--gold2) 0%, var(--gold) 46%, var(--gold3) 100%);
  border: 1px solid rgba(255,243,196,.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -2px 0 rgba(0,0,0,.20),
    0 2px 10px rgba(245,197,66,.22),
    var(--e-1);
  text-shadow: 0 1px 0 rgba(255,243,196,.45);
}
.cab--wide.live .cab-cta,
.cab--plate.live .cab-cta{
  color: #f4efff;
  font-weight: 800;
  background: linear-gradient(180deg, var(--violet) 0%, var(--violet-dim) 100%);
  border: 1px solid rgba(180,150,255,.42);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.20),
    inset 0 -2px 0 rgba(0,0,0,.24),
    var(--e-1);
}
/* A .live tile with no size modifier still needs to look live — violet. */
.cab.live .cab-cta{
  color: #f4efff;
  font-weight: 800;
  background: linear-gradient(180deg, var(--violet) 0%, var(--violet-dim) 100%);
  border: 1px solid rgba(180,150,255,.42);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.20),
    inset 0 -2px 0 rgba(0,0,0,.24),
    var(--e-1);
}
/* re-assert the gold hero above the generic .live rule (same specificity,
   later source order wins — keep this block last) */
.cab--hero.live .cab-cta{
  color: #1a1206;
  font-weight: 900;
  background: linear-gradient(180deg, var(--gold2) 0%, var(--gold) 46%, var(--gold3) 100%);
  border: 1px solid rgba(255,243,196,.55);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -2px 0 rgba(0,0,0,.20),
    0 2px 10px rgba(245,197,66,.22),
    var(--e-1);
}

/* ---- 5c · SOON / RESERVED ---------------------------------------------
   Reserved is not broken — it is a table with a cloth over it. Desaturate
   the art, keep the brass frame at full strength.                           */
.cab.soon .art{ filter: saturate(.22) brightness(.62); }
.cab.soon .art::after{ opacity: .9; }
.cab.soon .cab-name{ color: rgba(243,236,246,.62); }
.cab.soon .cab-tag{ color: rgba(167,149,181,.72); }
.cab.soon .cab-cta{
  color: rgba(207,181,59,.66);
  background: rgba(0,0,0,.22);
  border: 1px solid rgba(207,181,59,.22);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.03);
}

/* ---- 5d · INTERACTION --------------------------------------------------
   Press is a real press: the tile sinks toward the surface and its shadow
   collapses toward the light vector. Hover is gated behind a real pointer so
   iOS never gets a sticky hover state after a tap.                          */
.cab{ cursor: pointer; }

@media (hover: hover) and (pointer: fine){
  .cab:hover{
    transform: translateY(-2px);
    border-color: rgba(207,181,59,.44);
    box-shadow: var(--e-3), var(--rim), var(--shade);
  }
  .cab--hero:hover{ border-color: rgba(207,181,59,.52); }
  .cab:hover .art::after{ opacity: .88; }
}

.cab:active{
  transform: translateY(1px) scale(.988);
  box-shadow: var(--e-1), var(--rim), var(--shade);
  transition-duration: .07s;
}

/* keyboard focus — .cab is a div in the current markup, so give the
   integrator a ring that works the moment tabindex is added (see notes) */
.cab:focus-visible{
  outline: 2px solid var(--violet);
  outline-offset: 2px;
}

/* the existing "reserved" rejection wiggle — kept compatible, retuned to a
   shorter, less cartoonish throw */
.cab.shake{ animation: cabShake .34s cubic-bezier(.36,.07,.19,.97); }
@keyframes cabShake{
  0%,100%{ transform: translateX(0); }
  22%{ transform: translateX(-4px); }
  58%{ transform: translateX(4px); }
  82%{ transform: translateX(-2px); }
}


/* ==========================================================================
   6 · .glass — THE ONE BACKDROP-FILTER RECIPE
   --------------------------------------------------------------------------
   ⚠ HARD BUDGET: NEVER MORE THAN 3 .glass ELEMENTS VISIBLE AT ONCE.
   Each one is a separate compositing layer with a live blur; on an iPhone the
   4th is where the floor drops off 60fps. If you need a 4th surface, use a
   plain --panel tile — nobody will notice, and the ones that ARE glass will
   read as more special.
   Do not put .glass on anything inside a scrolling list (the blur re-samples
   every frame). It is for fixed chrome: the topbar, the mini bar, a modal.
   ========================================================================== */
.glass{
  position: relative;
  border-radius: var(--r-2);
  background: rgba(36,16,51,.58);
  -webkit-backdrop-filter: blur(16px) saturate(1.45);
  backdrop-filter: blur(16px) saturate(1.45);
  border: 1px solid rgba(207,181,59,.22);
  box-shadow: var(--e-2), var(--shade);
}
/* bright top edge — the lamp catching the lip of the pane */
.glass::before{
  content: "";
  position: absolute;
  left: var(--sp-4);
  right: var(--sp-4);
  top: 0;
  height: 1px;
  border-radius: 1px;
  background: linear-gradient(90deg,
    rgba(255,243,196,0) 0%,
    rgba(255,243,196,.42) 26%,
    rgba(255,243,196,.30) 62%,
    rgba(255,243,196,0) 100%);
  pointer-events: none;
}
/* Fallback: solid velvet panel wherever backdrop-filter is unavailable.
   `not (...)` needs the -webkit- form tested too or old iOS takes the
   fallback branch it does not need. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){
  .glass{
    background: linear-gradient(168deg, var(--panel2), var(--panel) 70%, var(--ink-2));
  }
}


/* ==========================================================================
   7 · RESPONSIVE
   Mobile-first: everything above is the phone layout.
     phone  (<=420px):  hero 2×2  |  wide 2×1  |  plates 2-up
     >=421px         :  plates go 1-up-per-column (4 across)
     >=560px         :  wide tiles become horizontal strips
     >=760px         :  the whole floor gets more air
   ========================================================================== */

/* ---- 7a · very narrow phones (iPhone SE / 320px) ----------------------- */
@media (max-width: 359px){
  :root{ --bento-gap: 8px; --cab-row: 112px; }
  .cab .cab-name{ font-size: 13px; }
  .machines .cab--hero .cab-name{ font-size: 17px; }
  .machines .cab--plate .cab-name{ font-size: 10px; }
}

/* ---- 7b · >=421px: the plates break into their true 1×1 form ------------ */
@media (min-width: 421px){
  :root{ --cab-row: 132px; --bento-gap: 12px; }

  .cab--plate{
    grid-column: span 1;
    --frame-gap: 3px;
  }
  /* at 4-up a plate is ~90px wide: the tag no longer earns its space, and
     the name gets the room instead */
  .machines .cab--plate .cab-tag{ display: none; }
  .machines .cab--plate .cab-name{ font-size: 10px; -webkit-line-clamp: 3; line-clamp: 3; }
  .cab--plate .art{ height: 52px; }
  .cab--plate .art .glyph{ font-size: 22px; }
  .machines .cab--plate.live::before{ font-size: 7px; letter-spacing: 1.2px; padding: 3px 5px 2px; }
}

/* ---- 7c · >=760px: tablet / desktop air -------------------------------- */
@media (min-width: 760px){
  :root{ --bento-gap: 14px; --cab-row: 152px; }
  .machines .cab--hero .cab-name{ font-size: 22px; }
  .cab--hero .art .glyph{ font-size: 68px; }
  /* :not() chain on purpose — a bare `.cab .art` here would out-source-order
     the hero's auto height and the wide strip's 100% height below */
  .cab:not(.cab--hero):not(.cab--wide):not(.cab--plate) .art{ height: 96px; }
  .cab--wide .art{ height: 84px; }
  .cab--plate .art{ height: 62px; }
  .machines .cab--plate .cab-name{ font-size: 11px; }
  .machines .cab--plate .cab-tag{ display: block; }
}

/* ---- 7d · >=860px: wide tiles become horizontal strips ------------------
   Art block on the left, name over tag in the middle, CTA parked right.
   Uses the EXISTING child order (.art, .cab-name, .cab-tag, .cab-cta) with
   explicit grid placement — no markup change required.
   860px is not arbitrary: below it the middle column is too narrow and the
   machine names ellipsis away to "RAEKO…". Do not lower it.
   Must stay LAST of the breakpoints — it overrides the >=760px art height. */
@media (min-width: 860px){
  .cab--wide{
    display: grid;
    grid-template-columns: 96px minmax(0, 1fr) auto;
    grid-template-rows: 1fr 1fr;
    align-items: center;
    padding: 0;
    text-align: left;
  }
  .cab--wide .art{
    grid-area: 1 / 1 / 3 / 2;
    margin: 0;
    height: 100%;
    border-bottom: 0;
    border-right: 1px solid rgba(207,181,59,.14);
  }
  .machines .cab--wide .cab-name{
    grid-area: 1 / 2 / 2 / 3;
    align-self: end;
    padding: 0 0 0 var(--sp-4);
    font-size: 15px;
    -webkit-line-clamp: 1;
    line-clamp: 1;
  }
  .machines .cab--wide .cab-tag{
    grid-area: 2 / 2 / 3 / 3;
    align-self: start;
    margin: var(--sp-1) 0 0;
    padding: 0 0 0 var(--sp-4);
  }
  .machines .cab--wide .cab-cta{
    grid-area: 1 / 3 / 3 / 4;
    align-self: center;
    margin: 0 var(--sp-5) 0 var(--sp-4);
    padding: var(--sp-3) var(--sp-5);
  }
  .cab--wide .art .glyph{ font-size: 34px; }
}


/* ==========================================================================
   8 · REDUCED MOTION
   Nothing on this screen conveys information through movement, so we can
   remove all of it and lose nothing. States still change — they change by
   colour and elevation instead of by travel.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  .cab{ transition: border-color .01ms linear; }
  .cab:hover,
  .cab:active{ transform: none; }
  .cab:active{ border-color: rgba(207,181,59,.55); }
  .cab.shake{ animation: none; border-color: rgba(176,58,74,.75); }
  .cab.live::before{ animation: none; }
}


/* ==========================================================================
   9 · FORCED COLORS / HIGH CONTRAST
   Gradients and box-shadows vanish in forced-colors mode; keep the tile
   boundaries and the CTA readable so the floor is still navigable.
   ========================================================================== */
@media (forced-colors: active){
  .cab{ border: 1px solid CanvasText; }
  .cab::after{ display: none; }
  .cab .cab-cta{ border: 1px solid CanvasText; forced-color-adjust: none; }
}


/* ============ ICONS =========== */

.ic{
  width:1em; height:1em;
  display:inline-block;
  vertical-align:-.145em;          /* optical baseline match for --body + --display */
  flex:none;                        /* never squash inside flex rows */
  stroke-width:1.5;                 /* the ONE tunable: inherited into the <use> tree */
  pointer-events:none;              /* clicks always land on the parent button */
  -webkit-user-select:none; user-select:none;
}
/* fixed sizes (px, not em) for chrome that must not drift with font-size */
.ic-16{width:16px;height:16px}
.ic-20{width:20px;height:20px}
.ic-24{width:24px;height:24px}
.ic-32{width:32px;height:32px;stroke-width:1.35}   /* optical thinning as it grows */
.ic-48{width:48px;height:48px;stroke-width:1.2}
.ic-64{width:64px;height:64px;stroke-width:1.1}

/* --- colour roles (60-30-10) --- */
.ic-brass  {color:var(--oldgold)}
.ic-violet {color:var(--violet)}
.ic-mute-c {color:var(--dim)}
.ic-cream  {color:var(--cream)}
.ic-risk   {color:var(--risk)}
.ic-green  {color:var(--green)}

/* Antique two-tier bevel — the icon equivalent of .engraved. Cheap, no filter. */
.ic-engraved{
  color:var(--oldgold);
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.62));
}
/* FLEX gold. WINS ONLY. Never more than 2-3 of these on screen at once (iOS GPU). */
.ic-flare{
  color:var(--gold);
  filter:drop-shadow(0 0 5px rgba(245,197,66,.5));
}
@media (prefers-reduced-motion:reduce){
  .ic-flare{filter:none}
}

/* Card-suit convention (blackjack / video poker pip runs) */
.ic-suit-red{color:var(--red)}
.ic-suit-blk{color:var(--cream)}

/* Cabinet glyph: drop the svg inside the EXISTING .glyph span and it inherits
   whatever font-size .glyph already has — zero CSS surgery on .art/.glyph. */
.cab .art .glyph .ic{width:1em;height:1em;vertical-align:middle}


/* ============ COMP CHIP ======= */
========================================================================== */

/* --- denomination faces (add these 5 to :root, or leave them here) --------- */
:root{
  --chip-slate:#3a5266;
  --chip-green:#1e6b45;
  --chip-oxblood:#7a1e2c;   /* --risk deepened */
  --chip-obsidian:#191320;
  --chip-goldface:#7a5410;  /* DEEP antique brass — never --gold. Deliberately darker
                               than the rim so the rim/inlay boundary still reads. */
}

/* --- the chip ------------------------------------------------------------- */
.rk-chip{
  --chip-size:64px;
  --chip-face:var(--chip-oxblood);
  --chip-ink:var(--oldgold,#cfb53b);
  --chip-denom:var(--chip-ink);
  --guil-vis:visible;      /* guilloche ring   (visibility is inherited -> reaches <use> shadow) */
  --micro-vis:visible;     /* "RAEKON" micro-text */
  width:var(--chip-size);height:var(--chip-size);
  display:block;flex:0 0 auto;overflow:visible;
  /* 3D lift: contact shadow + soft drop. Inset top highlight lives in the SVG. */
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.65)) drop-shadow(0 4px 6px rgba(0,0,0,.5));
  -webkit-tap-highlight-color:transparent;
}
.rk-chip .rk-denom{
  font-family:var(--display,system-ui);font-weight:900;font-size:17px;letter-spacing:.6px;
  text-anchor:middle;fill:var(--chip-denom);
  paint-order:stroke fill;stroke:rgba(0,0,0,.55);stroke-width:2.2px;stroke-linejoin:round;
}

/* --- sizes ---------------------------------------------------------------- */
.rk-chip.sm{                       /* 24px inline — wallet / ticker / inline runs */
  --chip-size:24px;--guil-vis:hidden;--micro-vis:hidden;--chip-denom:transparent;
  display:inline-block;vertical-align:-5px;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.6));
}
.rk-chip.md{--chip-size:50px;--micro-vis:hidden;}   /* bet buttons: micro-text is mush below ~56px */
.rk-chip.lg{--chip-size:96px;}

/* --- denominations (matches the existing data-v attributes) --------------- */
.rk-chip[data-v="10"]  {--chip-face:var(--chip-slate);}
.rk-chip[data-v="25"]  {--chip-face:var(--chip-green);}
.rk-chip[data-v="50"]  {--chip-face:var(--chip-oxblood);}
.rk-chip[data-v="100"] {--chip-face:var(--chip-obsidian);}
.rk-chip[data-v="250"] {--chip-face:var(--chip-goldface);--chip-ink:var(--gold2,#fff3c4);}
/* semantic aliases, if you'd rather not use data-v */
.rk-chip.face-slate   {--chip-face:var(--chip-slate);}
.rk-chip.face-green   {--chip-face:var(--chip-green);}
.rk-chip.face-oxblood {--chip-face:var(--chip-oxblood);}
.rk-chip.face-obsidian{--chip-face:var(--chip-obsidian);}
.rk-chip.face-gold    {--chip-face:var(--chip-goldface);--chip-ink:var(--gold2,#fff3c4);}

/* --- chip-as-button (replaces the old CSS-circle .bj-chip) ---------------- */
.rk-chip-btn{
  appearance:none;-webkit-appearance:none;background:none;border:0;padding:0;margin:0;
  line-height:0;border-radius:50%;color:inherit;cursor:pointer;
  transition:transform .13s cubic-bezier(.2,.8,.3,1),box-shadow .16s ease;
  -webkit-tap-highlight-color:transparent;
}
.rk-chip-btn:active{transform:translateY(3px) scale(.955);}
.rk-chip-btn.is-sel{box-shadow:0 0 0 2px var(--violet,#8b5cf6),0 0 16px rgba(139,92,246,.42);}
.rk-chip-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--violet,#8b5cf6);}
.rk-chip-btn[disabled]{cursor:default;filter:grayscale(.75) brightness(.55) contrast(.9);}
.rk-chip-btn[disabled]:active{transform:none;}

@media (prefers-reduced-motion:reduce){
  .rk-chip-btn{transition:none;}
  .rk-chip-btn:active{transform:none;filter:brightness(1.25);}
}
/* ==========================================================================

/* ============ CREST/DIVIDER === */
(paste anywhere after :root — it only defines new .rk-* classes)
   ══════════════════════════════════════════════════════════════════════════ */

/* ---------- RAEKON brand objects: cast-metal layer palette ----------
   Three flat stacked layers, no SVG filters (crisp on iOS, zero repaint cost).
   Paint order per object: SHADOW (pushed down) → SPECULAR (pushed up) → FACE. */
.rk-l-sd{fill:var(--rk-shade,#7a5c14);stroke:var(--rk-shade,#7a5c14);}
.rk-l-hi{fill:var(--rk-spec ,#fff3c4);stroke:var(--rk-spec ,#fff3c4);}
.rk-l-fc{fill:var(--rk-face ,#cfb53b);stroke:var(--rk-face ,#cfb53b);}

/* ---------- (1) THE R-SPADE CREST ---------- */
.rk-crest{
  --rk-face:var(--oldgold,#cfb53b);      /* antique brass body      */
  --rk-spec:var(--gold2,#fff3c4);        /* specular top edge       */
  --rk-shade:var(--oldgold-lo,#7a5c14);  /* cast shadow underneath  */
  display:block;width:var(--rk-crest-size,120px);height:auto;
  margin-inline:auto;flex:none;
}
/* the hairline frame reads better a half-step cooler than the cast mark */
.rk-crest .rk-l-fc.rk-frame{fill:var(--rk-face);stroke:var(--rk-face);}
/* optional: FLEX-gold crest, for a win / vault-open moment only (never a resting state) */
.rk-crest--flare{--rk-face:var(--gold,#f5c542);--rk-spec:#fffefa;--rk-shade:var(--gold3,#b8862a);}
/* optional: knocked-back crest for dense surfaces (card back, HQ header) */
.rk-crest--quiet{--rk-face:#9d8a3a;--rk-spec:#d9cf9e;--rk-shade:#4a3708;opacity:.9;}

/* ---------- (2) THE SPIDER-CHAIN DIVIDER ---------- */
.rk-divider{
  --rk-face:var(--oldgold,#cfb53b);
  --rk-shade:var(--oldgold-lo,#7a5c14);
  display:flex;align-items:center;justify-content:center;
  width:100%;max-width:var(--rk-divider-max,520px);
  height:24px;margin:16px auto 12px;
  pointer-events:none;user-select:none;-webkit-user-select:none;
}
.rk-divider__chain{
  flex:1 1 0;min-width:0;height:24px;display:block;
  /* fade to transparent at the OUTER ends — CSS mask, so the fade always spans
     the real rendered width no matter how the viewBox is stretched */
  -webkit-mask-image:linear-gradient(to left,#000 30%,rgba(0,0,0,.5) 66%,transparent 100%);
          mask-image:linear-gradient(to left,#000 30%,rgba(0,0,0,.5) 66%,transparent 100%);
}
.rk-divider__chain--r{transform:scaleX(-1);}      /* mirrors art AND mask together */
.rk-divider__spider{flex:0 0 34px;width:34px;height:24px;display:block;}
/* variants */
.rk-divider--tight{margin:10px auto 8px;}
.rk-divider--flush{max-width:none;}
.rk-divider--quiet{--rk-face:#a08e42;opacity:.75;}

/* Section header + rule, when the divider stands in for a .sec-h underline */
.rk-secrule{margin:18px 0 10px;}
.rk-secrule .sec-h,.rk-secrule .d-sech{margin-bottom:2px;}

/* No animation is defined on either object — restraint is the luxury, and it
   means nothing here needs a prefers-reduced-motion escape hatch. If you ever
   add a gleam, gate it with the query below. */
@media (prefers-reduced-motion:reduce){
  .rk-crest,.rk-divider,.rk-crest *,.rk-divider *{animation:none!important;transition:none!important;}
}
/* ══════════════════════════════════════════════════════════════════════════

/* ============ VAULT ENTER ===== */

/* ================= ENTER — THE VAULT =================
   Contract: the base styles ARE the final frame. Nothing animates by default.
   Intro motion lives only inside @media (prefers-reduced-motion:no-preference)
   AND only while .rk-animate is present, which JS adds pre-paint on a first
   visit. Returning visitors, reduced-motion users and a JS failure all land
   on the finished screen with zero motion. */

#scr-enter{align-items:center;justify-content:center;text-align:center;}

/* ---- 1. matte velvet ground ---------------------------------------------- */
.rk-ground{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(120% 78% at 50% 6%,   rgba(139,92,246,.15),  transparent 58%),
    radial-gradient(86% 56%  at 50% 40%,  rgba(58,28,86,.80),    transparent 72%),
    radial-gradient(140% 96% at 50% 112%, rgba(207,181,59,.075), transparent 62%),
    radial-gradient(104% 78% at 50% 48%,  rgba(26,13,36,0), rgba(6,3,9,.80) 96%),
    linear-gradient(180deg,#1b0e26 0%,#120814 60%,#0c0511 100%);
}
/* velvet nap: one static diagonal sheen. No blend modes, no movement, no lines. */
.rk-ground::before{
  content:"";position:absolute;inset:0;
  background:linear-gradient(104deg,
    rgba(255,255,255,0)    20%,
    rgba(243,236,246,.038) 44%,
    rgba(255,255,255,0)    58%,
    rgba(0,0,0,.11)        86%);
}
/* grain — scoped to this container only */
.rk-ground::after{
  content:"";position:absolute;inset:0;opacity:.055;
  background-image:radial-gradient(rgba(255,255,255,.55) .6px, transparent .7px);
  background-size:3px 3px;
}

/* ---- layout --------------------------------------------------------------- */
#scr-enter .inner.rk-enter{
  position:relative;z-index:2;width:100%;max-width:520px;
  padding:calc(26px + env(safe-area-inset-top)) 24px calc(26px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;align-items:center;
  transform-origin:50% 46%;
}
.rk-eyebrow{
  font-family:var(--display);letter-spacing:5px;font-size:11.5px;
  text-transform:uppercase;color:var(--dim);opacity:.86;
  margin-bottom:clamp(14px,3.4vh,22px);
}

/* ---- 2. crest ------------------------------------------------------------- */
.rk-defs{position:absolute;width:0;height:0;overflow:hidden;}
.rk-crest{
  display:block;width:clamp(62px,17vw,82px);height:auto;
  filter:drop-shadow(0 1px 0 rgba(255,243,196,.22)) drop-shadow(0 3px 7px rgba(0,0,0,.62));
}

/* ---- 3. wordmark + one-shot foil glint ------------------------------------ */
.rk-wordmark{
  display:inline-grid;                       /* stacks base + glint in one cell */
  margin-top:clamp(12px,2.6vh,18px);
  font-family:var(--display);font-weight:900;line-height:.9;
  font-size:clamp(52px,15.5vw,88px);letter-spacing:5px;white-space:nowrap;
}
.rk-wm-base,.rk-wm-glint{grid-area:1 / 1;}
.rk-wm-base{z-index:1;}
.rk-wm-glint{
  z-index:2;pointer-events:none;
  /* narrow hard-cored streak — a wide soft band reads as a wash, not as foil */
  background-image:linear-gradient(102deg,
    rgba(255,255,255,0)   42%,
    rgba(255,243,196,.55) 46.5%,
    rgba(255,255,255,1)   50%,
    rgba(255,243,196,.55) 53.5%,
    rgba(255,255,255,0)   58%);
  background-repeat:no-repeat;background-size:280% 100%;
  background-position:-90% 0;          /* FINAL frame: swept past, nothing visible */
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
  opacity:0;
}
.rk-house{
  font-family:var(--display);font-weight:700;font-size:clamp(13px,3.4vw,16px);
  letter-spacing:13px;text-indent:13px;text-transform:uppercase;
  color:var(--cream);opacity:.78;margin-top:10px;
}

/* ---- 4. wax seal ---------------------------------------------------------- */
.rk-seal{
  position:relative;display:block;padding:0;border:0;background:none;
  width:clamp(148px,44vw,186px);aspect-ratio:1 / 1;
  margin:clamp(26px,5.6vh,44px) 0 clamp(20px,4vh,30px);
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
}
.rk-seal:focus{outline:none;}
.rk-seal:focus-visible{outline:2px solid var(--oldgold);outline-offset:8px;border-radius:50%;}
.rk-seal-glow{
  position:absolute;left:50%;top:50%;width:190%;height:190%;
  transform:translate(-50%,-50%);pointer-events:none;
  background:radial-gradient(circle at 50% 50%,
    rgba(176,58,74,.26) 0%, rgba(139,92,246,.12) 40%, rgba(0,0,0,0) 68%);
}
.rk-seal-body{position:absolute;inset:0;display:block;transform-origin:50% 50%;}
/* cast shadow lives on the UNCLIPPED parent — a drop-shadow on the halves would
   trace the jagged crack line and expose the seam at rest */
.rk-seal-body::before{
  content:"";position:absolute;left:8%;top:9%;right:8%;bottom:7%;
  border-radius:50%;box-shadow:0 10px 24px 2px rgba(0,0,0,.58);
}
.rk-seal-piece{position:absolute;inset:0;display:block;transform-origin:50% 50%;}
/* matched crack vertices, 2% overlap so no hairline shows at rest */
.rk-p-l{clip-path:polygon(0% 0%, 52% 0%, 47% 18%, 55% 33%, 46% 49%, 54% 66%, 45% 82%, 51% 100%, 0% 100%);}
.rk-p-r{clip-path:polygon(50% 0%, 100% 0%, 100% 100%, 49% 100%, 43% 82%, 52% 66%, 44% 49%, 53% 33%, 45% 18%);}
.rk-seal-wax{position:absolute;inset:0;width:100%;height:100%;display:block;}
/* the stamped depression: dark at the top lip, a thin warm bounce at the bottom.
   No hard ring — a hard ring is what makes a wax seal read as a poker chip. */
.rk-seal-face{
  position:absolute;left:13%;top:13%;right:13%;bottom:13%;border-radius:50%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  box-shadow:
    inset 0 7px 14px rgba(20,3,8,.62),
    inset 0 -5px 12px rgba(214,124,132,.10),
    inset 0 0 22px rgba(20,3,8,.30);
}
.rk-seal .rk-seal-mark{
  width:46%;height:auto;margin-bottom:1px;color:#571522;
  filter:drop-shadow(0 1px 0 rgba(226,150,150,.22)) drop-shadow(0 -1px 1px rgba(0,0,0,.6));
}
/* pressed mark: flatten the crest's brass gradients down to one wax tone */
.rk-seal .rk-seal-mark [fill]{fill:currentColor;}
.rk-seal .rk-seal-mark [stroke]{stroke:currentColor;}
.rk-seal .rk-seal-mark [fill="none"]{fill:none;}
.rk-seal-word{
  font-family:var(--display);font-weight:900;font-size:clamp(14px,4vw,17px);
  letter-spacing:5px;text-indent:5px;color:#dcaeb2;
  text-shadow:0 1px 0 rgba(232,164,164,.18),0 -1px 1px rgba(0,0,0,.68);
}

/* ---- 5. credit + compliance ----------------------------------------------- */
.rk-credit{
  font-family:var(--display);font-size:clamp(10px,2.9vw,11.5px);letter-spacing:2.2px;
  text-transform:uppercase;color:var(--oldgold);opacity:.72;line-height:1.6;
}
.fineprint.rk-fine{
  margin-top:10px;font-size:10px;letter-spacing:1.5px;line-height:1.8;
  color:var(--dim);opacity:.66;max-width:36ch;
}
.rk-credit b,.rk-fine b{font-weight:inherit;white-space:nowrap;}

/* ================= VAULT-OPEN SEQUENCE — motion-safe only =================
   Total intro 1160ms. Everything is opacity/transform except the single
   one-shot glint (background-position on one text node). */
@media (prefers-reduced-motion:no-preference){

  #scr-enter.rk-animate .rk-ground {animation:rkGround 300ms ease-out both;}
  .rk-enter.rk-animate .rk-eyebrow {animation:rkRise   340ms ease-out 200ms both;}
  .rk-enter.rk-animate .rk-crest   {animation:rkEmboss 460ms cubic-bezier(.22,.9,.28,1) 110ms both;}
  .rk-enter.rk-animate .rk-wordmark{animation:rkRise   380ms cubic-bezier(.2,.8,.3,1) 280ms both;}
  .rk-enter.rk-animate .rk-house   {animation:rkRise   340ms ease-out 380ms both;}
  .rk-enter.rk-animate .rk-wm-glint{animation:rkGlint  640ms cubic-bezier(.42,0,.24,1) 500ms 1 both;}
  .rk-enter.rk-animate .rk-seal    {animation:rkSealIn 420ms cubic-bezier(.24,1.16,.36,1) 700ms both;}
  .rk-enter.rk-animate .rk-credit  {animation:rkRise   320ms ease-out 780ms both;}
  .rk-enter.rk-animate .rk-fine    {animation:rkRise   320ms ease-out 840ms both;}

  /* once the vault is open: one calm 4.8s breath on the oxblood glow.
     Never on the gold, never fast, nothing that reads as urgency. */
  .rk-enter.rk-idle .rk-seal-glow{animation:rkBreath 4.8s ease-in-out infinite;}
  .rk-seal:active .rk-seal-body{transform:scale(.965);transition:transform 90ms ease-out;}

  /* ---- seal crack + scale-through (tap) ---- */
  .rk-enter.rk-cracking .rk-seal-piece{will-change:transform,opacity;}
  .rk-enter.rk-cracking .rk-seal-body {animation:rkPress  200ms cubic-bezier(.3,.9,.3,1) both;}
  .rk-enter.rk-cracking .rk-p-l       {animation:rkCrackL 440ms cubic-bezier(.24,.72,.3,1) 130ms both;}
  .rk-enter.rk-cracking .rk-p-r       {animation:rkCrackR 440ms cubic-bezier(.24,.72,.3,1) 130ms both;}
  .rk-enter.rk-cracking .rk-seal-glow {animation:rkFlash  420ms ease-out 100ms both;}
  .rk-enter.rk-through                {animation:rkThrough 300ms cubic-bezier(.4,0,.9,.5) both;}
}

@keyframes rkGround{from{opacity:0}to{opacity:1}}
@keyframes rkRise{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
@keyframes rkEmboss{
  0%  {opacity:0;transform:scale(.94)}
  60% {opacity:1}
  100%{opacity:1;transform:scale(1)}
}
@keyframes rkGlint{
  0%  {opacity:0;background-position:190% 0}
  14% {opacity:1}
  86% {opacity:1}
  100%{opacity:0;background-position:-90% 0}
}
@keyframes rkSealIn{from{opacity:0;transform:scale(.78)}to{opacity:1;transform:scale(1)}}
@keyframes rkBreath{
  0%,100%{opacity:.72;transform:translate(-50%,-50%) scale(1)}
  50%    {opacity:1;  transform:translate(-50%,-50%) scale(1.045)}
}
@keyframes rkPress{
  0%  {transform:scale(1)}
  45% {transform:scale(.93)}
  100%{transform:scale(1.05)}
}
/* the pieces hold full opacity through the split and only fade on the way out,
   so the crack still reads at 440ms */
@keyframes rkCrackL{
  0%  {transform:translate3d(0,0,0) rotate(0deg);opacity:1}
  58% {opacity:1}
  100%{transform:translate3d(-21%,8%,0) rotate(-8deg);opacity:0}
}
@keyframes rkCrackR{
  0%  {transform:translate3d(0,0,0) rotate(0deg);opacity:1}
  58% {opacity:1}
  100%{transform:translate3d(21%,8%,0) rotate(8deg);opacity:0}
}
@keyframes rkFlash{
  0%  {opacity:.7;transform:translate(-50%,-50%) scale(1)}
  30% {opacity:1; transform:translate(-50%,-50%) scale(1.16)}
  100%{opacity:0; transform:translate(-50%,-50%) scale(1.5)}
}
@keyframes rkThrough{
  from{opacity:1;transform:scale(1)}
  to  {opacity:0;transform:scale(1.26)}
}

/* reduced motion: no intro, no crack, no scale-through — the seal just dims
   and the screen cross-fades out. */
@media (prefers-reduced-motion:reduce){
  .rk-enter{transition:opacity .18s linear;}
  .rk-enter.rk-cracking .rk-seal{opacity:.55;}
  .rk-enter.rk-through{opacity:0;}
}

/* View-transition into the floor. Only this screen opts in today; harmless
   no-op where the API is missing. */
@media (prefers-reduced-motion:no-preference){
  ::view-transition-old(root){animation-duration:.22s;}
  ::view-transition-new(root){animation-duration:.34s;}
}

/* short phones: shed vertical air before anything can clip */
@media (max-height:640px){
  .rk-eyebrow{margin-bottom:10px;}
  .rk-crest{width:clamp(52px,14vw,66px);}
  .rk-wordmark{font-size:clamp(44px,13vw,64px);}
  .rk-seal{width:clamp(126px,36vw,150px);margin:clamp(16px,3.4vh,26px) 0 16px;}
}
