/*
 * Components. Colors, spacing and type use only the variables from tokens.css (docs/design-system.md).
 */

/*
 * Logo typeface Cinzel 700 (Latin subset). files/cinzel-latin-700-normal.woff2 from npm @fontsource/cinzel 5.3.0,
 * copied as is: SIL OFL 1.1, public/fonts/cinzel/LICENSE. There is no build tool, so npm output is vendored (no CDN).
 */
@font-face {
    font-family: "Cinzel";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/cinzel/cinzel-latin-700-normal.woff2") format("woff2");
}

/*
 * UI typeface Inter (variable, weights 100-900 in one file per range). files/inter-latin(-ext)-wght-normal.woff2 from npm
 * @fontsource-variable/inter 5.3.0, copied by scripts/fonts (npm run vendor): SIL OFL 1.1, public/fonts/inter/LICENSE.
 * unicode-range as in the package, so the latin-ext file downloads only when a page uses those characters.
 */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/inter/inter-latin-wght-normal.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/inter/inter-latin-ext-wght-normal.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }
/* touch-action: manipulation stops double-tap zoom on phones (pinch zoom stays allowed; guard: ViewportZoomTest) */
html { color-scheme: dark; touch-action: manipulation; }
/* Han glyphs in the language of the page (the admin layout's <html lang> follows the operator's language). zh-Hant comes after zh so it wins at equal specificity */
html:lang(ja) { --font-sans: var(--font-sans-ja); }
html:lang(zh) { --font-sans: var(--font-sans-zh-hans); }
html:lang(zh-Hant), html:lang(zh-TW), html:lang(zh-HK), html:lang(zh-MO) { --font-sans: var(--font-sans-zh-hant); }
body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    background: var(--color-bg);
    color: var(--color-text);
}
/* Form controls do not inherit the page font by default (browsers use their own), so a control without .input/.btn would break the unified UI font (--font-sans) */
button, input, select, textarea { font-family: inherit; }
h1, h2, h3 { line-height: var(--leading-tight); margin: 0; }
h1 { font-size: var(--text-xl); font-weight: var(--weight-bold); }
h2 { font-size: var(--text-lg); font-weight: var(--weight-bold); }
h3 { font-size: var(--text-md); font-weight: var(--weight-medium); }
a { color: var(--color-accent); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
code { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-subtle); }
.muted { color: var(--color-text-muted); }
.subtle { color: var(--color-text-subtle); font-size: var(--text-sm); }

/* ---------- Layout ---------- */
.container { max-width: var(--content-max); margin: 0 auto; padding: var(--space-5) var(--space-4) var(--space-7); }
.page-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-5); flex-wrap: wrap; }
.stack > * + * { margin-top: var(--space-4); }

/* ---------- Footer (signed-in screens, copyright · Powered by) ---------- */
/* Keep the footer at the bottom of the viewport even when content is short. Applied only to screens with a footer, so the vertical centering of the login (bare) screen is untouched */
body:has(> .footer) { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
body:has(> .footer) > .container { flex: 1 0 auto; width: 100%; }
.footer {
    width: 100%;
    /* Copyright and Powered by sit together on the left instead of being split to both ends */
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-5);
    /* Same width and side padding as the top bar (.topbar): the border spans the full width and the text starts in line with the logo */
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--color-line);
    color: var(--color-text-subtle); font-size: var(--text-xs);
}
.footer p { margin: 0; }
/* Both names (copyright owner NEW BOSS, provider CNC/TOP) get the same emphasis */
.footer__owner, .footer__provider { color: var(--color-text-muted); font-weight: var(--weight-medium); }

/* ---------- Top bar ---------- */
.topbar {
    position: sticky; top: 0; z-index: 10;
    display: flex; align-items: center; gap: var(--space-5);
    min-height: var(--topbar-height);
    padding: 0 var(--space-5);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-line);
}
/* Logo: gold chip mark (public/images/logo-mark.svg, same file as the favicon) + name. The parent sets the size via --logo-size and font-size.
   The name is silver "new" + gold "boss" in Cinzel, like the animated login logo (gold is allowed because it is the logo; docs/design-system.md, direction section) */
