/* eslint-disable */
// Felt, chips, bet spots, the two hands, the scoreboard roads, rails, the pay sheet and the result panel.
//
// Three layouts share these parts (bac-app.jsx picks one from window.BAC_CANVAS), as in Three Card Poker:
//   wide     — desktop / tablet: the 1380×860 stage at its designed sizes
//   tight    — the same stage scaled below ~56% (a phone held sideways); tappable controls are drawn larger
//   portrait — the 460-wide upright phone column

const BAC_CHIP_DEFS = [
  { value: 5,   color: '#c0392b', edge: '#7a1f15', label: '$5'   },
  { value: 25,  color: '#2e7d4f', edge: '#194530', label: '$25'  },
  { value: 100, color: '#1f3a6a', edge: '#0e1f3d', label: '$100' },
  { value: 500, color: '#5b2a7a', edge: '#321444', label: '$500' }
];

// Player is blue and Banker red, as on every baccarat scoreboard; Tie is green.
const BAC_SIDE = {
  player: { ink: '#6fb1f0', deep: '#1d4f86', glow: 'rgba(111,177,240,.55)' },
  banker: { ink: '#f0786c', deep: '#8a2219', glow: 'rgba(240,120,108,.55)' },
  tie:    { ink: '#6fd39b', deep: '#1f6b43', glow: 'rgba(111,211,155,.55)' }
};

const BAC_CAN_HOVER = !window.matchMedia || window.matchMedia('(hover: hover)').matches;
const bacMoney = n => '$' + Math.abs(Math.round(n)).toLocaleString('en-US');

function Chip({ value, size = 56, onClick, disabled, selected }) {
  const def = BAC_CHIP_DEFS.find(c => c.value === value) || BAC_CHIP_DEFS[0];
  return (
    <button
      aria-label={'Use $' + value + ' chips'}
      aria-pressed={!!selected}
      onClick={onClick}
      disabled={disabled}
      style={{
        position: 'relative', width: size, height: size, flexShrink: 0,
        borderRadius: '50%', padding: 0, border: 'none',
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? .35 : 1,
        background: 'transparent',
        transform: selected ? 'translateY(-8px)' : 'none',
        transition: 'transform .18s ease',
        outline: 'none'
      }}
      onMouseEnter={e => !disabled && !selected && BAC_CAN_HOVER && (e.currentTarget.style.transform = 'translateY(-4px)')}
      onMouseLeave={e => !disabled && (e.currentTarget.style.transform = selected ? 'translateY(-8px)' : 'none')}
    >
      <div className="chip-3d" style={{
        width: '100%', height: '100%', borderRadius: '50%',
        background: `radial-gradient(circle at 35% 30%, ${def.color}, ${def.edge} 75%)`,
        display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative',
        boxShadow: selected ? '0 0 0 3px #f5d896, 0 0 18px 4px rgba(245,216,150,.55), 0 6px 12px rgba(0,0,0,.45)' : undefined
      }}>
        {Array.from({ length: 8 }).map((_, i) => (
          <div key={i} style={{
            position: 'absolute', left: '50%', top: '50%',
            width: 4, height: size * 0.18, background: 'rgba(255,255,255,.85)', transformOrigin: 'center',
            transform: `translate(-50%,-50%) rotate(${i * 45}deg) translateY(-${size * 0.42}px)`, borderRadius: 2
          }} />
        ))}
        <div style={{
          position: 'absolute', inset: size * 0.16, borderRadius: '50%',
          border: '1.5px dashed rgba(255,255,255,.55)',
          background: `radial-gradient(circle at 40% 35%, rgba(255,255,255,.18), transparent 60%), ${def.color}`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: '#fff', fontFamily: "'Playfair Display', serif", fontWeight: 700, fontSize: size * 0.26,
          textShadow: '0 1px 2px rgba(0,0,0,.5)'
        }}>{def.label}</div>
      </div>
    </button>
  );
}

// A small chip stack drawn on a bet spot: the biggest denomination the amount uses.
function MiniChip({ amount, size = 22 }) {
  const def = [...BAC_CHIP_DEFS].reverse().find(c => amount >= c.value) || BAC_CHIP_DEFS[0];
  return (
    <span className="chip-place" style={{
      display: 'inline-block', width: size, height: size, borderRadius: '50%', flexShrink: 0,
      background: `radial-gradient(circle at 35% 30%, ${def.color}, ${def.edge} 75%)`,
      border: '2px dashed rgba(255,255,255,.7)',
      boxShadow: '0 2px 0 rgba(0,0,0,.35), 0 3px 6px rgba(0,0,0,.4)'
    }} />
  );
}

