/* chrome/base.css — общий хром всех игр, FIRST sheet of the cascade (ported from design
   prototype tapium_field.html): :root tokens + skin overrides, preloader, conn/error
   banners, notif stack. :root = палитра хрома ПО УМОЛЧАНИЮ — её берут как есть arrow
   (tapium), nearmiss, slotmiss, tetroglass и boot без data-skin; скины переопределяют
   только своё в :root[data-skin]. The rest of the chrome lives in the sibling chrome/*.css sheets
   (order = <link> list in index.html). The field is rendered by Pixi (see themes/tapium.js
   — same tokens for the canvas). */

:root {
    --bg:          #FFFFFF;
    --accent:      #FF37C7;            /* base fill for others' bets */
    --coef-ink:    rgba(0, 0, 0, 0.70);
    --heat-ink:    #DC009F;
    --hairline:    rgba(26, 16, 22, 0.07);
    --hover-fill:  var(--pink);
    --hover-ink:   #5C0430;
    --bet-fill:    #00E114;
    --bet-coef-ink: #004A00;
    --bet-amt-ink:  rgba(0, 74, 0, 0.50);
    --ease:        cubic-bezier(0.4, 0, 0.2, 1);
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

    /* ---- Modal framework tokens (single source of truth) ---- */
    /* Фирменный розовый tapium — НЕ переопределяется темами (пинг-пилюля — вне тем). */
    --brand-pink:     #FF0080;
    --brand-pink-rgb: 255, 0, 128;
    --pink:        var(--brand-pink);  /* акцент хрома; темы переопределяют */
    --pink-rgb:    var(--brand-pink-rgb); /* = --pink, for rgba() */
    --accent-rgb:  255, 55, 199;       /* = --accent, for rgba() */
    --ink:         #16161A;
    --label:       #8A8A90;
    --label-2:     #9A9AA0;
    --label-3:     #6E6E76;
    --ok:          #0AA33A;
    --ok-2:        #1CB06C;
    --danger:      #FF3B5C;
    --pf-unknown:  #8A8F98;            /* PF-карточка: вердикт ставки неизвестен («?») — не сливать с --label */
    --pf-unknown-bg: rgba(138,143,152,.08); /* заливка клетки «?» — --pf-unknown (#8A8F98) полупрозрачный */
    --surface:     #F6F6F7;
    --surface-btn: #F3F3F4;
    --surface-press:#E9E9EB;
    --placeholder: #C2C2C8;
    --scrim:       rgba(12, 8, 14, 0.40);
    --r-modal:     28px;
    --r-field:     14px;
    --r-chip:      12px;
    --r-copy:      10px;
    --r-cta:       23px;
    --shadow-modal:0 12px 32px 4px rgba(0, 0, 0, 0.12);
    --blur-scrim:  7px;
    --blur-glass:  20px;

    /* ---- Краевые полосы-градиенты #topfade/#sysbar (цвет «дымки» у края экрана) ----
       Дефолт — белая дымка tapium/snowboarder (белое поле). Тема с тёмным полем
       переопределяет в :root[data-skin] (роль domEdgeFade палитры темы) и подкладывает
       под полупрозрачную пилюлю баланса сплошную --sys-chip (иначе серый текст тонет
       в тёмной полосе). Пинг-пилюля — вне тем, всегда как в tapium. */
    --edge-fade-rgb:   255, 255, 255;
    --edge-fade-top-a: 0.82;
    --edge-fade-bot-a: 0.88;
    --sys-chip:        #E5E5E9;       /* заливка пилюль MENU/звук */
    --sys-chip-under:  transparent;   /* подложка под пилюлей баланса (пинг — вне тем) */
    --inset:       14px;
    --pad-modal:   10px;
    --ff-head:     'Inter', sans-serif;
    --ff-body:     'Inter', sans-serif;
    --fs-label:    11px;
    --fs-body:     12px;
    --fs-value:    15px;
    --fs-title:    18px;
    /* INK BLEED — запас под чернила глифов, выходящие за строку: стековые
       вьетнамские диакритики заглавных (Ấ Ặ Ệ Ổ Ợ, точка снизу Ị Ụ), матры
       деванагари, тайские тональные знаки над гласными (ั้), кириллическая Й.
       Замерено (canvas actualBoundingBox vs clip-бокс, 18px): th до 5px сверху
       = 0.28em, vi ~3px сверху / 2px снизу. Применение — ТОЛЬКО парой
       `padding-block: var(--ink-bleed); margin-block: calc(-1 * var(--ink-bleed));`
       на элементе с overflow:hidden (ради ellipsis): clip-бокс = padding-box
       растёт, а внешний размер (вёрстка) не меняется ни на пиксель. */
    --ink-bleed:   0.3em;

    /* Z-INDEX SCALE (--z-*) — layers.css. */
}