.logo { display: inline-flex; align-items: center; gap: var(--space-2); line-height: 1; }
.logo__mark { width: var(--logo-size, 24px); height: var(--logo-size, 24px); flex: none; }
.logo__name { font-family: var(--font-display); font-weight: var(--weight-bold); letter-spacing: 0.04em; }
.logo__new { color: var(--color-text); }
.logo__boss {
    color: var(--color-accent);
    background: linear-gradient(180deg, var(--color-focus), var(--color-accent) 60%);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
/* ⚠️ display: flex is load-bearing: as a block, the inline-flex logo sits on a text line and the space under its baseline lifts the logo ~4px above the menu text (2026-09-26, guard TopbarBrandAlignmentTest) */
.topbar__brand { display: flex; font-size: var(--text-lg); color: var(--color-text); --logo-size: 26px; }
.topbar__brand:hover { text-decoration: none; }
/* Wide screens: .topbar__menu is display: contents, so its nav and account group (Account · Log out) become flex items of the bar. order produces logo · menu ··· balance · account
   (in the markup the balance precedes the menu because of the narrow-screen hamburger group) */
.topbar__menu { display: contents; }
.topbar__nav { display: flex; gap: var(--space-1); order: 1; }
.topbar__balance { order: 2; margin-left: auto; }
/* The bar's 24px gap separates logo · menu · right-hand group; between the language switcher and the account menu it looked like a hole next to
   the 4px between menu links (2026-09-27 user report), so the account group pulls back to the menu links' gap. Reset in the narrow panel below */
.topbar__account { order: 3; position: relative; display: flex; align-items: center; margin-left: calc(var(--space-1) - var(--space-5)); }
.topbar__logout { margin: 0; }
/* Account group (who is signed in · Account · Log out). Without JS it stays one row: avatar + username · Account · Log out */
.topbar__account-menu { display: flex; align-items: center; gap: var(--space-1); }
.topbar__identity { display: flex; align-items: center; gap: var(--space-2); margin: 0; padding: 0 var(--space-2); min-width: 0; }
.topbar__identity-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.topbar__identity-name { font-weight: var(--weight-medium); color: var(--color-text); overflow-wrap: anywhere; }
/* Initial of the username in a round badge. Neutral colors: gold stays reserved for the balance chip */
.avatar {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    width: 28px; height: 28px;
    border: 1px solid var(--color-line-strong); border-radius: var(--radius-pill);
    background: var(--color-surface-raised); color: var(--color-text);
    font-size: var(--text-xs); font-weight: var(--weight-bold); line-height: 1;
}
/* Username button that opens the dropdown. It is a topbar__link like every other top menu item, with the avatar pulled to the left edge.
   ⚠️ There is no global [hidden] rule and .topbar .topbar__link sets display, so the hidden state must be restated at this specificity */
.topbar .topbar__user { gap: var(--space-2); padding-left: var(--space-1); color: var(--color-text); }
.topbar .topbar__user[hidden] { display: none; }
.topbar .topbar__user[aria-expanded="true"] { background: var(--color-surface-raised); }
.topbar__username { max-width: 16ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar__caret { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; color: var(--color-text-muted); }
.topbar__user[aria-expanded="true"] .topbar__caret { transform: rotate(180deg); }
/* With JS (data-dropdown), the group collapses into a panel under the username button, right-aligned with the bar */
.topbar__account[data-dropdown] .topbar__account-menu {
    display: none;
    position: absolute; top: calc(100% + var(--space-2)); right: 0; z-index: 1;
    flex-direction: column; align-items: stretch; gap: 0;
    min-width: 220px; max-width: 320px; padding: var(--space-2);
    background: var(--color-surface);
    border: 1px solid var(--color-line); border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);
}
.topbar__account[data-dropdown].is-open .topbar__account-menu { display: flex; }
.topbar__account[data-dropdown] .topbar__identity { padding: var(--space-2) var(--space-3) var(--space-3); margin-bottom: var(--space-2); border-bottom: 1px solid var(--color-line); }
.topbar__account[data-dropdown] .topbar__identity-label { position: static; width: auto; height: auto; overflow: visible; clip: auto; display: block; font-size: var(--text-xs); color: var(--color-text-muted); }
.topbar__account[data-dropdown] .topbar__account-menu .topbar__link { width: 100%; justify-content: flex-start; }
/* One top menu item (left links · Account · Log out; also the admin login screen's language switcher in .locale-corner, which has no bar around it). Left and right must look the same: on 2026-09-26 only Account and Log out were btn--sm, so their text was smaller and Account showed an underline (guard ResponsiveLayoutTest).
   ⚠️ Log out is a <button>, so it carries the btn class. Scoped under .topbar so the later .btn size, weight and border do not win */
.topbar .topbar__link, .locale-corner .topbar__link {
    display: inline-flex; align-items: center;
    padding: var(--space-2) var(--space-3);
    border: 0; border-radius: var(--radius-sm);
    background: transparent; color: var(--color-text-muted);
    font: inherit; font-weight: var(--weight-regular); line-height: var(--leading-normal);
    /* Never wrap: a squeezed bar broke translated CJK items one character per line (Korean Games at 800px, 2026-09-27) */
    white-space: nowrap;
}
.topbar .topbar__link:hover, .locale-corner .topbar__link:hover { color: var(--color-text); background: var(--color-surface-raised); text-decoration: none; }
.topbar .topbar__link[aria-current="page"] { color: var(--color-text); background: var(--color-surface-raised); }
/* Hamburger button on narrow screens only; the script removes the hidden attribute. ⚠️ Scoped under .topbar to outrank the later .btn { display: inline-flex } */
.topbar .topbar__toggle { display: none; }
.topbar__toggle-icon { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.topbar__toggle-close, .topbar.is-open .topbar__toggle-open { display: none; }
.topbar.is-open .topbar__toggle-close { display: inline; }

/* Language switcher (<x-locale-menu>): a <details> dropdown in the player and admin top bars and in the admin login screen corner.
   In a bar it sits right after the balance chip (player) or takes its place (admin, admin.css): order 2 on wide screens, 1 on narrow ones.
   It matches the other top bar items (2026-09-27 user request - it used to be a smaller btn--sm with no sign that it opens):
   the toggle is a topbar__link with the account menu's caret, and the list is the account dropdown's raised panel */
.locale-menu { position: relative; }
.topbar .locale-menu { order: 2; }
.locale-menu > summary { list-style: none; gap: var(--space-2); }
.locale-menu > summary::-webkit-details-marker { display: none; }
.locale-menu[open] > .locale-menu__toggle { color: var(--color-text); background: var(--color-surface-raised); }
.locale-menu[open] .topbar__caret { transform: rotate(180deg); }
/* The toggle shows the language's own name, not a code (2026-09-27 user request). On small phones (≤400px, the same tier that hides
   the player balance chip label in app.css) the longest names (简体中文, 繁體中文, English) push the hamburger off the bar - measured
   at 361-374px, where the ≤360px logo shrink no longer applies - so there the toggle keeps only the flag; its aria-label still carries the name */
.locale-menu__name { font-weight: var(--weight-medium); white-space: nowrap; }
@media (max-width: 400px) { .locale-menu__toggle .locale-menu__name { display: none; } }
/* Player bar: the switcher sits next to the balance chip, and with the four menu links the wide bar ran out of room below 1024px
   (English overflowed from 641px up to 950px with a 12,345.67 balance, measured 2026-09-27), so there it keeps only the flag.
   The chip's Balance label goes to screen readers only in the same range (as on small phones, see the 400px rule below) to pay for the switcher -
   the English bar already overflowed at 641-810px before it. On small phones the switcher also drops the caret and becomes a 44px square like the hamburger */
@media (max-width: 1023px) {
    .topbar__balance + .locale-menu .locale-menu__name { display: none; }
    .topbar__balance .chip__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (max-width: 400px) {
    .topbar__balance + .locale-menu .topbar__caret { display: none; }
    .topbar .topbar__balance + .locale-menu .locale-menu__toggle { justify-content: center; min-width: var(--touch-target); padding: 0 var(--space-3); }
}
/* Flags are 4:3 SVGs (public/images/flags, vendored from flag-icons). The hairline keeps a white field visible on the dark bar */
.locale-menu__flag { flex: none; width: 20px; height: 15px; border-radius: 2px; box-shadow: 0 0 0 1px var(--color-line-strong); }
.locale-menu__items {
    position: absolute; top: calc(100% + var(--space-2)); right: 0; z-index: 20;
    display: flex; flex-direction: column; align-items: stretch; min-width: 180px; margin: 0;
    padding: var(--space-2); background: var(--color-surface);
    border: 1px solid var(--color-line); border-radius: var(--radius-md); box-shadow: var(--shadow-2);
}
.locale-menu__items .topbar__link { gap: var(--space-3); width: 100%; justify-content: flex-start; }
.locale-menu__items .topbar__link[aria-current="true"] { color: var(--color-text); background: var(--color-surface-raised); font-weight: var(--weight-medium); }
/* Admin login screen (bare layout, no top bar; the player login screen has no switcher): the switcher sits alone in the top right corner */
.locale-corner { position: absolute; top: var(--space-3); right: var(--space-4); z-index: 20; }

/* Balance chip: the most important number on the site. Gold only here and on primary buttons */
.chip {
    display: inline-flex; align-items: baseline; gap: var(--space-2);
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-accent);
    border-radius: var(--radius-pill);
    background: var(--color-accent-surface);
}
.chip__label { font-size: var(--text-xs); color: var(--color-text-muted); }
.chip__value { font-weight: var(--weight-bold); color: var(--color-accent); font-variant-numeric: tabular-nums; }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border: 1px solid transparent; border-radius: var(--radius-sm);
    font: inherit; font-size: var(--text-sm); font-weight: var(--weight-medium);
    line-height: var(--leading-tight);
    cursor: pointer;
}
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn--primary { background: var(--color-accent); color: var(--color-accent-ink); font-weight: var(--weight-bold); }
.btn--primary:hover:not(:disabled) { background: var(--color-accent-hover); }
.btn--secondary { background: var(--color-surface-raised); color: var(--color-text); border-color: var(--color-line-strong); }
.btn--secondary:hover:not(:disabled) { border-color: var(--color-text-subtle); }
.btn--ghost { background: transparent; color: var(--color-text-muted); }
.btn--ghost:hover:not(:disabled) { color: var(--color-text); background: var(--color-surface-raised); }
.btn--sm { padding: var(--space-1) var(--space-3); font-size: var(--text-xs); }
.btn--lg { padding: var(--space-3) var(--space-5); font-size: var(--text-md); }
.btn--block { width: 100%; }

/* ---------- Cards ---------- */
.card { background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-md); padding: var(--space-5); }

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: var(--space-1); }
.field__label { font-size: var(--text-sm); color: var(--color-text-muted); }
.input {
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-line-strong); border-radius: var(--radius-sm);
    background: var(--color-bg); color: var(--color-text);
    font: inherit; font-size: var(--text-sm);
}
.input:focus-visible { border-color: var(--color-focus); }
.input[aria-invalid="true"] { border-color: var(--color-negative); }
/* Secondary button inside the right edge of an input (show password, etc.) */
.input-group { position: relative; display: flex; }
.input-group .input { flex: 1; min-width: 0; padding-right: 72px; }
/* Fills the input height so the whole strip is tappable, not just the 25px btn--sm (login Show) */
.input-group .btn { position: absolute; right: var(--space-1); top: var(--space-1); bottom: var(--space-1); }

