/* ===========================================================================
   VAULT  —  the Dead Man's Deal board, and the revolver
   ---------------------------------------------------------------------------
   THIS IS THE SCRIPT'S OWN BOARD. Same markup, same card styles, same deal,
   claim, call and revolver a player sees — running on a loop.

   The game measures everything in vh because it fills a screen. The stage
   sets --vh to a fraction of ITS OWN height, so every number lifted out of
   the game's stylesheet keeps its proportion at any size. Change a card in
   the script and the same values port straight back across.
   =========================================================================== */

:root {
  --card-face: #f4efe3;
  --card-ink:  #191512;
  --card-back: #2a1c18;
  --felt:      #0f1a14;   /* the table's own green, and the only place it is
                             used: the board is a window into the game, not a
                             section of the site. */
  --dmd-logo:  url('/assets/dmd-logo.png');
}

/* ============================================================= THE FRAME ==
   The board is framed rather than floating. A bezel and a strip along the top
   are what make it read as a capture of the running game instead of a few
   divs on a dark rectangle — which is what it is, so the frame is telling the
   truth rather than dressing it up.
   ========================================================================= */

.frame {
  position: relative;
  border-radius: var(--r4);
  border: 1px solid var(--line);
  background: var(--bg-sink);
  box-shadow: var(--sh-3), 0 0 0 1px rgba(224, 168, 60, .1);
  overflow: hidden;
}
.frame-bar {
  display: flex; align-items: center; gap: var(--s3);
  padding: 14px var(--s4);
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, .015);
  font-size: .8rem; color: var(--tx-3);
}
.frame-note { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frame-meta { margin-left: auto; font-size: .74rem; color: var(--tx-4); flex: none; }
@media (max-width: 700px) { .frame-meta { display: none; } }

.live {
  display: flex; align-items: center; gap: 8px; flex: none;
  font-weight: 700; text-transform: uppercase; letter-spacing: .1em;
  font-size: .72rem; color: var(--gold-lit);
}
.live::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--red-lit); animation: pip 2s infinite;
}
@keyframes pip {
  0%   { box-shadow: 0 0 0 0 rgba(239, 90, 82, .55); }
  70%  { box-shadow: 0 0 0 9px rgba(239, 90, 82, 0); }
  100% { box-shadow: 0 0 0 0 rgba(239, 90, 82, 0); }
}

/* THE ROOM BEHIND THE BOARD.
   A first-person shot from a seat at the table: two players across from you,
   one lamp, green baize. The board's own panels are drawn on top of it, so
   the photograph is pushed a long way back - darkened, slightly desaturated,
   and vignetted - because the moment it competes with a card face it has
   stopped being a background and started being noise.

   The felt colour stays underneath it as the ground. On a narrow screen the
   stage is 320px tall and `cover` crops hard into the middle of the frame,
   which is the half with the table in it, so the crop loses the ceiling
   rather than the game. */
.stage {
  --vh: 6.6px;
  position: relative; height: 660px; overflow: hidden;
  background: var(--felt);
}
.stage::before {
  content: ''; position: absolute; inset: 0; z-index: 0;
  background: url('/assets/board-room.webp') center 42% / cover no-repeat;
  filter: brightness(.62) saturate(.85) contrast(1.05);
}
/* The lamp's pool of light, re-drawn over the photo so the middle of the
   table stays the brightest thing and the edges fall away into the frame. */
.stage::after {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 44%, rgba(224, 168, 60, .13), transparent 52%),
    radial-gradient(ellipse at 50% 52%, transparent 30%, rgba(5, 8, 6, .72) 88%);
}
@media (max-width: 1040px) { .stage { --vh: 5.4px; height: 540px; } }
@media (max-width: 720px)  { .stage { --vh: 4.1px; height: 410px; } }
@media (max-width: 470px)  { .stage { --vh: 3.2px; height: 320px; } }

/* ---------------------------------------------------------- opponents -- */