/* Visually hidden, still read by screen readers (money owners' «Balance: …» label —
   TapiumUI.amountOwner). position:absolute keeps it out of every flex/FitText budget. */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Переопределения скинов — styles/skins/<скин>.css (CSS-модули скинов). */

/* ===== PRELOADER (id contract: loading-screen / loading-bar / loading-percent) */
#loading-screen {
    position: fixed; inset: 0; z-index: var(--z-preloader); background: #FFFFFF;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    /* .25s (was .4s): the fade is the LAST thing before the field is visible —
       it starts only after the (already-late) first ktable, so a shorter fade
       directly shaves perceived time-to-playable without a jarring cut. */
    opacity: 1; transition: opacity .25s ease;
}
/* After the fade completes, take the loader fully OUT of paint via a delayed
   visibility:hidden (transitioned at 0s, i.e. only after the .25s opacity fade).
   opacity:0 alone leaves this position:fixed;z-index:9999 layer in the compositor,
   where iOS Safari can ghost-repaint it (dynamic address-bar viewport shifts /
   bfcache restore / GPU re-raster) — its absolutely-positioned "POWERED BY WINJOY"
   footer then flashes over the game field. visibility:hidden elements are not
   painted at all, so the branding can only ever show on the loader, never in-game. */
#loading-screen.fade-out {
    opacity: 0; pointer-events: none; visibility: hidden;
    transition: opacity .25s ease, visibility 0s linear .25s;
}
#loading-screen .pl-center { position: relative; display: flex; flex-direction: column; align-items: center; gap: 26px; }
#loading-screen .pl-logo { width: min(190px, 48vw); line-height: 0; }
#loading-screen .pl-logo img, #loading-screen .pl-logo svg { width: 100%; height: auto; display: block; }
/* snowboarder: размер лого загрузки — в критическом inline-CSS index.html (SSoT). */
#loading-screen .pl-bar { width: min(150px, 42vw); height: 3px; border-radius: 3px; background: #ECECEF; overflow: hidden; }
#loading-screen .pl-bar-fill { width: 0%; height: 100%; border-radius: 3px; background: var(--pink); transition: width .4s var(--ease); }
#loading-screen .pl-foot { position: absolute; left: 0; right: 0; bottom: 30px; display: flex; flex-direction: column; align-items: center; gap: 7px; }
#loading-screen .pl-powered {
    font-family: 'Inter', sans-serif; font-size: 9px; font-weight: 600; letter-spacing: .16em;
    color: var(--placeholder); text-transform: uppercase;
}
#loading-screen .pl-co { width: 140px; line-height: 0; opacity: .9; }
#loading-screen .pl-co svg { width: 100%; height: auto; display: block; }
/* Long-load status (watchdog): shown if ktable has not arrived
   within the timeout — so the white loader doesn't look frozen. */