/* ---------- Alerts ---------- */
.alert { padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); border: 1px solid; font-size: var(--text-sm); }
.alert--error { background: var(--color-negative-surface); border-color: var(--color-negative); color: var(--color-text); }
.alert--notice { background: var(--color-warning-surface); border-color: var(--color-warning); color: var(--color-text); }
/* Flash alert the layout prints at the top of main */
.container > .alert { margin-bottom: var(--space-4); }
.alert--info { background: var(--color-info-surface); border-color: var(--color-info); color: var(--color-text); }

/* ---------- Wallet (self-service deposit/withdraw) ---------- */
.wallet { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-4); }
.wallet__balance { display: flex; flex-direction: column; gap: var(--space-2); }
.wallet__amount { font-size: var(--text-xl); font-variant-numeric: tabular-nums; }
.wallet__form { display: flex; flex-direction: column; gap: var(--space-4); }
.wallet-history { display: flex; flex-direction: column; gap: var(--space-3); }
.wallet-history__title { font-size: var(--text-md); }

/* ---------- Account (details · password change) ---------- */
.account { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-4); align-items: start; max-width: 880px; }
.account__profile, .account__form { display: flex; flex-direction: column; gap: var(--space-4); }
.account__form .alert { margin: 0; }
.account__details { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-3) var(--space-5); margin: 0; }
.account__details dt { font-size: var(--text-sm); color: var(--color-text-muted); }
.account__details dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