.rail {
  position: absolute; left: calc(var(--vh) * 2.4); top: calc(var(--vh) * 2.4);
  display: flex; flex-direction: column; gap: calc(var(--vh) * 1.1); z-index: 5;
}
.opp {
  width: calc(var(--vh) * 30);
  padding: calc(var(--vh) * 1.3) calc(var(--vh) * 1.6);
  border-radius: calc(var(--vh) * 1.2);
  border: 1px solid var(--line);
  border-top: 3px solid transparent;
  background: rgba(9, 13, 11, .88);
  transition: border-color .3s var(--ease), background .3s var(--ease),
              opacity .4s var(--ease), filter .4s var(--ease);
}
.opp.turn   { border-top-color: var(--gold); background: rgba(24, 32, 27, .96); }
.opp.target { border-top-color: var(--red); }
.opp.dead   { opacity: .36; filter: grayscale(1); }
.opp-top { display: flex; align-items: baseline; gap: calc(var(--vh) * .8); }
.opp-name { font-size: calc(var(--vh) * 1.55); font-weight: 700; color: var(--tx); }
.opp-state {
  margin-left: auto; font-size: calc(var(--vh) * 1.05); font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--tx-4);
}
.opp.turn .opp-state { color: var(--gold-lit); }
.opp.dead .opp-state { color: var(--red); }
.opp-cards { display: flex; margin-top: calc(var(--vh) * .9); padding-left: calc(var(--vh) * .6); }

/* THE CARD BACK, matched to the script: the mark centred at 78% over a 45deg
   weave on the game's own card-back colour. It was a flat brown rectangle
   once, and that single detail is what made the board read as a diagram of
   the game rather than the game. */
.back {
  background:
    var(--dmd-logo) center/78% no-repeat,
    repeating-linear-gradient(45deg, rgba(224, 168, 60, .16) 0 2px, transparent 2px 5px),
    var(--card-back);
  box-shadow: inset 0 0 0 1px rgba(224, 168, 60, .3);
}
.opp-cards .mini {
  width: calc(var(--vh) * 2.5); height: calc(var(--vh) * 3.6);
  margin-left: calc(var(--vh) * -.6);
  border-radius: calc(var(--vh) * .4);
  animation: miniIn .4s var(--ease) backwards;
}
@keyframes miniIn { from { opacity: 0; transform: translateY(calc(var(--vh) * -.7)) rotate(-6deg); } }

/* --------------------------------------------------------------- pot ---- */

.house {
  position: absolute; right: calc(var(--vh) * 2.4); top: calc(var(--vh) * 2.4); z-index: 6;
  min-width: calc(var(--vh) * 28);
  padding: calc(var(--vh) * 1.7) calc(var(--vh) * 2);
  border-radius: calc(var(--vh) * 1.2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--gold);
  background: rgba(9, 13, 11, .92);
  text-align: right;
}
.pot-k { font-size: calc(var(--vh) * 1.05); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--tx-4); }
.pot-v {
  font-size: calc(var(--vh) * 3.6); font-weight: 800; letter-spacing: -.03em;
  line-height: 1.1; color: var(--gold-lit);
  font-variant-numeric: tabular-nums;
  transition: transform .35s var(--snap);
}
.pot-v.pop { transform: scale(1.16); }
.pot-s { margin-top: calc(var(--vh) * .6); font-size: calc(var(--vh) * 1.05); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--tx-4); }

/* ------------------------------------------------------------- claim ---- */

.claim {
  position: absolute; left: 50%; top: calc(var(--vh) * 4); transform: translateX(-50%);
  display: flex; align-items: center; gap: calc(var(--vh) * 1.4);
  padding: calc(var(--vh) * 1.3) calc(var(--vh) * 2.6);
  border-radius: calc(var(--vh) * 1);
  background: var(--card-face); color: var(--card-ink);
  box-shadow: 0 calc(var(--vh) * .8) calc(var(--vh) * 3) rgba(0, 0, 0, .7);
  opacity: 0; transition: opacity .45s var(--ease); z-index: 4;
}
.claim.on { opacity: 1; }
.claim svg { width: calc(var(--vh) * 2.7); height: calc(var(--vh) * 2.7); fill: var(--card-ink); }
.claim-k { font-size: calc(var(--vh) * 1); font-weight: 700; letter-spacing: .18em; text-transform: uppercase; opacity: .55; }
.claim-v { font-size: calc(var(--vh) * 2.3); font-weight: 800; letter-spacing: -.02em; line-height: 1.1; }