// A place to bet. `big` spots are Player and Banker; the rest are Tie and the side bets.
// outcome: null | 'win' | 'push' | 'lose' once the coup is settled; ret is what came back.
function BetSpot({ spot, amount, onClick, outcome, ret, big = false, compact = false, tight = false, showEdge = false, w, h }) {
  const R = BAC_RULES;
  const side = BAC_SIDE[spot === 'playerPair' ? 'player' : spot === 'bankerPair' ? 'banker' : spot === 'dragon7' ? 'banker' : spot];
  const interactive = !!onClick;
  const win = outcome === 'win', push = outcome === 'push', lose = outcome === 'lose';
  const label = R.LABELS[spot];
  const sub = spot === 'banker' ? '1:1 · 3-card 7 pushes' : R.ODDS[spot];
  const fs = compact ? (big ? 20 : 13) : tight ? (big ? 30 : 19) : (big ? 24 : 13);
  const subFs = compact ? (big ? 11 : 11) : tight ? 15 : (big ? 11 : 10);
  return (
    <button
      onClick={onClick}
      disabled={!interactive}
      aria-label={`${label}, pays ${R.ODDS[spot]}${amount ? `, $${amount} bet` : ''}`}
      className={win ? 'glow-pulse' : ''}
      style={{
        position: 'relative', width: w, height: h, flexShrink: 0,
        borderRadius: big ? 18 : 12,
        border: `2px ${amount > 0 ? 'solid' : 'dashed'} ${amount > 0 || win ? side.ink : 'rgba(230,197,144,.38)'}`,
        background: big
          ? `linear-gradient(180deg, ${side.deep}55, rgba(0,0,0,.28))`
          : 'radial-gradient(ellipse at 50% 40%, rgba(0,0,0,.18), rgba(0,0,0,.34))',
        color: 'var(--ivory)',
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
        padding: '0 6px', cursor: interactive ? 'pointer' : 'default',
        opacity: lose ? .45 : 1,
        transition: 'all .2s ease', outline: 'none', fontFamily: 'inherit'
      }}
      onMouseEnter={e => interactive && BAC_CAN_HOVER && (e.currentTarget.style.background = big ? `linear-gradient(180deg, ${side.deep}88, rgba(0,0,0,.2))` : 'radial-gradient(ellipse at 50% 40%, rgba(255,255,255,.06), rgba(0,0,0,.3))')}
      onMouseLeave={e => (e.currentTarget.style.background = big ? `linear-gradient(180deg, ${side.deep}55, rgba(0,0,0,.28))` : 'radial-gradient(ellipse at 50% 40%, rgba(0,0,0,.18), rgba(0,0,0,.34))')}
    >
      <div style={{
        fontFamily: "'Playfair Display', serif", fontStyle: big ? 'italic' : 'normal', fontWeight: 700,
        fontSize: fs, lineHeight: 1.05, letterSpacing: big ? '.06em' : '.02em',
        color: big || spot === 'tie' ? side.ink : 'var(--brass-2)', textTransform: big ? 'uppercase' : 'none', whiteSpace: 'nowrap'
      }}>{label}</div>
      <div style={{ fontSize: subFs, letterSpacing: '.08em', color: 'var(--ivory-dim)', marginTop: 2, whiteSpace: 'nowrap' }}>
        {sub}{showEdge && !compact ? ` · edge ${R.EDGE[spot]}%` : ''}
      </div>
      {amount > 0 && (
        <div style={{
          position: 'absolute', ...(compact && big ? { top: 6 } : { bottom: big ? 8 : 4 }), right: big ? 12 : 6,
          display: 'flex', alignItems: 'center', gap: 5,
          fontFamily: "'Playfair Display', serif", fontWeight: 700, fontSize: compact ? 14 : tight ? 20 : (big ? 17 : 13), color: 'var(--brass-2)'
        }}>
          {!compact || big ? <MiniChip amount={amount} size={compact ? 16 : tight ? 26 : (big ? 22 : 16)} /> : null}${amount}
        </div>
      )}
      {(win || push) && (
        <div style={{
          position: 'absolute', top: -11, left: '50%', transform: 'translateX(-50%)',
          fontSize: compact || tight ? 12 : 10, letterSpacing: '.14em', textTransform: 'uppercase', fontWeight: 800,
          background: win ? 'linear-gradient(180deg, #f5d896, #c9a26a)' : 'rgba(35,22,10,.95)',
          color: win ? '#1a1208' : 'var(--brass-2)', border: win ? 'none' : '1px solid rgba(230,197,144,.5)',
          padding: '2px 9px', borderRadius: 4, whiteSpace: 'nowrap', boxShadow: '0 4px 10px rgba(0,0,0,.4)'
        }}>{win ? `+${bacMoney(ret - amount)}` : 'Push'}</div>
      )}
    </button>
  );
}

// The whole betting layout: the long shots in a row, Player and Banker beneath.
function BetLayout({ bets, onBet, settled, compact = false, tight = false, showEdge = false, width }) {
  const out = settled ? settled.outcome : {};
  const ret = settled ? settled.returns : {};
  const gap = compact ? 6 : tight ? 12 : 12;
  const smallW = Math.floor((width - gap * 3) / 4);
  const bigW = Math.floor((width - gap) / 2);
  const smallH = compact ? 50 : tight ? 78 : 60;
  const bigH = compact ? 66 : tight ? 100 : 84;
  const spot = (k, big) => (
    <BetSpot key={k} spot={k} big={big} compact={compact} tight={tight} showEdge={showEdge}
      w={big ? bigW : smallW} h={big ? bigH : smallH}
      amount={bets[k]} outcome={out[k]} ret={ret[k]}
      onClick={onBet ? () => onBet(k) : null} />
  );
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap, width }}>
      <div style={{ display: 'flex', gap }}>{['playerPair', 'tie', 'dragon7', 'bankerPair'].map(k => spot(k, false))}</div>
      <div style={{ display: 'flex', gap }}>{spot('player', true)}{spot('banker', true)}</div>
    </div>
  );
}