/* ---------- Tabs (game vendors) ---------- */
.tabs { display: flex; gap: var(--space-2); overflow-x: auto; padding-bottom: var(--space-2); margin-bottom: var(--space-4); scrollbar-width: thin; }
.tabs a {
    flex: none; padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-line); border-radius: var(--radius-pill);
    color: var(--color-text-muted); font-size: var(--text-sm); white-space: nowrap;
}
.tabs a:hover { color: var(--color-text); border-color: var(--color-line-strong); text-decoration: none; }
.tabs a[aria-current="page"] { color: var(--color-text); border-color: var(--color-text); background: var(--color-surface-raised); }

/* ---------- Filters ---------- */
.filters { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; margin-bottom: var(--space-5); }
.filters .input[type="search"] { min-width: 220px; }

/* ---------- Game cards ---------- */
.game-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: var(--space-4); }
.game {
    display: flex; flex-direction: column; gap: var(--space-2);
    padding: var(--space-3);
    background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-md);
}
.game:hover { border-color: var(--color-line-strong); }
.game__art { width: 100%; aspect-ratio: 1; border-radius: var(--radius-sm); object-fit: cover; background: var(--color-surface-raised); }
.game__name { font-size: var(--text-sm); font-weight: var(--weight-medium); }
.game__meta { font-size: var(--text-xs); color: var(--color-text-subtle); margin-top: calc(var(--space-1) * -1); }
.game .btn { margin-top: auto; }
/* Recently played row above the vendor tabs; separated from the catalog below by a hairline */
.recent-games { margin-bottom: var(--space-6); padding-bottom: var(--space-6); border-bottom: 1px solid var(--color-line); }
.recent-games__title { font-size: var(--text-md); margin-bottom: var(--space-3); }

