/* ============================================================
   Munch Mania — brand system
   Palette from the Munch's Supply / Munch Mania logo:
     navy  #1E355E  (primary)   deep #112955 / #0C1E42
     blue  #35548C  light #6E92CE  pale #AEC3E6
     gray  #CAC8C8  light #F6F6F6
   Crisp, corporate layout — small radii, straight rules, tight
   shadows — with the playful icons + confetti kept for energy.
   ============================================================ */

:root {
    --navy: #1E355E;
    --navy-deep: #112955;
    --navy-900: #0C1E42;
    --blue: #35548C;
    --blue-bright: #6E92CE;
    --blue-pale: #AEC3E6;
    --gray: #CAC8C8;
    --gray-mid: #6b7385;
    --gray-light: #F6F6F6;
    --ink: #1c2942;
    --line: #e3e7ef;

    --font-ui: "Montserrat", "Segoe UI", system-ui, -apple-system, sans-serif;
    /* One branded typeface throughout — no playful display face. */
    --font-display: "Montserrat", "Segoe UI", system-ui, -apple-system, sans-serif;

    --radius: 4px;
    --radius-md: 6px;

    --shadow-card: 0 1px 2px rgba(12, 30, 66, .06), 0 1px 3px rgba(12, 30, 66, .10);
    --shadow-pop: 0 6px 22px rgba(12, 30, 66, .16);
}