// One hand: its name, its running total, and up to three cards.
function HandBox({ who, cards, shownCount, total, winner, cardW, cardH, compact = false, tight = false, natural }) {
  const side = BAC_SIDE[who];
  const won = winner === who, tied = winner === 'tie';
  const overlap = compact ? Math.round(cardW * 0.34) : 0;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: compact ? 4 : 8 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, height: compact ? 26 : tight ? 40 : 30 }}>
        <span style={{
          fontSize: compact ? 13 : tight ? 20 : 13, letterSpacing: '.22em', fontWeight: 800, textTransform: 'uppercase', color: side.ink
        }}>{who === 'player' ? 'Player' : 'Banker'}</span>
        <span aria-label={`${who} total`} style={{
          minWidth: compact ? 26 : tight ? 40 : 32, height: compact ? 26 : tight ? 40 : 30, borderRadius: 999, padding: '0 6px',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: "'Playfair Display', serif", fontWeight: 700, fontSize: compact ? 17 : tight ? 26 : 19,
          background: won ? side.ink : tied && total != null ? BAC_SIDE.tie.ink : 'rgba(0,0,0,.45)',
          color: won || (tied && total != null) ? '#10140f' : 'var(--ivory)',
          border: `1px solid ${side.ink}88`,
          boxShadow: won ? `0 0 18px ${side.glow}` : 'none',
          visibility: total == null ? 'hidden' : 'visible'
        }}>{total == null ? 0 : total}</span>
        {natural && (
          <span style={{ fontSize: compact ? 11 : tight ? 16 : 10, letterSpacing: '.18em', textTransform: 'uppercase', color: 'var(--brass-2)', fontWeight: 700 }}>Natural</span>
        )}
      </div>
      <div style={{ display: 'flex', height: cardH, minWidth: cardW * 3 - overlap * 2 + (compact ? 0 : 16), justifyContent: 'center' }}>
        {cards.length === 0
          ? [0, 1].map(i => <div key={i} style={{ width: cardW, height: cardH, marginLeft: i ? (compact ? 6 : 8) : 0, borderRadius: 10, border: '1.5px dashed rgba(230,197,144,.18)' }} />)
          : cards.map((c, i) => (
            <div key={c.id} style={{ marginLeft: i ? (compact ? -overlap : 8) : 0, position: 'relative', zIndex: i }}>
              <PlayingCard rank={c.rank} suit={c.suit} faceDown={i >= shownCount}
                w={cardW} h={cardH} dealIndex={i < 2 ? (who === 'player' ? i * 2 : i * 2 + 1) : 0}
                fromX={who === 'player' ? 220 : -40} fromY={-260}
                glow={won} />
            </div>
          ))}
      </div>
    </div>
  );
}