/* ---------- Tables ---------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--color-line); border-radius: var(--radius-md); }
.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table th { text-align: left; font-weight: var(--weight-medium); color: var(--color-text-muted); background: var(--color-surface); }
.table th, .table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-line); white-space: nowrap; vertical-align: top; }
.table tbody tr:last-child td { border-bottom: 0; }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table tr.is-muted td { color: var(--color-text-subtle); }
.table .empty { text-align: center; padding: var(--space-7) var(--space-4); color: var(--color-text-muted); }
/* Game cell on Bets/Transactions: catalog thumbnail (<x-game-thumb>) next to the name. Fixed size so rows line up whether or not a game has an icon */
.game-cell { display: flex; align-items: center; gap: var(--space-3); }
.game-thumb { flex: none; width: 40px; height: 40px; border-radius: var(--radius-sm); object-fit: cover; background: var(--color-surface-raised); }
.game-thumb--empty { display: inline-block; border: 1px dashed var(--color-line); }
/* Non-game rows (deposit, withdrawal, adjustment) on Transactions: an invisible slot of the same size so the text lines up with game rows without looking like a missing game icon */
.game-thumb--blank { display: inline-block; background: none; }
/* Canceled/rejected rows dim their text; dim the thumbnail with them so the row reads as one */
.table tr.is-muted .game-thumb { opacity: 0.5; }
/* Totals row (tfoot): set off from the body rows by a heavier top rule */
.table tfoot th, .table tfoot td { font-weight: var(--weight-bold); color: var(--color-text); background: var(--color-surface); border-top: 2px solid var(--color-line); border-bottom: 0; }
/* Table value with no length limit (<x-clip>): names, codes, usernames, reasons, vendor IDs. Cells never wrap here, so one long value pushed the other columns off the screen; cut it to one line, the full value is in the title tooltip */
.clip { display: inline-block; max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
/* Text decoration does not reach inline-block children, so links around a clipped value lost their hover underline */
a:hover .clip { text-decoration: underline; }

/* ---------- Pagination (resources/views/pagination.blade.php) ---------- */
.pager { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-4); }
.pager .btn { min-width: 88px; }
.pager .btn:hover { text-decoration: none; }
.pager [aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }

/* ---------- Amounts: sign and direction color ---------- */
.amount { font-variant-numeric: tabular-nums; font-weight: var(--weight-medium); }
.amount--pos { color: var(--color-positive); }
.amount--neg { color: var(--color-negative); }
.amount--zero { color: var(--color-text-subtle); }

/* ---------- Badges ---------- */
.badge {
    display: inline-block; padding: 0 var(--space-2);
    border-radius: var(--radius-pill); border: 1px solid var(--color-line-strong);
    font-size: var(--text-xs); line-height: 20px; color: var(--color-text-muted); white-space: nowrap;
}
.badge--bet { color: var(--color-text); }
.badge--win { color: var(--color-positive); border-color: var(--color-positive); background: var(--color-positive-surface); }
.badge--cancel { color: var(--color-info); border-color: var(--color-info); background: var(--color-info-surface); }
.badge--other { color: var(--color-warning); border-color: var(--color-warning); background: var(--color-warning-surface); }
/* Self-service deposit/withdraw: the amount column color shows the direction of money, so the badge is neutral */
.badge--wallet { color: var(--color-text); border-style: dashed; }
.badge--status-canceled { color: var(--color-text-subtle); }
.badge--status-rejected { color: var(--color-negative); border-color: var(--color-negative); background: var(--color-negative-surface); }
/* Bet result: the net column color shows the direction of money, so Won/Lost do not use green/red */
.badge--result-won { color: var(--color-text); }
.badge--result-lost { color: var(--color-text-muted); }
.badge--result-open { color: var(--color-text-subtle); border-style: dashed; }
.badge--result-canceled { color: var(--color-info); border-color: var(--color-info); background: var(--color-info-surface); }
.badge--result-rejected { color: var(--color-negative); border-color: var(--color-negative); background: var(--color-negative-surface); }
.badge--mock { color: var(--color-negative); border-color: var(--color-negative); font-weight: var(--weight-bold); }