#loading-screen .pl-status {
    /* Absolutely positioned (out of the .pl-center flex flow) so that when the
       slow-connection watchdog appears it does NOT grow .pl-center and shift the
       centered logo+bar off their design position. Anchored to .pl-center's
       bottom edge (= the bar) — NOT to the screen centre: the large snowboarder
       logo pushes the bar below 50%+56px and the status used to land above it. */
    position: absolute; top: calc(100% + 14px); left: 50%; transform: translateX(-50%);
    width: max-content;
    font-family: 'Inter', sans-serif; font-size: 12px; font-weight: 600;
    text-align: center; max-width: min(80vw, calc(100vw - 32px));
}
/* Читаемость на любом фоне скина (светлый снег snowboarder и т.п.): мягкое
   затемнение, НЕ «окно» — многослойная тень вокруг букв + растушёванное
   радиальное пятно позади (::before), края которого не читаются. */
#loading-screen .pl-status,
#fatal-error .fe-detail, #session-error .fe-detail {
    color: #fff; overflow-wrap: anywhere; isolation: isolate;
    text-shadow: 0 1px 2px rgba(0,0,0,.8), 0 0 8px rgba(0,0,0,.7), 0 0 16px rgba(0,0,0,.5);
}
#loading-screen .pl-status::before,
#fatal-error .fe-detail::before, #session-error .fe-detail::before {
    content: ''; position: absolute; inset: -24px -48px; z-index: -1; pointer-events: none;
    background: radial-gradient(ellipse at center, rgba(0,0,0,.55), transparent 70%);
}
#fatal-error .fe-detail, #session-error .fe-detail { position: relative; }
#loading-screen .pl-status[hidden], #loading-screen .pl-status:empty { display: none; }
/* gl-статус (glStatus.js): сырая строка браузера под человекочитаемой причиной. */
#loading-screen .pl-status-raw { display: block; margin-top: 4px; font-size: 10px; font-weight: 400; font-family: ui-monospace, monospace; color: rgba(255,255,255,.88); overflow-wrap: anywhere; }

/* ===== RECONNECT / FATAL / SESSION — blurred full-screen overlay =========
   Same frosted look as the settings modal backdrop (.wf-modal-backdrop):
   the live field stays visible behind a blur, with the message centered
   directly on the blur — no white card/box. Reuses that blur radius/scrim. */
#conn-banner, #fatal-error, #session-error {
    position: fixed; inset: 0; z-index: var(--z-system);
    display: flex; align-items: center; justify-content: center;
    padding: 24px; text-align: center;
    background: var(--scrim);
    backdrop-filter: blur(var(--blur-scrim)); -webkit-backdrop-filter: blur(var(--blur-scrim));
    font-family: 'Inter', sans-serif;
}
#conn-banner[hidden], #fatal-error[hidden], #session-error[hidden] { display: none; }

/* ☢️ ТЕРМИНАЛЬНЫЕ экраны (#fatal-error, #session-error) — НЕПРОЗРАЧНЫЙ фон.
   #conn-banner (реконнект) намеренно оставляет живое поле видимым сквозь блюр:
   там игра жива и цифры на HUD настоящие. У терминальной ошибки мир МЁРТВ, а
   его цифры — ложь: под «Session error» сквозь блюр читался локальный
   демо-баланс 3 000.00 (денег, которых нет) — претензия владельца из приёмки
   2026-09-09. Сумма рядом с ошибкой сессии — денежное враньё, поэтому
   терминальный экран закрывает поле целиком. */
#fatal-error, #session-error {
    background: #14101A;
    backdrop-filter: none; -webkit-backdrop-filter: none;
}

/* reconnect: spinner + "Connecting…" centered straight on the blur */
#conn-banner {
    flex-direction: column; gap: 14px;
    color: #fff; font-size: 17px; font-weight: 700;
    text-shadow: 0 2px 14px rgba(0,0,0,.45);
}
.conn-spinner {
    width: 28px; height: 28px; border-radius: 50%;
    border: 3px solid rgba(255, 255, 255, 0.25);
    border-top-color: #fff;
    animation: conn-spin 0.8s linear infinite;
}
@keyframes conn-spin { to { transform: rotate(360deg); } }