// ── Scoreboard: the bead plate and the big road ──
function BeadPlate({ history, cell = 15, cols = 10 }) {
  const all = BAC_RULES.beadPlate(history, 6);
  const lastCol = all.length ? all[all.length - 1].col : 0;
  const from = Math.max(0, lastCol - cols + 1);
  const shown = all.filter(c => c.col >= from);
  const W = cols * cell, H = 6 * cell;
  return (
    <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} role="img" aria-label="Bead plate: every coup this shoe" style={{ display: 'block', flexShrink: 0 }}>
      <rect width={W} height={H} fill="rgba(255,253,246,.92)" rx="4" />
      {Array.from({ length: cols - 1 }).map((_, i) => <line key={'v' + i} x1={(i + 1) * cell} x2={(i + 1) * cell} y1="0" y2={H} stroke="rgba(0,0,0,.1)" />)}
      {Array.from({ length: 5 }).map((_, i) => <line key={'h' + i} y1={(i + 1) * cell} y2={(i + 1) * cell} x1="0" x2={W} stroke="rgba(0,0,0,.1)" />)}
      {shown.map((c, i) => {
        const x = (c.col - from) * cell + cell / 2, y = c.row * cell + cell / 2;
        const fill = BAC_SIDE[c.h.winner].deep;
        return (
          <g key={i}>
            <circle cx={x} cy={y} r={cell * 0.42} fill={fill} />
            <text x={x} y={y + cell * 0.18} textAnchor="middle" fontSize={cell * 0.52} fontWeight="700" fill="#fff" fontFamily="Inter, system-ui, sans-serif">
              {c.h.winner === 'player' ? 'P' : c.h.winner === 'banker' ? 'B' : 'T'}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

function BigRoad({ history, cell = 15, cols = 30 }) {
  const road = BAC_RULES.bigRoad(history, 6);
  const maxCol = road.cells.reduce((m, c) => Math.max(m, c.col), 0);
  const from = Math.max(0, maxCol - cols + 2);
  const W = cols * cell, H = 6 * cell;
  return (
    <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} role="img" aria-label="Big road: streaks of Player and Banker wins" style={{ display: 'block', flexShrink: 0 }}>
      <rect width={W} height={H} fill="rgba(255,253,246,.92)" rx="4" />
      {Array.from({ length: cols - 1 }).map((_, i) => <line key={'v' + i} x1={(i + 1) * cell} x2={(i + 1) * cell} y1="0" y2={H} stroke="rgba(0,0,0,.1)" />)}
      {Array.from({ length: 5 }).map((_, i) => <line key={'h' + i} y1={(i + 1) * cell} y2={(i + 1) * cell} x1="0" x2={W} stroke="rgba(0,0,0,.1)" />)}
      {road.cells.filter(c => c.col >= from).map((c, i) => {
        const x = (c.col - from) * cell + cell / 2, y = c.row * cell + cell / 2, r = cell * 0.36;
        const ink = BAC_SIDE[c.winner].deep;
        return (
          <g key={i}>
            <circle cx={x} cy={y} r={r} fill="none" stroke={ink} strokeWidth={cell * 0.14} />
            {c.ties > 0 && <line x1={x - r} y1={y + r} x2={x + r} y2={y - r} stroke={BAC_SIDE.tie.deep} strokeWidth={cell * 0.13} />}
            {c.ties > 1 && <text x={x} y={y + cell * 0.17} textAnchor="middle" fontSize={cell * 0.5} fontWeight="800" fill={BAC_SIDE.tie.deep}>{c.ties}</text>}
            {c.bankerPair && <circle cx={x - r * 0.8} cy={y - r * 0.8} r={cell * 0.12} fill={BAC_SIDE.banker.deep} />}
            {c.playerPair && <circle cx={x + r * 0.8} cy={y + r * 0.8} r={cell * 0.12} fill={BAC_SIDE.player.deep} />}
          </g>
        );
      })}
    </svg>
  );
}

function RoadCounts({ history, shoeLeft, compact = false, tight = false }) {
  const n = BAC_RULES.counts(history);
  const fs = compact ? 12 : tight ? 17 : 11;
  const pill = (k, label) => (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, whiteSpace: 'nowrap' }}>
      <span style={{ width: fs - 1, height: fs - 1, borderRadius: '50%', background: BAC_SIDE[k].deep, border: `1.5px solid ${BAC_SIDE[k].ink}` }} />
      <span style={{ color: 'var(--ivory-dim)' }}>{label}</span>
      <b style={{ color: 'var(--ivory)', fontFamily: "'JetBrains Mono', monospace", fontWeight: 600 }}>{n[k]}</b>
    </span>
  );
  return (
    <div style={{ display: 'flex', flexDirection: compact ? 'row' : 'column', gap: compact ? 12 : tight ? 8 : 6, fontSize: fs, letterSpacing: '.08em', textTransform: 'uppercase', fontWeight: 600, justifyContent: 'center' }}>
      {pill('banker', 'Banker')}
      {pill('player', 'Player')}
      {pill('tie', 'Tie')}
      <span style={{ color: 'var(--ivory-dim)', whiteSpace: 'nowrap' }} title="Cards left before the cut card">
        Shoe <b style={{ color: 'var(--ivory)', fontFamily: "'JetBrains Mono', monospace", fontWeight: 600 }}>{shoeLeft}</b>
      </span>
    </div>
  );
}

function Scoreboard({ history, shoeLeft, tight = false }) {
  const cell = tight ? 17 : 14;
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14, padding: tight ? '6px 10px' : '8px 12px',
      background: 'linear-gradient(180deg, rgba(20,12,6,.88), rgba(10,6,3,.88))',
      border: '1px solid rgba(201,162,106,.35)', borderRadius: 10,
      boxShadow: '0 10px 24px rgba(0,0,0,.4)'
    }}>
      <BeadPlate history={history} cell={cell} cols={tight ? 8 : 11} />
      <BigRoad history={history} cell={cell} cols={tight ? 20 : 29} />
      <RoadCounts history={history} shoeLeft={shoeLeft} tight={tight} />
    </div>
  );
}

function FeltBackdrop() {
  return (
    <div style={{
      position: 'absolute', inset: 0, borderRadius: 18, overflow: 'hidden',
      background: 'radial-gradient(ellipse 110% 75% at 50% 45%, #1a5040 0%, #0e3a2e 45%, #0a2a21 80%), #0a2a21',
      boxShadow: 'var(--shadow-deep), inset 0 0 0 1px rgba(201,162,106,.18), inset 0 0 80px rgba(0,0,0,.5)'
    }}>
      <div style={{ position: 'absolute', inset: 0, backgroundImage: 'url(../assets/casino/felt.webp)', backgroundSize: 'cover', opacity: .25, mixBlendMode: 'overlay' }} />
      <svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', opacity: .5 }}>
        <filter id="bacn">
          <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" stitchTiles="stitch" />
          <feColorMatrix values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .12 0" />
        </filter>
        <rect width="100%" height="100%" filter="url(#bacn)" />
      </svg>
    </div>
  );
}

function FeltLogo() {
  return (
    <div style={{ position: 'absolute', left: 0, right: 0, top: '42%', textAlign: 'center', pointerEvents: 'none', opacity: .16 }}>
      <div style={{ fontFamily: "'Playfair Display', serif", fontSize: 40, letterSpacing: '.3em', color: 'var(--brass-2)', fontStyle: 'italic', fontWeight: 600 }}>Baccarat</div>
    </div>
  );
}