/* ---------- Login (bare screen without top bar) ---------- */
.container--bare {
    min-height: 100vh; min-height: 100dvh;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-4);
    padding-top: var(--space-7);
}
.auth { width: 100%; max-width: 400px; display: flex; flex-direction: column; }
.auth__brand { display: flex; justify-content: center; margin-bottom: var(--space-5); }
/* The animated logo GIF is 2x resolution (624×224), so render it at 312px and scale proportionally on narrow screens */
.auth__logo { display: block; width: 100%; max-width: 312px; height: auto; }
/*
 * Login card: a double border like the chip rim (outer line + inner 1px band), with the top one step lighter so it reads as a base under the logo.
 * ⚠️ Do not touch the background outside the card (around the logo): the logo GIF has --color-bg baked in, so a different background exposes a box.
 */
.auth__card, .error-page__card {
    position: relative;
    padding: var(--space-6);
    border-color: var(--color-line-strong);
    border-radius: var(--radius-lg);
    background: linear-gradient(180deg, var(--color-surface-raised), var(--color-surface) 38%);
    box-shadow: inset 0 0 0 4px var(--color-surface), inset 0 0 0 5px var(--color-line), var(--shadow-2);
}
.auth__form { display: flex; flex-direction: column; gap: var(--space-4); }
.auth__form h1 {
    margin-bottom: var(--space-1);
    font-family: var(--font-display); font-weight: var(--weight-bold); letter-spacing: 0.06em; text-align: center;
}
.auth__form .alert { margin: 0; }
.auth__form .input {
    padding-block: var(--space-3); font-size: var(--text-md);
    border-radius: var(--radius-md);
    transition: border-color 0.15s, box-shadow 0.15s;
}
.auth__form .input:hover { border-color: var(--color-text-subtle); }
/* Focus: keep the shared outline (--color-focus) but overlap it onto the border (-1px) so it shows as one ring instead of a double border, with a faint gold glow outside */
.auth__form .input:focus-visible { outline-offset: -1px; border-color: var(--color-focus); box-shadow: 0 0 0 5px var(--color-accent-surface); }
.auth__form .input[aria-invalid="true"] { border-color: var(--color-negative); }
.auth__form .input[aria-invalid="true"]:focus-visible { outline-color: var(--color-negative); box-shadow: 0 0 0 5px var(--color-negative-surface); }
/* Log in button: metallic gold lighter at the top like the logo lettering, drops one step when pressed. On hover the logo light streak sweeps across once */
.auth__form .btn--primary {
    position: relative; overflow: hidden;
    margin-top: var(--space-2); padding-block: var(--space-4);
    border-radius: var(--radius-md);
    background: linear-gradient(180deg, var(--color-accent-hover), var(--color-accent) 55%);
    box-shadow: inset 0 1px 0 var(--color-focus), var(--shadow-1);
    letter-spacing: 0.02em;
}
.auth__form .btn--primary:hover:not(:disabled) { background: linear-gradient(180deg, var(--color-focus), var(--color-accent-hover) 55%); }
.auth__form .btn--primary:active:not(:disabled) { transform: translateY(1px); box-shadow: inset 0 1px 0 var(--color-accent); }
.auth__form .btn--primary::after {
    content: ""; position: absolute; inset: 0 auto 0 -40%; width: 30%;
    background: linear-gradient(90deg, transparent, var(--color-text), transparent);
    opacity: 0.5; transform: skewX(-20deg); pointer-events: none;
}
.auth__form .btn--primary:hover:not(:disabled)::after { left: 120%; transition: left 0.6s ease-out; }
@media (prefers-reduced-motion: reduce) {
    .auth__form .btn--primary::after { display: none; }
    .auth__form .input { transition: none; }
}
.auth__demo {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap;
    margin-top: var(--space-4); padding: var(--space-3) var(--space-4);
    border: 1px dashed var(--color-line-strong); border-radius: var(--radius-lg);
}
.auth__demo p { margin: 0; }
@media (max-width: 640px) {
    .container--bare { justify-content: flex-start; padding-top: var(--space-7); }
    .auth__card, .error-page__card { padding: var(--space-5); }
}