/* -------------------------------------------------------------- pile ---- */

.pile {
  position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%);
  width: calc(var(--vh) * 24); height: calc(var(--vh) * 17); z-index: 3;
}
.pile .mini {
  position: absolute; left: 50%; top: 50%;
  width: calc(var(--vh) * 7.4); height: calc(var(--vh) * 10.4);
  margin: calc(var(--vh) * -5.2) 0 0 calc(var(--vh) * -3.7);
  border-radius: calc(var(--vh) * .7);
  box-shadow: inset 0 0 0 1px rgba(224, 168, 60, .3), 0 calc(var(--vh) * .5) calc(var(--vh) * 1.8) rgba(0, 0, 0, .6);
  animation: toPile .55s var(--ease) both;
}
@keyframes toPile { from { opacity: 0; transform: translateY(calc(var(--vh) * 16)) scale(.78); } }

/* -------------------------------------------------------------- hand ---- */

.hand {
  position: absolute; left: 50%; bottom: calc(var(--vh) * 2.4); transform: translateX(-50%);
  display: flex; align-items: flex-end; height: calc(var(--vh) * 21); z-index: 5;
}
.card-pl {
  position: relative;
  width: calc(var(--vh) * 12.6); height: calc(var(--vh) * 17.6);
  margin: 0 calc(var(--vh) * -1.9);
  border-radius: calc(var(--vh) * .9);
  background: var(--card-face); color: var(--card-ink);
  box-shadow: 0 calc(var(--vh) * .7) calc(var(--vh) * 2.8) rgba(0, 0, 0, .6);
  --rot: 0deg; --lift: 0px;
  transform: rotate(var(--rot)) translateY(var(--lift));
  transition: transform .3s var(--snap), box-shadow .25s ease;
  animation: dealIn .65s var(--ease) backwards;
}
@keyframes dealIn { from { opacity: 0; transform: translate(calc(var(--vh) * 9), calc(var(--vh) * -15)) rotate(22deg) scale(.85); } }
.card-pl::after {
  content: ''; position: absolute; inset: calc(var(--vh) * .85);
  border-radius: calc(var(--vh) * .5);
  box-shadow: inset 0 0 0 1px rgba(25, 21, 18, .22);
}
.card-pl .pip {
  position: absolute; left: calc(var(--vh) * .95); top: calc(var(--vh) * .75);
  display: flex; flex-direction: column; align-items: center;
  font-size: calc(var(--vh) * 1.95); font-weight: 800; line-height: 1;
}
.card-pl .pip svg { width: calc(var(--vh) * 1.5); height: calc(var(--vh) * 1.5); fill: currentColor; }
.card-pl .pip.br { left: auto; right: calc(var(--vh) * .95); top: auto; bottom: calc(var(--vh) * .75); transform: rotate(180deg); }
.card-pl .face { position: absolute; inset: 0; display: grid; place-items: center; }
.card-pl .face svg { width: calc(var(--vh) * 6.6); height: calc(var(--vh) * 6.6); fill: currentColor; opacity: .9; }
.card-pl.joker { color: #8a2b2b; }
/* the one hint the board gives you: a gold edge on the cards matching the
   called rank, which you could have worked out for yourself anyway */
.card-pl.match { box-shadow: inset 0 0 0 2px var(--gold), 0 calc(var(--vh) * .7) calc(var(--vh) * 2.8) rgba(0, 0, 0, .6); }
.card-pl.match .face svg { fill: var(--gold-dim); opacity: 1; }
.card-pl.pick {
  transform: rotate(0deg) translateY(calc(var(--vh) * -3.2));
  box-shadow: inset 0 0 0 2px var(--gold), 0 calc(var(--vh) * 2.5) calc(var(--vh) * 5) rgba(0, 0, 0, .78);
}

/* ------------------------------------------------------ shout and gun --- */

.shout {
  position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%) scale(.82);
  font-size: calc(var(--vh) * 8); font-weight: 800; letter-spacing: -.03em;
  color: var(--red-lit); text-shadow: 0 0 calc(var(--vh) * 8) rgba(214, 58, 52, .7);
  opacity: 0; z-index: 8; pointer-events: none;
  transition: opacity .2s ease, transform .35s var(--snap);
}
.shout.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.shout.safe { color: var(--green); text-shadow: 0 0 calc(var(--vh) * 8) rgba(69, 192, 122, .55); }