// The player's seat on the rail: an initial avatar (or a silhouette for a guest)
// that opens the name card. A plain click opens the card in place; a modifier
// or middle click falls through to the full profile page.
function BacProfilePill({ name, height = 34, showName = true, fontSize = 10, onOpen }) {
  const initial = (name || '').trim().charAt(0).toUpperCase();
  const avatar = height >= 44 ? 26 : 22;
  function click(e) {
    if (!onOpen) return;
    if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button === 1) return;
    e.preventDefault();
    onOpen();
  }
  return (
    <a href="/profile/" title="Your name and account" aria-label={name ? `${name}: your name and account` : 'Your name and account'}
       onClick={click} style={{
      display: 'inline-flex', alignItems: 'center', gap: 8, flex: 'none',
      height, padding: showName ? '0 12px 0 6px' : '0 6px',
      background: 'rgba(20,12,6,.6)', color: 'var(--brass-2)',
      border: '1px solid rgba(201,162,106,.5)', borderRadius: 999,
      fontSize, fontWeight: 700, letterSpacing: '.14em',
      textTransform: 'uppercase', textDecoration: 'none', whiteSpace: 'nowrap'
    }}>
      <span aria-hidden="true" style={{
        width: avatar, height: avatar, borderRadius: '50%', flex: 'none',
        background: 'radial-gradient(circle at 35% 30%, #f5d896, #8c6a3f 75%)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: "'Playfair Display', serif", fontStyle: 'italic', fontWeight: 800,
        fontSize: avatar * 0.6, color: '#1a1208', letterSpacing: 0,
        boxShadow: 'inset 0 1px 0 rgba(255,255,255,.4), 0 1px 3px rgba(0,0,0,.4)'
      }}>
        {initial || (
          <svg viewBox="0 0 24 24" width={avatar * 0.62} height={avatar * 0.62} fill="#1a1208" aria-hidden="true">
            <circle cx="12" cy="8" r="4.2"/><path d="M4 20.5c0-4.2 3.6-7 8-7s8 2.8 8 7z"/>
          </svg>
        )}
      </span>
      {showName && <span style={{ maxWidth: 110, overflow: 'hidden', textOverflow: 'ellipsis' }}>{name || 'Profile'}</span>}
    </a>
  );
}