/* ---------- Error pages (resources/views/errors, bare screen like login) ---------- */
/* Quiet on purpose: the status code is a small neutral label, not a big number, and gold stays on the one way out (the primary button) */
.error-page { width: 100%; max-width: 440px; display: flex; flex-direction: column; align-items: center; gap: var(--space-5); }
/* display: flex keeps the inline-flex logo off the text baseline (same reason as .topbar__brand) */
.error-page__brand { display: flex; --logo-size: 40px; font-size: var(--text-xl); color: var(--color-text); }
.error-page__card { width: 100%; display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center; }
.error-page__code {
    margin: 0; padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-line-strong); border-radius: var(--radius-pill);
    color: var(--color-text-muted); font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em;
}
.error-page__card h1 { margin-top: var(--space-2); }
.error-page__message { margin: 0; color: var(--color-text-muted); }
.error-page__detail { margin: 0; color: var(--color-text); font-weight: var(--weight-medium); }
.error-page__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); margin-top: var(--space-3); }
/* There is no global [hidden] rule and .btn sets display, so the Go back button (hidden until the script finds history) needs this */
.error-page__actions .btn[hidden] { display: none; }
@media (max-width: 640px) {
    .error-page__actions { flex-direction: column; align-self: stretch; }
}

/* ---------- Mock CNC screens (playing the external vendor) ---------- */
.mock-game { max-width: 820px; margin: 0 auto; padding: var(--space-5) var(--space-4) var(--space-7); }
.mock-game__head { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-5); }
.mock-game__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-5); }
.mock-game pre {
    margin: 0; padding: var(--space-3);
    background: var(--color-bg); border: 1px solid var(--color-line); border-radius: var(--radius-sm);
    overflow: auto; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-muted);
}
.mock-game details { margin-bottom: var(--space-3); }
.mock-game summary { cursor: pointer; font-size: var(--text-sm); padding: var(--space-1) 0; }