.gunwrap {
  position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%);
  width: calc(var(--vh) * 20); height: calc(var(--vh) * 20);
  opacity: 0; transition: opacity .4s var(--ease); z-index: 7; pointer-events: none;
}
.gunwrap.on { opacity: 1; }

/* ============================================================ THE ODDS ==
   A DEMONSTRATION, NOT A CHART. Six static cylinders in a row was a diagram
   OF the rule; this is the rule happening, one chamber a beat, in the order
   the game delivers it. The sixth fires.
   ========================================================================= */

.oddsdemo {
  position: relative; overflow: hidden;
  display: grid; place-items: center;
  padding: var(--s6) var(--s4) var(--s5);
}
.revolver { width: min(320px, 68vw); }
.cyl-body { fill: #171a18; stroke: #3b423d; stroke-width: 3; }
.cyl-hub  { fill: #222724; stroke: #4b524d; stroke-width: 2; }
.hole { fill: #060807; stroke: #4b524d; stroke-width: 2.5; transition: fill .35s var(--ease), stroke .35s var(--ease); }
.hole.live { fill: var(--red); stroke: var(--red-lit); }
.hole.just { animation: seat .55s var(--snap); transform-box: fill-box; transform-origin: center; }
@keyframes seat { 0% { transform: scale(.3); } }

.oddsread { margin-top: var(--s4); text-align: center; }
.oddsbig {
  font-size: clamp(2.6rem, 6vw, 3.6rem); font-weight: 800; letter-spacing: -.04em;
  line-height: 1; color: var(--tx);
  transition: color .35s var(--ease);
}
.oddsbig i { font-style: normal; color: var(--tx-4); font-size: .5em; }
.oddsstate {
  margin-top: 10px; font-size: .78rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--tx-3);
}
.oddsdemo.dead .oddsbig { color: var(--red-lit); }
.oddsdemo.dead .oddsstate { color: var(--red); }

.oddsflash {
  position: absolute; inset: -25%; pointer-events: none; opacity: 0;
  background: radial-gradient(circle at 50% 42%, rgba(255, 222, 158, .9), rgba(255, 124, 42, .22) 26%, transparent 58%);
}
.oddsdemo.fired .oddsflash { animation: fire .5s var(--ease); }
@keyframes fire { 0% { opacity: 1; transform: scale(.45); } 100% { opacity: 0; transform: scale(1.25); } }
.oddsdemo.fired .revolver { animation: kick .42s cubic-bezier(.36, .07, .19, .97); }
@keyframes kick {
  15% { transform: translate(-9px, 6px) rotate(-1.6deg); }
  40% { transform: translate(7px, -3px) rotate(1.1deg); }
  70% { transform: translate(-3px, 2px); }
}

/* ============================================================== THE BANG ==
   The script's real result frame. The clip is drawn on black, and `screen`
   drops that out entirely so the muzzle flash sits on the page rather than
   inside a box.
   ========================================================================= */

.bangbox {
  position: relative; display: grid; place-items: center;
  min-height: clamp(260px, 30vw, 420px);
  overflow: hidden;
}
.bangbox img { width: 100%; mix-blend-mode: screen; opacity: 0; transition: opacity .55s var(--ease); }
.bangbox img.on { opacity: 1; }