body {
    font-family: var(--font-ui);
    color: var(--ink);
    background: var(--gray-light);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* Sticky footer (canonical). The body is a full-height flex column. The content
   region grows to push the footer to the viewport bottom when content is short,
   and — crucially — has flex-shrink:0 so it keeps its natural height and never
   gets compressed into the footer when the content is near the viewport height.
   The footer also never shrinks. When content is taller than the window, nothing
   grows or shrinks: the footer simply sits below the content and scrolls. */
body > .container { flex: 1 0 auto; }
.munch-footer { flex-shrink: 0; }

/* ---------- Navbar ---------- */
.munch-navbar {
    background: linear-gradient(100deg, var(--navy-deep) 0%, var(--navy) 70%, #24406e 100%);
    box-shadow: 0 1px 0 rgba(0, 0, 0, .15);
    border-bottom: 3px solid var(--blue-bright);
    padding-top: .4rem;
    padding-bottom: .4rem;
}

/* Logo doubled in the header; the wordmark lives in the logo itself. */
.munch-navbar .navbar-brand { display: inline-flex; align-items: center; padding: 0; }
.munch-navbar .navbar-brand img { height: 64px; display: block; }

.munch-navbar .nav-link {
    color: rgba(255, 255, 255, .82) !important;
    font-weight: 600;
    font-size: .95rem;
    letter-spacing: .2px;
    border-radius: var(--radius);
}
.munch-navbar .nav-link:hover { color: #fff !important; }
.munch-navbar .navbar-text { color: rgba(255, 255, 255, .9); font-weight: 600; }

.btn-signout {
    border: 1px solid rgba(255, 255, 255, .55);
    color: #fff;
    font-weight: 600;
    border-radius: var(--radius);
    padding: .35rem 1rem;
    transition: background .15s ease, color .15s ease;
}
.btn-signout:hover { background: #fff; color: var(--navy); }

.role-pill {
    display: inline-block;
    margin-left: 6px;
    background: rgba(255, 255, 255, .16);
    color: #fff;
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    padding: 2px 7px;
    border-radius: var(--radius);
    vertical-align: middle;
}

/* ---------- Buttons ---------- */
.btn-mania {
    background: var(--navy);
    border: 1px solid var(--navy);
    color: #fff;
    font-family: var(--font-ui);
    font-weight: 600;
    letter-spacing: .2px;
    border-radius: var(--radius);
    padding: .6rem 1.3rem;
    transition: background .15s ease, box-shadow .15s ease, transform .1s ease;
}
.btn-mania:hover {
    background: #26426f;
    color: #fff;
    box-shadow: var(--shadow-card);
    transform: translateY(-1px);
}
.btn-mania:active { transform: translateY(0); }
.btn-mania:disabled { opacity: .55; }

/* ============================================================
   LOGIN — full-bleed navy stage with floating diamonds + confetti
   ============================================================ */
.mania-stage {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: radial-gradient(1200px 700px at 50% -10%, #2a4a80 0%, var(--navy) 45%, var(--navy-deep) 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

/* Floating diamond motif echoing the logo shape (sharp-edged) */
.mania-diamond {
    position: absolute;
    width: 120px; height: 120px;
    transform: rotate(45deg);
    border-radius: 2px;
    opacity: .08;
    background: #fff;
    animation: floatY 9s ease-in-out infinite;
}
.mania-diamond.d1 { top: 8%;  left: 10%; width: 90px;  height: 90px;  animation-delay: 0s; }
.mania-diamond.d2 { top: 60%; left: 6%;  width: 150px; height: 150px; opacity: .05; animation-delay: 1.5s; }
.mania-diamond.d3 { top: 15%; right: 9%; width: 130px; height: 130px; opacity: .06; animation-delay: .8s; }
.mania-diamond.d4 { bottom: 8%; right: 14%; width: 80px; height: 80px; animation-delay: 2.2s; }

@keyframes floatY {
    0%, 100% { transform: rotate(45deg) translateY(0); }
    50%      { transform: rotate(45deg) translateY(-24px); }
}

/* Confetti */
.confetti { position: absolute; top: -40px; width: 10px; height: 15px; opacity: .9; animation: fall linear infinite; }
@keyframes fall {
    0%   { transform: translateY(-40px) rotate(0deg); opacity: 0; }
    10%  { opacity: 1; }
    100% { transform: translateY(105vh) rotate(720deg); opacity: .9; }
}

/* Login card */
.mania-card {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 420px;
    background: #fff;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-pop);
    padding: 30px 30px 26px;
    border-top: 3px solid var(--blue-bright);
    animation: cardFade .35s ease both;
}
@keyframes cardFade { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.mania-logo {
    display: block;
    width: 220px;
    max-width: 80%;
    height: auto;
    margin: 0 auto 14px;
}

.mania-ribbon {
    display: inline-block;
    background: var(--navy);
    color: #fff;
    font-weight: 700;
    font-size: .68rem;
    letter-spacing: 2px;
    text-transform: uppercase;
    padding: 4px 12px;
    border-radius: var(--radius);
    margin: 0 auto 2px;
}
.mania-sub { text-align: center; color: var(--gray-mid); font-size: .88rem; margin-bottom: 22px; }
.mania-sub .est { color: var(--navy); font-weight: 700; }

.mania-card .form-label { font-weight: 600; color: var(--navy); font-size: .85rem; margin-bottom: .3rem; }
.mania-card .form-control {
    border-radius: var(--radius);
    border: 1px solid #d7dce6;
    padding: .6rem .85rem;
}
.mania-card .form-control:focus {
    border-color: var(--blue-bright);
    box-shadow: 0 0 0 .2rem rgba(110, 146, 206, .25);
}

.mania-tagline {
    text-align: center;
    margin-top: 20px;
    color: var(--navy);
    font-weight: 700;
    letter-spacing: 3px;
    font-size: .68rem;
    opacity: .5;
}

.mania-alt { text-align: center; margin-top: 16px; font-size: .88rem; color: var(--gray-mid); }
.mania-alt a { color: var(--navy); font-weight: 700; text-decoration: none; }
.mania-alt a:hover { text-decoration: underline; }

/* ============================================================
   DASHBOARD / CONTENT
   ============================================================ */
.mania-hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-md);
    padding: 26px 30px;
    margin-bottom: 24px;
    color: #fff;
    background: linear-gradient(105deg, var(--navy-deep) 0%, var(--navy) 60%, #274571 100%);
    border-bottom: 3px solid var(--blue-bright);
}
/* Sharp diamond accent, straight-edged.
   pointer-events:none is load-bearing, not tidiness: this sits in the top-right
   of the hero, which is exactly where the hero's action button goes (Import IDs,
   Export CSV, New prize...). As the last child it paints — and hit-tests — above
   that button, so without this the button only responds around its edges where
   the diamond tapers away. */
.mania-hero::after {
    content: "";
    position: absolute;
    right: -50px; top: -70px;
    width: 220px; height: 220px;
    background: #fff;
    opacity: .06;
    transform: rotate(45deg);
    pointer-events: none;
}
.mania-hero h1 {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -.3px;
    margin: 0;
    font-size: clamp(1.6rem, 3.6vw, 2.1rem);
    position: relative;
}
.mania-hero h1 .pop { color: var(--blue-pale); }
.mania-hero p { margin: 5px 0 0; opacity: .85; font-weight: 400; position: relative; }
.mania-hero .hero-emoji { font-size: 1.9rem; position: relative; }

/* ============================================================
   COUNTER REDEMPTION — the public page reps use behind a trade
   counter, usually on a phone. Shares the login stage, but must
   scroll: .mania-stage is fixed + overflow:hidden, which would
   cut off the result panel and the confirm button on a small
   screen.
   ============================================================ */
.mania-stage--counter {
    position: relative;
    inset: auto;
    min-height: 100vh;
    overflow-y: auto;
}

.counter-code {
    text-transform: uppercase;
    letter-spacing: .12em;
    font-weight: 700;
    font-size: 1.15rem;
    text-align: center;
}

.counter-result {
    margin-top: 20px;
    padding: 18px;
    border-radius: var(--radius-md);
    text-align: center;
}
.counter-result h2 { font-size: 1.05rem; font-weight: 800; margin: 6px 0 8px; }
.counter-result p { font-size: .9rem; }
.counter-result--good { background: #eaf6ee; border: 1px solid #b7e0c4; }
.counter-result--bad { background: #fdecec; border: 1px solid #f1c3c3; }
.counter-result--warn { background: #fff7e8; border: 1px solid #f0dcae; }
.counter-emoji { font-size: 2rem; line-height: 1; }

.counter-details {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 5px 12px;
    margin: 14px 0 0;
    text-align: left;
    font-size: .9rem;
}
.counter-details dt {
    align-self: center;
    text-transform: uppercase;
    letter-spacing: .8px;
    font-size: .66rem;
    font-weight: 700;
    color: var(--gray-mid);
}
.counter-details dd { margin: 0; }

/* The "you can't undo this" note, deliberately hard to skim past. */
.counter-warn {
    margin-top: 14px;
    padding: 9px 11px;
    background: #fff;
    border-left: 3px solid var(--blue-bright);
    text-align: left;
    font-size: .85rem;
}

/* Section label — crisp corporate divider */
.section-heading {
    font-family: var(--font-ui);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    color: var(--navy);
    font-size: .82rem;
    margin: 30px 0 14px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--line);
}

/* Tiles */
.mania-tile {
    height: 100%;
    border: 1px solid var(--line);
    border-top: 3px solid transparent;
    border-radius: var(--radius-md);
    background: #fff;
    box-shadow: var(--shadow-card);
    transition: transform .12s ease, box-shadow .12s ease, border-top-color .12s ease;
}
.mania-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-pop);
    border-top-color: var(--blue-bright);
}
.mania-tile .tile-icon {
    width: 48px; height: 48px;
    display: grid; place-items: center;
    border-radius: var(--radius);
    font-size: 1.5rem;
    background: #eef2fa;
    border: 1px solid var(--line);
    color: var(--navy);
    margin-bottom: 14px;
}
.mania-tile h2 { font-family: var(--font-ui); font-weight: 700; color: var(--navy); font-size: 1.1rem; }
.mania-tile p { color: var(--gray-mid); font-size: .9rem; }

.badge-soon {
    background: #eef2fa;
    color: var(--navy);
    border: 1px solid var(--line);
    font-weight: 600;
    letter-spacing: .4px;
    border-radius: var(--radius);
    padding: .25rem .6rem;
    font-size: .7rem;
    text-transform: uppercase;
}

/* Metric cards */
.metric-card {
    border: 1px solid var(--line);
    border-left: 3px solid var(--blue-bright);
    border-radius: var(--radius-md);
    background: #fff;
    box-shadow: var(--shadow-card);
}
.metric-card .metric-icon {
    font-size: 1.4rem;
    width: 42px; height: 42px;
    display: grid; place-items: center;
    border-radius: var(--radius);
    background: #eef2fa;
    border: 1px solid var(--line);
    margin-bottom: 12px;
}
.metric-card .metric-value {
    font-family: var(--font-ui);
    font-weight: 700;
    font-size: 2rem;
    line-height: 1;
    color: var(--navy);
    font-variant-numeric: tabular-nums;
}
.metric-card .metric-label {
    color: var(--gray-mid);
    font-weight: 600;
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .4px;
    margin-top: 6px;
}
.metric-card.metric-card--alert { border-left-color: #b0453a; }
.metric-card .metric-note { color: var(--gray-mid); font-size: .74rem; margin-top: 4px; }

.text-navy { color: var(--navy) !important; }

/* Tables */
.munch-table { border: 1px solid var(--line); }
.munch-table thead th {
    color: var(--navy);
    font-family: var(--font-ui);
    font-weight: 700;
    text-transform: uppercase;
    font-size: .74rem;
    letter-spacing: .4px;
    background: #f2f5fa;
    border-bottom: 2px solid var(--blue-bright);
    white-space: nowrap;
}
.munch-table tbody td { vertical-align: middle; }
.munch-table .table-warning { --bs-table-bg: #fbf3e2; }

/* Player play panel */
.play-panel {
    background: #fff;
    border: 1px solid var(--line);
    border-top: 3px solid var(--blue-bright);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 40px 28px;
    max-width: 620px;
    margin: 0 auto;
}
.play-panel .play-emoji { font-size: 2.8rem; }
.play-panel .play-title {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--navy);
    margin: 12px 0 8px;
}
.play-panel .play-text { color: var(--gray-mid); max-width: 46ch; margin: 0 auto 22px; }

/* ============================================================
   PLAY — scratch-off ticket + prize boards
   ============================================================ */

/* Scratches-left counter in the player hero */
.mania-hero .hero-count { position: relative; text-align: center; min-width: 110px; }
.mania-hero .hero-count-value {
    font-weight: 800;
    font-size: 2.6rem;
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
}
.mania-hero .hero-count-label {
    text-transform: uppercase;
    letter-spacing: 1px;
    font-size: .66rem;
    font-weight: 700;
    color: var(--blue-pale);
    margin-top: 4px;
}

.scratch-stage { max-width: 620px; margin: 0 auto 8px; }

.ticket {
    background: #fff;
    border: 1px solid var(--line);
    border-top: 3px solid var(--blue-bright);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

.ticket-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--navy);
    color: #fff;
}
.ticket-brand { font-weight: 800; letter-spacing: 2px; font-size: .74rem; }
.ticket-serial {
    font-weight: 700;
    letter-spacing: 1.4px;
    font-size: .66rem;
    color: var(--blue-pale);
    font-variant-numeric: tabular-nums;
}

/* ONE panel per ticket. Every ticket is either an instant win or a collect
   ticket, decided by the same roll that decides what it won — so there's a
   single foil and nothing on it hints at which kind you're holding. */
.ticket-panels {
    background: var(--line);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
}
.ticket-panel { background: #fff; }

/* The window holds the outcome; the foil canvas sits directly on top of it. */
.ticket-window {
    position: relative;
    min-height: 232px;
    display: grid;
    place-items: center;
    background: #f7f9fc;
}

.ticket-face {
    text-align: center;
    padding: 18px 14px;
    width: 100%;
}
.ticket-face .face-icon { font-size: 2.6rem; line-height: 1; }
.ticket-face .face-headline {
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--navy);
    margin-top: 8px;
    line-height: 1.25;
}
.ticket-face .face-detail {
    color: var(--gray-mid);
    font-size: .82rem;
    max-width: 30ch;
    margin: 6px auto 0;
}
.ticket-face .face-prize {
    margin-top: 10px;
    display: inline-block;
    background: var(--navy);
    color: #fff;
    font-weight: 700;
    font-size: .78rem;
    letter-spacing: .4px;
    padding: 5px 11px;
    border-radius: var(--radius);
}
/* A piece names the prize it belongs to — that isn't a win yet. */
.ticket-face .face-prize.is-muted {
    background: #eef2fa;
    color: var(--navy);
    border: 1px solid var(--line);
}
.ticket-face.is-win { background: linear-gradient(180deg, #fff 0%, #eef4ff 100%); }

.ticket-foil {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* You scratch a lottery ticket with a coin, so hand them one. 36px keeps the
       diamond readable while staying close to scratch.js's 30px rub, so the coin
       looks like it clears its own footprint. Hotspot is dead centre — the JS
       brush is centred on the pointer too.
       The plain url() line is the fallback; a browser that can't parse the
       image-set() line drops it and keeps this one. Crosshair remains the last
       resort if the image itself fails. */
    cursor: url('../images/scratch-coin.png') 18 18, crosshair;
    cursor: -webkit-image-set(url('../images/scratch-coin.png') 1x, url('../images/scratch-coin-2x.png') 2x) 18 18, crosshair;
    cursor: image-set(url('../images/scratch-coin.png') 1x, url('../images/scratch-coin-2x.png') 2x) 18 18, crosshair;
    /* Rubbing must not scroll the page on touch. */
    touch-action: none;
    transition: opacity .45s ease;
}
.ticket-foil.is-gone { opacity: 0; pointer-events: none; }

.ticket-foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 16px;
    background: #fff;
}
.ticket-foot .foot-label {
    text-transform: uppercase;
    letter-spacing: .8px;
    font-size: .68rem;
    font-weight: 700;
    color: var(--gray-mid);
}
.ticket-foot .foot-value {
    font-weight: 800;
    font-size: 1.15rem;
    color: var(--navy);
    font-variant-numeric: tabular-nums;
}

.scratch-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-top: 18px;
    flex-wrap: wrap;
}
.btn-reveal {
    background: none;
    border: none;
    color: var(--gray-mid);
    font-size: .84rem;
    font-weight: 600;
    text-decoration: underline;
    padding: .4rem .2rem;
}
.btn-reveal:hover { color: var(--navy); }

.scratch-status {
    text-align: center;
    color: var(--gray-mid);
    font-size: .88rem;
    min-height: 1.4em;
    margin: 12px 0 0;
}

/* Win burst — fixed layer reusing the login-stage confetti animation. */
.win-confetti {
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 1080;
}

/* ---------- prize boards ---------- */
.win-name {
    font-family: var(--font-ui);
    font-weight: 700;
    color: var(--navy);
    font-size: 1.02rem;
    margin: 0;
}
.win-value {
    font-weight: 700;
    color: var(--blue);
    font-size: .9rem;
    white-space: nowrap;
}
.win-desc { color: var(--gray-mid); font-size: .88rem; margin: 6px 0 0; }
.win-meta { color: var(--gray-mid); font-size: .76rem; margin-top: 10px; }
.win-card { border-left: 3px solid var(--blue-bright); }

.collect-progress {
    font-weight: 700;
    font-size: .78rem;
    color: var(--gray-mid);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.collect-board.is-won { border-top-color: #2e7d51; }

/* A settled tier — every winner it allows has been found. Recessive, never
   alarming: the dealer keeps their pieces and the board stays readable, it just
   stops competing for attention with the tiers still in play. */
.collect-board.is-closed {
    border-top-color: var(--gray);
    background: var(--gray-light);
}
.collect-board.is-closed .win-name { color: var(--gray-mid); }
.collect-board.is-closed .slot-row { opacity: .65; }

.board-closed {
    display: block;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--line);
}
.board-closed-title {
    display: block;
    font-weight: 700;
    font-size: .8rem;
    color: var(--navy);
}
.board-closed-text {
    display: block;
    color: var(--gray-mid);
    font-size: .76rem;
    margin-top: 2px;
}

/* "3 still open" beside the section heading — the count that actually helps. */
.boards-open {
    display: inline-block;
    vertical-align: middle;
    margin-left: 10px;
    background: var(--navy);
    color: #fff;
    font-weight: 700;
    font-size: .68rem;
    letter-spacing: .6px;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: var(--radius);
}
.boards-note {
    color: var(--gray-mid);
    font-size: .82rem;
    margin: -4px 0 12px;
}

/* Settled prizes fold away. The answer to "why has this stopped moving" is one
   click and the count is always visible, but nobody has to scroll past prizes
   they can no longer win to reach the ones they can. */
.settled-boards {
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    background: var(--gray-light);
    padding: 0 14px;
    margin-bottom: 18px;
}
.settled-boards[open] { padding-bottom: 12px; }
.settled-boards > summary {
    cursor: pointer;
    padding: 11px 2px;
    font-size: .86rem;
    font-weight: 600;
    color: var(--gray-mid);
    list-style: none;
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
}
.settled-boards > summary::-webkit-details-marker { display: none; }
.settled-boards > summary::before {
    content: "▸";
    color: var(--gray-mid);
    font-size: .8rem;
    transition: transform .15s ease;
}
.settled-boards[open] > summary::before { transform: rotate(90deg); }
.settled-boards > summary:hover { color: var(--navy); }
.settled-count {
    display: inline-block;
    min-width: 22px;
    text-align: center;
    background: var(--gray);
    color: var(--ink);
    font-weight: 800;
    font-size: .78rem;
    border-radius: var(--radius);
    padding: 1px 6px;
}
.settled-hint { font-weight: 400; color: var(--gray-mid); }

@media (prefers-reduced-motion: reduce) {
    .settled-boards > summary::before { transition: none; }
}

.slot-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }

/* One slot per piece in the set — filled ones show the piece, the rest stay
   blank. The board never says WHY a slot is empty. */
.prize-slot {
    position: relative;
    flex: 1 1 76px;
    min-width: 76px;
    max-width: 120px;
    text-align: center;
    padding: 10px 6px 8px;
    border: 1px dashed var(--line);
    border-radius: var(--radius);
    background: var(--gray-light);
    color: var(--gray-mid);
}
.prize-slot .slot-mark { font-size: 1.5rem; font-weight: 700; line-height: 1.2; }
.piece-icon { font-size: 1.15rem; }

/* Scratch log — hits read strongly, misses recede. */
.log-hit { font-weight: 600; color: var(--navy); }
.log-miss { color: var(--gray); }

/* Redemption codes — monospaced so they're easy to read out and compare. */
.code-cell {
    font-family: Consolas, "Courier New", monospace;
    font-weight: 700;
    letter-spacing: .5px;
    color: var(--navy);
    white-space: nowrap;
}
.redeem-code {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding: 8px 10px;
    background: #eef4ff;
    border: 1px dashed var(--blue-bright);
    border-radius: var(--radius);
}
.redeem-code .redeem-label {
    text-transform: uppercase;
    letter-spacing: .8px;
    font-size: .62rem;
    font-weight: 700;
    color: var(--gray-mid);
}
.redeem-code .redeem-value {
    font-family: Consolas, "Courier New", monospace;
    font-weight: 700;
    font-size: 1rem;
    color: var(--navy);
    letter-spacing: 1px;
}
.prize-slot .slot-label {
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .2px;
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.prize-slot .slot-count {
    position: absolute;
    top: 3px;
    right: 5px;
    font-size: .6rem;
    font-weight: 700;
    color: var(--blue);
}
.prize-slot.is-held {
    border-style: solid;
    border-color: var(--blue-bright);
    background: #eef4ff;
    color: var(--navy);
}

.grand-card { border-left: 3px solid var(--blue-pale); }
.entry-count {
    font-weight: 800;
    font-size: 1.9rem;
    line-height: 1;
    color: var(--navy);
    font-variant-numeric: tabular-nums;
}
.entry-label {
    text-transform: uppercase;
    letter-spacing: .6px;
    font-size: .62rem;
    font-weight: 700;
    color: var(--gray-mid);
    margin-top: 4px;
}

/* Footer */
.munch-footer {
    background: var(--navy-deep);
    color: rgba(255, 255, 255, .72);
    border-top: 3px solid var(--blue-bright);
    font-size: .82rem;
}
.munch-footer .tag { color: var(--blue-pale); font-weight: 700; letter-spacing: 2px; }

/* ---------- Odds manager (/Prizes/Odds) ----------
   All prizes share one roll, so the pool total is the number that matters.
   The summary sticks to the top of the viewport: you're editing rows far down
   the page and the total is the only way to know where you've landed. */
.odds-summary {
    position: sticky;
    top: 0;
    z-index: 20;
    background: #fff;
    border: 1px solid var(--line);
    border-top: 3px solid var(--blue-bright);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 16px 18px;
    margin-bottom: 22px;
}
.odds-summary.is-over { border-top-color: #b0453a; }

.odds-summary-figures {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
}
.odds-total {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 2.4rem;
    line-height: 1;
    color: var(--navy);
}
.odds-summary.is-over .odds-total { color: #b0453a; }

.odds-split { display: flex; gap: 26px; flex-wrap: wrap; }
.odds-split .metric-label {
    color: var(--gray-mid);
    font-weight: 600;
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .4px;
}
.odds-sub {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--navy);
    font-variant-numeric: tabular-nums;
}
.odds-key {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 5px;
    vertical-align: baseline;
}
.odds-key--instant { background: var(--navy); }
.odds-key--collect { background: var(--blue-bright); }
.odds-key--none { background: var(--gray); }

/* Stacked bar: instant | collect | no win. Over 100% it's drawn against the
   larger total, matching how the engine actually spreads the roll. */
.odds-bar {
    display: flex;
    height: 12px;
    margin-top: 14px;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--gray-light);
    border: 1px solid var(--line);
}
.odds-bar-seg { display: block; height: 100%; transition: width .15s ease; }
.odds-bar-seg--instant { background: var(--navy); }
.odds-bar-seg--collect { background: var(--blue-bright); }
.odds-bar-seg--none { background: var(--gray); }

.odds-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 14px;
}
.odds-dirty {
    color: #8a5a00;
    background: #fff6e5;
    border: 1px solid #f0dcb4;
    border-radius: var(--radius);
    font-size: .76rem;
    font-weight: 700;
    padding: 3px 9px;
    text-transform: uppercase;
    letter-spacing: .4px;
}

.odds-table .odds-col { width: 190px; }
.odds-input-wrap {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    justify-content: flex-end;
}
.odds-input {
    width: 120px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.odds-suffix { color: var(--gray-mid); font-weight: 700; font-size: .84rem; }

/* A prize that isn't in the roll — inactive, or a set with no live pieces.
   Its odds still edit, they just don't count toward anything yet. */
.odds-table .odds-row--out { background: var(--gray-light); }
.odds-table .odds-row--out td { color: var(--gray-mid); }

/* ---------- Odds projection (/Prizes/Odds) ----------
   The pool total says the odds are legal; this says what they'd pay out. */
.projection {
    background: #fff;
    border: 1px solid var(--line);
    border-top: 3px solid var(--blue-bright);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 22px 24px 24px;
    margin: 34px 0 24px;
}
.projection .section-heading { margin-top: 0; }

.proj-controls {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.proj-field { display: flex; flex-direction: column; gap: 4px; }
.proj-field > span {
    text-transform: uppercase;
    letter-spacing: .6px;
    font-size: .68rem;
    font-weight: 700;
    color: var(--gray-mid);
}
.proj-field input { width: 130px; text-align: right; font-variant-numeric: tabular-nums; }
.proj-times, .proj-equals {
    color: var(--gray-mid);
    font-weight: 700;
    padding-bottom: 7px;
}
.proj-total { display: flex; flex-direction: column; padding-bottom: 2px; }
.proj-total-value {
    font-weight: 800;
    font-size: 1.3rem;
    color: var(--navy);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.proj-total-label {
    text-transform: uppercase;
    letter-spacing: .6px;
    font-size: .66rem;
    font-weight: 700;
    color: var(--gray-mid);
}
.proj-hint { max-width: 68ch; margin-bottom: 4px; }
.proj-status { color: var(--gray-mid); font-size: .88rem; min-height: 1.3em; margin: 8px 0 0; }

.proj-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
    gap: 12px;
    margin: 14px 0 16px;
}
.proj-tile {
    border: 1px solid var(--line);
    border-left: 3px solid var(--blue-bright);
    border-radius: var(--radius);
    padding: 12px 14px;
    background: #fbfcfe;
}
.proj-tile--bad { border-left-color: #b0453a; background: #fdf6f5; }
.proj-tile-label {
    text-transform: uppercase;
    letter-spacing: .6px;
    font-size: .64rem;
    font-weight: 700;
    color: var(--gray-mid);
}
.proj-tile-value {
    font-weight: 800;
    font-size: 1.25rem;
    color: var(--navy);
    margin: 3px 0 3px;
    font-variant-numeric: tabular-nums;
}
.proj-tile--bad .proj-tile-value { color: #b0453a; }
.proj-tile-note { font-size: .78rem; color: var(--gray-mid); line-height: 1.45; }

.proj-flags { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.proj-flag {
    border-radius: var(--radius);
    padding: 9px 13px;
    font-size: .87rem;
    line-height: 1.5;
    border: 1px solid transparent;
}
.proj-flag--bad { background: #fdf1ef; border-color: #f0cdc6; color: #7d2f26; }
.proj-flag--warn { background: #fff6e5; border-color: #f0dcb4; color: #7a5310; }
.proj-flag strong { font-weight: 700; }

.projection td.num, .projection th.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.projection caption {
    caption-side: top;
    text-align: left;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-size: .68rem;
    font-weight: 700;
    color: var(--gray-mid);
    padding: 0 0 8px;
}
.projection tr.flag > td { background: #fdf7ec; }
.projection .proj-out { font-size: .8rem; color: var(--gray-mid); }
.proj-note {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .5px;
    font-weight: 700;
    color: #7d2f26;
    background: #fdf1ef;
    border-radius: 3px;
    padding: 1px 6px;
    white-space: nowrap;
}
.proj-foot { font-size: .78rem; color: var(--gray-mid); margin: 12px 0 0; }

@media (prefers-reduced-motion: reduce) {
    .mania-diamond, .confetti { animation: none !important; }
    .odds-bar-seg { transition: none; }
}