/* ---------- Narrow screens ---------- */
@media (max-width: 640px) {
    .container { padding: var(--space-4) var(--space-4) var(--space-6); }
    .page-head { margin-bottom: var(--space-4); gap: var(--space-1) var(--space-4); }

    /* Top bar: logo ··· balance chip · hamburger. The menu (#topbar-menu) is a panel that opens below the bar */
    .topbar { gap: var(--space-3); padding: 0 var(--space-2) 0 var(--space-4); min-height: var(--topbar-height-sm); }
    /* Match the narrow top bar's left padding (its right side is tighter only because of the hamburger, so the footer uses the same on both sides) */
    .footer { padding: var(--space-4); }
    .topbar__brand { font-size: var(--text-md); --logo-size: 24px; }
    /* Order: logo ··· balance · hamburger. Re-set the wide-screen order (balance 2) here */
    .topbar__balance { order: 1; }
    .topbar__toggle:not([hidden]) { order: 2; display: inline-flex; width: var(--touch-target); height: var(--touch-target); padding: 0; color: var(--color-text); }
    .topbar__menu {
        display: flex; flex-direction: column;
        position: absolute; top: 100%; left: 0; right: 0;
        padding: var(--space-2) var(--space-4) var(--space-4);
        background: var(--color-surface);
        border-bottom: 1px solid var(--color-line);
        box-shadow: var(--shadow-2);
    }
    /* Collapse only when the script has added data-collapsible; without JS the menu stays expanded on the row below the bar */
    .topbar:not([data-collapsible]) { flex-wrap: wrap; padding-bottom: var(--space-2); }
    .topbar:not([data-collapsible]) .topbar__menu { order: 3; position: static; width: 100%; padding: 0; box-shadow: none; border: 0; }
    .topbar[data-collapsible]:not(.is-open) .topbar__menu { display: none; }
    .topbar__nav { flex-direction: column; gap: 0; }
    .topbar__account { flex-direction: column; align-items: stretch; gap: 0; margin-left: 0; margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--color-line); }
    /* No dropdown inside the hamburger panel: hide the username button and lay the group out open (identity row, then Account · Log out).
       Same on the admin bar, which uses the same panel (<x-topbar-menu>).
       ⚠️ Every selector here must outrank its [data-dropdown] counterpart above, otherwise the panel keeps the dropdown look */
    .topbar .topbar__menu .topbar__user { display: none; }
    .topbar__menu .topbar__account .topbar__account-menu { display: flex; position: static; flex-direction: column; align-items: stretch; gap: 0; min-width: 0; max-width: none; padding: 0; border: 0; border-radius: 0; box-shadow: none; background: none; }
    .topbar__menu .topbar__account .topbar__identity { min-height: var(--touch-target); padding: 0 var(--space-3); margin: 0; border: 0; }
    .topbar__menu .topbar__account .topbar__identity-label { position: static; width: auto; height: auto; overflow: visible; clip: auto; display: block; font-size: var(--text-xs); color: var(--color-text-muted); }
    .topbar .topbar__link { display: flex; width: 100%; justify-content: flex-start; min-height: var(--touch-target); padding: 0 var(--space-3); }
    /* Language switcher: stays in the bar like the balance chip (logo ··· balance · language · hamburger). The line above stretches every
       top bar link to the panel width; the toggle is not in the panel, so it keeps its own width */
    .topbar .locale-menu { order: 1; }
    .topbar .locale-menu__toggle { width: auto; min-height: var(--touch-target); }

    /* iOS Safari zooms in when an input under 16px gets focus. ⚠️ The login .auth__form .input (15px) has higher specificity and must be listed separately to be overridden */
    .input, .auth__form .input { font-size: var(--text-input-touch); }
    .pager .btn { min-height: var(--touch-target); }
    /* Search boxes take a full row; selects and dates go two per row so their text stays readable
       (flex: 1 squeezed all six game-list selects onto one row and only the arrows were left). The button, Clear and the count share the last row */
    .filters .input[type="search"] { flex: 1 1 100%; min-width: 0; }
    .filters select.input, .filters .input[type="date"] { flex: 1 1 calc(50% - var(--space-2)); min-width: 0; }
    .filters > .subtle { margin-left: auto; }
    /* Same height for every control: date inputs were taller than selects and the button shorter, so paired rows looked uneven */
    .filters .input, .filters .btn { min-height: var(--touch-target); }

    .game-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: var(--space-3); }
    /* One swipeable row instead of three stacked rows, so the vendor tabs stay near the top of the screen */
    .recent-games .game-grid { grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: 132px; overflow-x: auto; overscroll-behavior-x: contain; padding-bottom: var(--space-1); }
    .recent-games { margin-bottom: var(--space-5); padding-bottom: var(--space-5); }

    /* Table → cards: one row per card, each cell prefixed with its data-label (column header) on the left */
    .table--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .table--cards, .table--cards tbody, .table--cards tr, .table--cards td { display: block; }
    .table--cards tr { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-line); }
    .table--cards tbody tr:last-child { border-bottom: 0; }
    .table--cards td {
        position: relative;
        padding: var(--space-1) 0 var(--space-1) var(--card-label-width);
        border: 0; text-align: right; white-space: normal; overflow-wrap: anywhere;
    }
    .table--cards td::before {
        content: attr(data-label);
        position: absolute; left: 0; top: var(--space-1);
        color: var(--color-text-muted); text-align: left;
    }
    .table--cards td:empty { display: none; }
    .table--cards td.empty { padding: var(--space-6) 0; text-align: center; }
    /* Cells are right-aligned in card mode; keep the thumbnail next to the right-aligned name */
    .table--cards .game-cell { justify-content: flex-end; }
    /* Values are right-aligned here, so rows never need to line up; the invisible non-game slot would only take room from the text */
    .table--cards .game-thumb--blank { display: none; }
    /* Cards have room to wrap, so show the whole value */
    .table--cards .clip { max-width: none; white-space: normal; overflow-wrap: anywhere; }
    /* Row actions (Manage, Turn off, Stats) are btn--sm, 25px tall — too small for a finger */
    .table--cards .btn { min-height: var(--touch-target); }
    .table--cards tfoot, .table--cards tfoot th { display: block; }
    .table--cards tfoot tr { border-top: 2px solid var(--color-line); border-bottom: 0; }
    .table--cards tfoot th, .table--cards tfoot td { border-top: 0; background: none; }
    /* The row already has the card padding; the table cell padding indented "Total" a second time */
    .table--cards tfoot th { padding: var(--space-1) 0; }
}

/* Small phones (≤400px): keep the chip label for screen readers only so a ten-digit balance (1,234,567,890) does not push the hamburger out (measured at 375px, 2026-09-26) */
@media (max-width: 400px) {
    .topbar__balance .chip__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* 320px class: shrink the logo text and bar spacing one step */
@media (max-width: 360px) {
    .topbar { gap: var(--space-2); }
    .topbar__brand { font-size: var(--text-sm); --logo-size: 22px; }
}

@media (prefers-reduced-motion: reduce) {
    * { scroll-behavior: auto !important; transition: none !important; }
}