/* ===== UNIFIED NOTIFICATION STACK — top-centre =======================
   One fixed flex-column container holds every transient banner:
     row 1 (top) = #conn-pill (pink link-status, weak/bad)
     row 2       = .wf-toast   (grey, all other transient toasts)
   Flex ordering does the layout: when #conn-pill is hidden the grey toast
   naturally becomes the top row — no manual reordering. */
#notif-stack {
    position: fixed;
    top: calc(22px + env(safe-area-inset-top));
    /* span the full viewport with 20px side gutters; children centre via flex.
       (the old left:50% + translateX(-50%) capped shrink-to-fit width at HALF
       the viewport — fixed-element available width is measured from `left`.) */
    left: 0; right: 0; padding: 0 20px; box-sizing: border-box;
    /* ABOVE the game chrome, yet BELOW the rotate gate, the preloader and
       critical conn/fatal overlays (Z-INDEX SCALE in :root). While ANY blur
       modal is open (menu, settings, autoplay editor…) the stack is HIDDEN —
       see the :has() rule right below; bonus-mode suppression hides it too. */
    z-index: var(--z-notif);
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    pointer-events: none;
}

/* pink link-status pill — Inter Semibold 14, 15%-alpha bright-pink glass.
   weak: warning only; .bad: bets are blocked (slightly denser tint). */
#conn-pill {
    /* always single line → half-height radius = full-semicircle side caps (pill). */
    padding: 8px 16px; border-radius: calc((1em + 16px) / 2);
    font-family: 'Inter', sans-serif;
    font-size: 14px; font-weight: 600; line-height: 1;
    white-space: nowrap; text-align: center;
    color: var(--notice-ink, var(--pink));
    background: var(--notice-bg, rgba(var(--pink-rgb), 0.15));
    backdrop-filter: blur(var(--blur-glass)); -webkit-backdrop-filter: blur(var(--blur-glass));
    pointer-events: none;
    /* width budget = the stack's 20px gutters; single line, ellipsis if
       it still doesn't fit. */
    max-width: 100%; box-sizing: border-box;
    overflow: hidden; text-overflow: ellipsis;
}
#conn-pill.bad { background: var(--notice-bg-strong, rgba(var(--pink-rgb), 0.22)); }
#conn-pill[hidden] { display: none; }

/* Owner (2026-09-30): no warning/info/error pills over an open blur modal
   (autoplay editor, menu, settings…). SSoT of "a blur modal is open" = the DOM
   itself: `.wf-modal-backdrop.show` (the same predicate ModalStack uses for
   store.uiModalOpen) — no second flag to keep in sync. `visibility` (not
   display/removal) only hides: #conn-pill keeps its state and reappears on
   close if the link is still weak; toasts keep their own 1.5 s lifetime. */
body:has(.wf-modal-backdrop.show) #notif-stack { visibility: hidden; }


/* fatal / session: title + sub + reload, all on the blur (no box) */
#fatal-error .fe-box, #session-error .fe-box {
    display: flex; flex-direction: column; align-items: center; gap: 14px;
    padding: 0 24px;
    text-shadow: 0 2px 14px rgba(0,0,0,.45);
}
#fatal-error .fe-title, #session-error .fe-title { font-size: 20px; font-weight: 800; color: #fff; }
#fatal-error .fe-sub, #session-error .fe-sub { font-size: 14px; font-weight: 500; color: rgba(255,255,255,.72); }
#fatal-error .fe-detail, #session-error .fe-detail { white-space: pre-line; text-align: center; font-size: 12px; font-family: ui-monospace, monospace; color: rgba(255,255,255,.85); user-select: text; max-width: min(560px, calc(100vw - 32px)); }
#fatal-error .fe-detail:empty, #session-error .fe-detail:empty { display: none; }
#fatal-error .fe-btn, #session-error .fe-btn {
    margin-top: 6px; padding: 11px 28px; border: none; border-radius: 24px;
    background: var(--pink); color: #fff; font-size: 14px; font-weight: 700;
    cursor: pointer; text-shadow: none;
}