function BrassRail({ bankroll, streak, played, won, showHints, onToggleHints, onPays, playerName, onOpenProfile, tight = false }) {
  const winRate = played ? Math.round(won / played * 100) : null;
  const railBtn = tight ? { padding: '0 16px', minHeight: 68, fontSize: 16, letterSpacing: '.1em' } : null;
  const logoPx = tight ? 36 : 32;
  const btn = {
    display: 'inline-flex', alignItems: 'center', alignSelf: 'center', padding: '8px 14px',
    background: 'rgba(20,12,6,.6)', color: 'var(--brass-2)', border: '1px solid rgba(201,162,106,.5)', borderRadius: 999,
    fontSize: 10, fontWeight: 700, letterSpacing: '.18em', textTransform: 'uppercase', textDecoration: 'none', whiteSpace: 'nowrap',
    cursor: 'pointer', boxShadow: '0 2px 6px rgba(0,0,0,.3)', fontFamily: 'inherit', ...railBtn
  };
  return (
    <div style={{
      display: 'flex', alignItems: 'stretch', margin: '14px 22px 0', padding: tight ? '3px 10px' : '10px 18px',
      background: 'linear-gradient(180deg, rgba(35,22,10,.75), rgba(20,12,6,.85))', border: '1px solid rgba(201,162,106,.35)',
      borderRadius: 10, backdropFilter: 'blur(10px)', boxShadow: '0 8px 22px rgba(0,0,0,.4), inset 0 1px 0 rgba(230,197,144,.15)',
      zIndex: 5, position: 'relative'
    }}>
      <a href="../casino/" title="Back to casino" style={{ ...btn, marginRight: 14 }}>← Lobby</a>
      {/* Brand: the site logo after the lobby link, linking home. Gives way before the stats do. */}
      <a href="/" title="Limestone Games home" style={{
        display: 'flex', alignItems: 'center', gap: 10, paddingRight: tight ? 12 : 14, marginRight: 12,
        borderRight: '1px solid rgba(201,162,106,.2)', textDecoration: 'none', color: 'inherit',
        whiteSpace: 'nowrap', minWidth: 0, overflow: 'hidden'
      }}>
        <img src="../assets/logo-96.png" alt="" width={logoPx} height={logoPx} decoding="async"
             style={{ width: logoPx, height: logoPx, borderRadius: 8, flexShrink: 0, boxShadow: '0 2px 6px rgba(0,0,0,.4)' }} />
        {!tight && (
          <div style={{ minWidth: 0 }}>
            <div style={{ fontFamily: "'Playfair Display', serif", fontSize: 17, color: 'var(--brass-2)', fontStyle: 'italic', fontWeight: 600, letterSpacing: '.02em', lineHeight: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Limestone Games</div>
            <div style={{ fontSize: 9, letterSpacing: '.32em', color: 'var(--ivory-dim)', textTransform: 'uppercase', marginTop: 3, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Baccarat · Table 08</div>
          </div>
        )}
      </a>
      {/* Stat slots — never squeezed; the brand gives way first */}
      <div style={{ flex: '1 0 auto', display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
        <RailStat tight={tight} label="Bankroll" value={bacMoney(bankroll)} accent />
        <RailStat tight={tight} label="Streak" value={streak > 0 ? `🔥 ×${streak}` : '—'} highlight={streak >= 3} />
        <RailStat tight={tight} label="Hands" value={played || '—'} />
        {!tight && <RailStat label="Win Rate" value={winRate !== null ? `${winRate}%` : '—'} />}
        <button onClick={onPays} style={{ ...btn, marginLeft: 14 }}>Pays</button>
        <button onClick={onToggleHints} title={showHints ? 'Hide strategy hints' : 'Show strategy hints'} style={{
          ...btn, marginLeft: 8,
          background: showHints ? 'linear-gradient(180deg, #e6c590, #c9a26a)' : 'rgba(20,12,6,.6)',
          color: showHints ? '#1a1208' : 'var(--brass-2)'
        }}>{showHints ? '✦ Hints On' : 'Hints Off'}</button>
        <span style={{ marginLeft: 8, display: 'inline-flex', alignSelf: 'center' }}>
          <BacProfilePill name={playerName} height={tight ? 56 : 34} fontSize={tight ? 14 : 10} onOpen={onOpenProfile} />
        </span>
      </div>
    </div>
  );
}

function RailStat({ label, value, accent, highlight, small, tight = false }) {
  return (
    <div style={{ padding: tight ? '4px 12px' : '4px 16px', borderLeft: '1px solid rgba(201,162,106,.18)', textAlign: 'right', minWidth: tight ? undefined : small ? 80 : 92 }}>
      <div style={{ fontSize: tight ? 13 : 8, letterSpacing: tight ? '.14em' : '.28em', color: 'var(--ivory-dim)', textTransform: 'uppercase', fontWeight: 600 }}>{label}</div>
      <div style={{
        fontFamily: accent ? "'Playfair Display', serif" : "'JetBrains Mono', monospace",
        fontSize: accent ? (tight ? 30 : 22) : tight ? 22 : (small ? 13 : 15),
        color: highlight ? '#ffb347' : accent ? 'var(--brass-2)' : '#fff',
        fontWeight: accent ? 700 : 500, lineHeight: 1.1, marginTop: 2, fontStyle: accent ? 'italic' : 'normal'
      }}>{value}</div>
    </div>
  );
}

// Slim top rail for the upright layout: Lobby, logo, bankroll, pays, hints, the player's seat.
function PortraitRail({ bankroll, streak, showHints, onToggleHints, onPays, playerName, onOpenProfile }) {
  const pill = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center', minHeight: 44, padding: '0 12px',
    border: '1px solid rgba(201,162,106,.5)', borderRadius: 999, fontSize: 12, fontWeight: 700, letterSpacing: '.1em',
    textTransform: 'uppercase', whiteSpace: 'nowrap', cursor: 'pointer', textDecoration: 'none', fontFamily: 'inherit',
    boxShadow: '0 2px 6px rgba(0,0,0,.3)'
  };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 6, padding: '4px 6px',
      background: 'linear-gradient(180deg, rgba(35,22,10,.8), rgba(20,12,6,.88))', border: '1px solid rgba(201,162,106,.35)',
      borderRadius: 14, boxShadow: '0 8px 22px rgba(0,0,0,.4), inset 0 1px 0 rgba(230,197,144,.15)', flexShrink: 0
    }}>
      <a href="../casino/" title="Back to casino" style={{ ...pill, background: 'rgba(20,12,6,.6)', color: 'var(--brass-2)' }}>← Lobby</a>
      <a href="/" title="Limestone Games home" aria-label="Limestone Games home" style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', minHeight: 44, width: 40, flexShrink: 0 }}>
        <img src="../assets/logo-96.png" alt="" width="34" height="34" decoding="async" style={{ width: 34, height: 34, borderRadius: 8, boxShadow: '0 2px 6px rgba(0,0,0,.45)' }} />
      </a>
      <div style={{ flex: 1, minWidth: 0, textAlign: 'center', lineHeight: 1 }}>
        <div style={{ fontSize: 12, letterSpacing: '.14em', color: 'var(--ivory-dim)', textTransform: 'uppercase', fontWeight: 600 }}>
          Bankroll{streak > 0 ? ` · 🔥×${streak}` : ''}
        </div>
        <div style={{ fontFamily: "'Playfair Display', serif", fontStyle: 'italic', fontSize: 24, fontWeight: 700, color: 'var(--brass-2)', marginTop: 3 }}>{bacMoney(bankroll)}</div>
      </div>
      <button onClick={onPays} style={{ ...pill, background: 'rgba(20,12,6,.6)', color: 'var(--brass-2)' }}>Pays</button>
      <button onClick={onToggleHints} title={showHints ? 'Hide strategy hints' : 'Show strategy hints'} style={{
        ...pill, background: showHints ? 'linear-gradient(180deg, #e6c590, #c9a26a)' : 'rgba(20,12,6,.6)', color: showHints ? '#1a1208' : 'var(--brass-2)'
      }}>{showHints ? '✦ Hints' : 'Hints'}</button>
      <BacProfilePill name={playerName} height={44} showName={false} onOpen={onOpenProfile} />
    </div>
  );
}

// The pay table, the drawing rules and the house edges, over the table (every layout).
function PaySheet({ onClose, big = false }) {
  const R = BAC_RULES;
  const fs = big ? 18 : 14;
  const rows = ['banker', 'player', 'tie', 'playerPair', 'bankerPair', 'dragon7'];
  const what = {
    banker: 'Banker wins. A Banker win on a three-card 7 pushes.',
    player: 'Player wins.',
    tie: 'The hands tie. Player and Banker bets push.',
    playerPair: 'Player’s first two cards are a pair.',
    bankerPair: 'Banker’s first two cards are a pair.',
    dragon7: 'Banker wins with a three-card 7.'
  };
  const th = { textAlign: 'left', padding: '0 8px 8px', fontSize: big ? 13 : 10, letterSpacing: '.14em', color: 'var(--ivory-dim)', textTransform: 'uppercase', fontWeight: 700 };
  const td = { padding: big ? '9px 8px' : '6px 8px', fontSize: fs, borderTop: '1px solid rgba(230,197,144,.12)', verticalAlign: 'top' };
  return (
    <div role="dialog" aria-label="Pays and rules" style={{
      position: 'absolute', inset: 0, zIndex: 30, background: 'rgba(8,5,2,.72)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 14
    }} onClick={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div style={{
        width: big ? '100%' : 640, maxHeight: '100%', overflow: 'auto', padding: big ? '18px 16px 16px' : '22px 24px 18px',
        background: 'linear-gradient(180deg, rgba(28,18,8,.98), rgba(12,7,3,.98))', borderRadius: 14,
        border: '1px solid rgba(230,197,144,.45)', boxShadow: '0 20px 50px rgba(0,0,0,.6)'
      }}>
        <div style={{ fontFamily: "'Playfair Display', serif", fontStyle: 'italic', fontSize: big ? 24 : 26, fontWeight: 600, color: 'var(--brass-2)', marginBottom: 12, textAlign: 'center' }}>Pays &amp; rules</div>
        <table style={{ width: '100%', borderCollapse: 'collapse' }}>
          <thead><tr><th style={th}>Bet</th><th style={th}>Pays</th><th style={th}>When</th><th style={{ ...th, textAlign: 'right' }}>Edge</th></tr></thead>
          <tbody>
            {rows.map(k => (
              <tr key={k}>
                <td style={{ ...td, fontFamily: "'Playfair Display', serif", fontStyle: 'italic', color: k === 'player' || k === 'banker' || k === 'tie' ? BAC_SIDE[k].ink : 'var(--ivory)', whiteSpace: 'nowrap' }}>{R.LABELS[k]}</td>
                <td style={{ ...td, fontFamily: "'JetBrains Mono', monospace", color: 'var(--brass-2)', whiteSpace: 'nowrap' }}>{R.ODDS[k]}</td>
                <td style={{ ...td, color: 'var(--ivory-dim)', lineHeight: 1.35 }}>{what[k]}</td>
                <td style={{ ...td, fontFamily: "'JetBrains Mono', monospace", textAlign: 'right', color: 'var(--ivory-dim)', whiteSpace: 'nowrap' }}>{R.EDGE[k]}%</td>
              </tr>
            ))}
          </tbody>
        </table>
        <div style={{ marginTop: 14, fontSize: big ? 15 : 13, lineHeight: 1.5, color: 'var(--ivory-dim)' }}>
          Cards count face value; aces are 1 and tens and court cards are 0. Only the last digit of a total counts, so 7 + 8 is 5.
          Either hand on 8 or 9 with two cards is a <b style={{ color: 'var(--ivory)' }}>natural</b>, and both stand.
          Otherwise Player draws on 0–5 and stands on 6–7. If Player stood, Banker draws on 0–5; if Player drew, Banker follows
          the house table (on 3 Banker draws unless Player’s third card was an 8; on 6 only against a 6 or 7). Eight decks, reshuffled at the cut card.
        </div>
        <button onClick={onClose} style={{
          marginTop: 16, width: '100%', minHeight: big ? 52 : 44,
          background: 'linear-gradient(180deg, rgba(40,28,18,.95), rgba(20,12,6,.95))', color: 'var(--ivory)',
          border: '1px solid rgba(201,162,106,.45)', borderRadius: 12, fontFamily: "'Playfair Display', serif", fontStyle: 'italic',
          fontSize: big ? 20 : 18, fontWeight: 600, cursor: 'pointer'
        }}>Close</button>
      </div>
    </div>
  );
}

// ── Hand result in plain words ──
// coup: BAC_RULES.coup(); s: BAC_RULES.settle(); bets: the stakes.
function bacResultWords(coup, s, bets) {
  const R = BAC_RULES;
  const signed = (k) => {
    const o = s.outcome[k], amt = bets[k];
    if (!o) return null;
    if (o === 'push') return R.LABELS[k] + ' push';
    if (o === 'win') return R.LABELS[k] + ' +' + bacMoney(s.returns[k] - amt);
    return R.LABELS[k] + ' −' + bacMoney(amt);
  };
  let title;
  if (s.net > 0) title = 'You win ' + bacMoney(s.net);
  else if (s.net < 0) title = 'You lose ' + bacMoney(s.net);
  else title = 'Push. Your bets come back';

  const pt = coup.playerTotal, bt = coup.bankerTotal;
  let reason;
  if (coup.winner === 'tie') reason = `Tie, ${pt} to ${bt}. Player and Banker bets push.`;
  else {
    const W = coup.winner === 'player' ? 'Player' : 'Banker';
    const wt = Math.max(pt, bt), lt = Math.min(pt, bt);
    const nat = coup.natural && (coup.winner === 'player' ? coup.player.length === 2 && pt >= 8 : coup.banker.length === 2 && bt >= 8);
    reason = `${W} wins ${wt} to ${lt}${nat ? ' with a natural' : ''}.`;
    if (coup.dragon7) reason += ' A three-card 7 for Banker: Banker bets push.';
  }
  const pairs = [coup.playerPair && 'Player pair', coup.bankerPair && 'Banker pair'].filter(Boolean);
  if (pairs.length) reason += ' ' + pairs.join(' and ') + '.';

  const detail = R.SPOTS.map(signed).filter(Boolean).join(' · ');
  const bonus = (s.outcome.tie === 'win') || (s.outcome.dragon7 === 'win') || (s.outcome.playerPair === 'win') || (s.outcome.bankerPair === 'win');
  const tone = s.net > 0 ? (bonus ? 'bonus' : 'win') : s.net < 0 ? 'lose' : 'push';
  return { title, reason, detail, tone };
}

const BAC_RESULT_TONES = {
  win: { color: '#9eddb8', glow: 'rgba(158,221,184,.55)' },
  bonus: { color: '#ffd97a', glow: 'rgba(255,217,122,.6)' },
  lose: { color: '#f29a8c', glow: 'rgba(192,57,43,.6)' },
  push: { color: '#e6c590', glow: 'rgba(201,162,106,.55)' }
};

function ResultPanel({ words, size = 'wide' }) {
  if (!words) return null;
  const t = BAC_RESULT_TONES[words.tone] || BAC_RESULT_TONES.push;
  const S = size === 'tight'
    ? { title: 34, reason: 21, detail: 19, pad: '10px 18px', gap: 3 }
    : size === 'portrait'
      ? { title: 22, reason: 15, detail: 13, pad: '6px 12px', gap: 2 }
      : { title: 26, reason: 15, detail: 12, pad: '12px 18px', gap: 4 };
  return (
    <div role="status" aria-live="polite" style={{
      width: '100%', padding: S.pad, background: 'linear-gradient(180deg, rgba(15,10,5,.9), rgba(8,4,2,.9))',
      border: `1px solid ${t.glow}`, borderRadius: 10, boxShadow: `0 0 34px -12px ${t.glow}, 0 10px 24px rgba(0,0,0,.45)`,
      textAlign: size === 'portrait' ? 'center' : 'left'
    }}>
      <div style={{ fontFamily: "'Playfair Display', serif", fontStyle: 'italic', fontWeight: 700, fontSize: S.title, lineHeight: 1.15, color: t.color }}>{words.title}</div>
      <div style={{ fontSize: S.reason, lineHeight: 1.3, color: 'var(--ivory)', marginTop: S.gap }}>{words.reason}</div>
      <div style={{ fontSize: S.detail, lineHeight: 1.3, color: 'var(--brass-2)', marginTop: S.gap, fontWeight: 600, letterSpacing: '.02em' }}>{words.detail}</div>
    </div>
  );
}

// The hint for the bets on the table: Baccarat has no decisions after the deal, so the only advice is where to bet.
function bacHint(bets) {
  const R = BAC_RULES;
  const longShots = ['tie', 'playerPair', 'bankerPair', 'dragon7'].filter(k => bets[k] > 0);
  if (longShots.length) {
    const worst = longShots.reduce((a, b) => (R.EDGE[a] > R.EDGE[b] ? a : b));
    return { action: 'Long shots cost more', explanation: `${R.LABELS[worst]} gives the house ${R.EDGE[worst]}%, against ${R.EDGE.banker}% on Banker. Fun for the big payout; the main bets last longer.` };
  }
  if (bets.player > 0 && bets.banker > 0) {
    return { action: 'Pick one side', explanation: 'Betting Player and Banker together mostly cancels out, and you still pay the house edge on both.' };
  }
  if (bets.player > 0) {
    return { action: 'Banker is a touch better', explanation: `Player is a fine bet (${R.EDGE.player}% edge), but Banker wins more often and has the lowest edge here, ${R.EDGE.banker}%.` };
  }
  return { action: 'Bet Banker', explanation: `Banker wins 45.9% of hands to Player’s 44.6%, the lowest house edge at the table (${R.EDGE.banker}%). The roads don’t predict the next hand.` };
}

Object.assign(window, {
  BAC_CHIP_DEFS, BAC_SIDE, Chip, MiniChip, BetSpot, BetLayout, HandBox,
  BeadPlate, BigRoad, RoadCounts, Scoreboard, FeltBackdrop, FeltLogo,
  BrassRail, RailStat, PortraitRail, BacProfilePill, PaySheet, ResultPanel, bacResultWords, bacHint, bacMoney
});
