/* tapium.css — Tapium design chrome (ported from design prototype tapium_field.html).
   The field is rendered by Pixi (see themes/tapium.js — same tokens for the canvas);
   here — preloader, pills, bet/ap-sheet, sysbar, modals, buttons. */

: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) ---- */
    --pink:        #FF0080;
    --ink:         #16161A;
    --label:       #8A8A90;
    --label-2:     #9A9AA0;
    --label-3:     #6E6E76;
    --ok:          #0AA33A;
    --ok-2:        #1CB06C;
    --danger:      #FF3B5C;
    --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;
    --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;
}

/* ===== PRELOADER (id contract: loading-screen / loading-bar / loading-percent) */
#loading-screen {
    position: fixed; inset: 0; z-index: 9999; 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 { 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 svg { width: 100%; height: auto; display: block; }
#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. Sits just below the bar. */
    position: absolute; top: calc(50% + 56px); left: 50%; transform: translateX(-50%);
    font-family: 'Inter', sans-serif; font-size: 12px; font-weight: 600;
    color: var(--label-3); text-align: center; max-width: 80vw;
}
#loading-screen .pl-status[hidden] { display: none; }

/* ===== 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: 10001;
    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; }

/* 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 menu/modal blur (.wf-modal-backdrop z-index 9900) so info/toast
       pills stay visible & unblurred over ANY open modal (incl. autoplay editor),
       yet BELOW the preloader (#loading-screen 9999) and critical conn/fatal
       overlays (10001). bonus-mode suppression below still hides them by intent. */
    z-index: 9950;
    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: #FF2E88;
    background: rgba(255, 0, 128, 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: rgba(255, 0, 128, 0.22); }
#conn-pill[hidden] { display: none; }


/* 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-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;
}

/* ===== LOGO (top-left) ============================================== */
#logo {
    position: fixed;
    top: 14px; left: 20px;
    height: 53px;                /* same height as the balance pill */
    z-index: 20;
    display: flex; align-items: center;
    pointer-events: none; user-select: none; line-height: 0;
    filter: drop-shadow(0 4px 10px rgba(255, 0, 128, 0.20));
}
#logo svg { display: block; width: 44px; height: auto; overflow: visible; }
/* white outer stroke 3px: stroke under fill, width 6 → 3px visible outside */
#logo svg path { stroke: #FFFFFF; stroke-width: 6; paint-order: stroke; stroke-linejoin: round; }

/* ===== PILLS: bet bottom-left (balance lives in the bottom sysbar) ===== */
.pill {
    position: fixed;
    z-index: 20;
    height: 53px;
    display: flex; align-items: center; justify-content: center;
    padding: 0 18px;
    background: #FFFFFF;
    border: none;
    border-radius: 100px;
    box-shadow: 0 4px 10px 3px rgba(0, 0, 0, 0.10);
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform 100ms var(--ease);
}
/* Press feedback — like the autoplay button. Only the clickable bet pill
   (the balance pill is not clickable). */
.pill-bet:active { transform: scale(0.96); }
.pill-val {
    position: relative;
    display: inline-flex; align-items: baseline;
    font-family: 'Inter', sans-serif;
    font-weight: 600; font-size: 16px; line-height: 1;
    color: #000000; white-space: nowrap;
    /* Safeguard only — K/M compaction (formatAmount, PILL_COMPACT_FROM) is the real
       mechanism that keeps the value short; this just prevents a runaway string from
       stretching the tile if compaction is ever bypassed. */
    max-width: 42vw; overflow: hidden; text-overflow: ellipsis;
}
.pill-cap {
    position: absolute;
    left: 0; right: 0;
    bottom: calc(100% + 2px);
    text-align: center;
    font-family: 'Inter', sans-serif;
    font-weight: 700; font-size: 9px; line-height: 1;
    letter-spacing: 0.04em; text-transform: uppercase;
    color: rgba(0, 0, 0, 0.50);
    pointer-events: none;
}
.pill-unit {
    margin-left: 4px;
    font-size: 16px; font-weight: 600; letter-spacing: -0.02em;
    text-transform: uppercase;
    color: rgba(0, 0, 0, 0.50);
}
.pill-bet { bottom: 44px; left: 20px; }

/* Mobile: never zoom on double-tap. touch-action: manipulation keeps
   taps/clicks/scroll but disables double-tap zoom (including the amount input).
   The play field and modals are already under touch-action: none. */
.pill, .bet-sheet, .bet-sheet *, .bet-scrim,
.sys-stat, .sys-stat *,
button, [contenteditable], input, select { touch-action: manipulation; }

/* ===== Bet-energy ring around BET (token bucket, ChargeMeter.js) ===
   SVG stroke around the pill perimeter; fill fraction = charges + progress to next.
   Pure cosmetics — bet gate is server-side only. Position/size set by JS. */
#bet-charge-ring {
    position: fixed;
    z-index: 21;                 /* above pill (z20), but pointer-events off */
    pointer-events: none;
    overflow: visible;
}
#bet-charge-ring rect { fill: none; stroke-linecap: round; }
#bet-charge-ring .bcr-track { stroke: rgba(0, 0, 0, 0.08); stroke-width: 3; }
#bet-charge-ring .bcr-fill {
    stroke: var(--accent);       /* Tapium heat-pink */
    stroke-width: 3;
    filter: drop-shadow(0 0 4px rgba(255, 55, 199, 0.45));
}
#bet-charge-ring .bcr-notch { stroke: #FFFFFF; stroke-width: 4.5; stroke-linecap: butt; }
/* Charges depleted — red pulse to indicate "betting not allowed". */
#bet-charge-ring.empty .bcr-fill {
    stroke: var(--hover-fill);
    animation: bcr-pulse 1s var(--ease) infinite;
}
@keyframes bcr-pulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
}

/* ===== DRUM (odometer) for amounts ======================================= */
.drum .rd {
    display: inline-block; position: relative; height: 1.4em; overflow: hidden;
    text-align: center; vertical-align: bottom;
    -webkit-mask-image: linear-gradient(to bottom,
        transparent 0%, #000 32%, #000 68%, transparent 100%);
    mask-image: linear-gradient(to bottom,
        transparent 0%, #000 32%, #000 68%, transparent 100%);
}
.drum .rstatic { display: inline-block; line-height: 1.4em; }
.drum .rbase   { display: inline-block; line-height: 1.4em; }
.drum .rstack  { position: absolute; left: 0; right: 0; top: 0.2em; line-height: 1em; }
/* Drum in pills: more compact height, aligned to baseline with USD and label */
.pill-num.drum { display: inline-flex; align-items: baseline; }
.pill-num.drum .rd { height: 1.25em; vertical-align: baseline; }
.pill-num.drum .rstack { top: 0.13em; }
/* Balance and bet pills: mask below digits is solid (fade only at top) —
   otherwise the drum fades to white and a "flare" shows under the amount. */
#pill-balance .pill-num.drum .rd,
#pill-bet .pill-num.drum .rd {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 100%);
    mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 100%);
}

/* ===== Camera return button (aim) ===================================== */
#aim-btn {
    position: fixed;
    top: 50%; left: 15px;
    transform: translateY(-50%) scale(0.85);
    width: 53px; height: 53px;
    z-index: 21;
    background: var(--pink);
    border: 3px solid #FFFFFF;
    border-radius: 50%;
    box-shadow: 0 4px 10px 3px rgba(255, 0, 128, 0.20);
    display: none;
    align-items: center; justify-content: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    opacity: 0;
    transition: opacity 200ms var(--ease), transform 220ms var(--ease-spring);
}
#aim-btn.show { display: flex; opacity: 1; transform: translateY(-50%) scale(1); }
#aim-btn svg { display: block; width: 25px; height: 25px; transform: translateX(-2px); }
#aim-btn.on-right { left: auto; right: 15px; }
#aim-btn.on-right svg { transform: scaleX(-1) translateX(-2px); }

/* ===== Snake head indicator at screen edge ============================ */
#head-indicator {
    position: fixed;
    left: 4px; top: 50%;
    z-index: 21;
    width: 25px; height: 25px;
    display: none;
    pointer-events: none;
    filter: drop-shadow(0 4px 10px rgba(255, 0, 128, 0.20));
    transition: opacity 200ms var(--ease);
    opacity: 0;
}
#head-indicator.show { display: block; opacity: 1; }
#head-indicator.on-right { left: auto; right: 4px; }
#head-indicator.on-right svg { transform: scaleX(-1); }
#head-indicator svg { display: block; width: 25px; height: 25px; overflow: visible; }
#head-indicator svg path { fill: var(--pink); stroke: #FFFFFF; stroke-width: 6; paint-order: stroke; stroke-linejoin: round; }

/* ===== Bet amount popover ====================================== */
.bet-scrim {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.04);
    z-index: 25;
    opacity: 0; visibility: hidden;
    transition: opacity 180ms var(--ease), visibility 180ms var(--ease);
}
.bet-scrim.open { opacity: 1; visibility: visible; }

.bet-sheet {
    position: fixed;
    left: 20px; bottom: 44px;
    z-index: 26;
    width: 264px;
    background: #FFFFFF;
    border-radius: var(--r-modal);
    box-shadow: var(--shadow-modal);
    padding: 10px;
    font-family: 'Inter', sans-serif;
    letter-spacing: -0.01em;
    opacity: 0; visibility: hidden;
    transform: translateY(8px) scale(0.98);
    transform-origin: left bottom;
    transition: opacity 180ms var(--ease), transform 200ms var(--ease-spring),
                visibility 180ms var(--ease);
}
.bet-sheet.open { opacity: 1; visibility: visible; transform: translateY(0) scale(1); }

.bet-amount-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 7px;
}
.bet-pm {
    flex: none; width: 40px; height: 40px; border: none; border-radius: var(--r-field);
    background: var(--surface-btn); color: #000;
    font-family: inherit; font-weight: 600; font-size: 22px; line-height: 1;
    cursor: pointer; user-select: none;
    transition: background 120ms var(--ease), transform 80ms var(--ease);
}
.bet-pm:active { transform: scale(0.92); background: var(--surface-press); }
.bet-pm.disabled { opacity: 0.32; pointer-events: none; }
.bet-amount-mid {
    flex: 1; position: relative; display: flex; align-items: center; justify-content: center;
    min-width: 0; height: 1.25em;
    font-size: 28px; font-weight: 600; color: #000;
    letter-spacing: 0.01em;
}
.bet-amount-text {
    font-size: 28px; font-weight: 600; color: #000; line-height: 1;
    letter-spacing: 0.01em;
    white-space: nowrap;
    display: inline-flex; align-items: flex-end;
}
/* Input — overlaid on drum in the same metric; hidden by default */
#bet-input {
    outline: none; cursor: text; caret-color: var(--pink);
    position: absolute; left: 50%; transform: translateX(-50%);
    display: none;
    height: 1.4em; line-height: 1.4em;
    align-items: center;
}
.bet-amount-mid.editing #bet-display { visibility: hidden; }
.bet-amount-mid.editing #bet-input { display: inline-flex; }

.bet-presets {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px;
    margin-bottom: 11px;
}
.bet-preset {
    height: 34px; border: none; border-radius: var(--r-chip);
    background: var(--surface-btn); color: #000;
    font-family: inherit; font-weight: 600; font-size: 13px;
    letter-spacing: -0.01em; cursor: pointer;
    transition: background 120ms var(--ease), transform 80ms var(--ease);
}
.bet-preset:active { transform: scale(0.94); background: var(--surface-press); }

.bet-confirm {
    width: 100%; height: 46px; border: none; border-radius: var(--r-cta);
    background: var(--pink); color: #FFFFFF;
    font-family: var(--ff-head); font-weight: 900; font-size: 14px;
    letter-spacing: 0.01em;
    text-transform: uppercase; cursor: pointer;
    transition: transform 100ms var(--ease), filter 120ms var(--ease);
}
.bet-confirm:active { transform: scale(0.97); filter: brightness(0.95); }

/* ===== AUTOPLAY ================================================== */
/* Button sits ABOVE the BET tile (left-aligned with it); both left & bottom
   are set from JS in TapiumUI._initAutoplay().place(). */
#autoplay-btn {
    position: fixed; bottom: 44px; left: 0; z-index: 20;
    width: 53px; height: 53px; border: none; border-radius: 50%;
    background: #FFFFFF; box-shadow: 0 4px 10px 3px rgba(0, 0, 0, 0.10);
    display: flex; align-items: center; justify-content: center; padding: 0;
    cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
    transition: transform 100ms var(--ease);
}
#autoplay-btn:active { transform: scale(0.96); }
#autoplay-btn .ap-ico { display: flex; align-items: center; justify-content: center; line-height: 0; }
#autoplay-btn .ap-ico svg { display: block; width: 36px; height: 36px; overflow: visible; }
#autoplay-btn .ap-arrows {
    transform-box: fill-box; transform-origin: center;
    transition: transform 420ms cubic-bezier(.2, 1.3, .4, 1);
}
@media (hover: hover) and (pointer: fine) {
    #autoplay-btn:hover .ap-arrows { transform: rotate(40deg); }
}

/* Running-state icon (magenta progress ring + black stop square) — hidden until
   the bot runs, then it replaces the refresh-arrows glyph. */
#autoplay-btn .ap-run-ico { display: none; position: relative; width: 44px; height: 44px; }
#autoplay-btn .ap-ring { display: block; width: 44px; height: 44px; transform: rotate(-90deg); }
#autoplay-btn .ap-ring-track { fill: none; stroke: rgba(255, 0, 128, 0.15); stroke-width: 4; }
#autoplay-btn .ap-ring-prog {
    fill: none; stroke: var(--pink); stroke-width: 4; stroke-linecap: round;
    stroke-dasharray: 119.38; stroke-dashoffset: 119.38; /* 2πr, r=19 */
    transition: stroke-dashoffset 300ms var(--ease);
}
#autoplay-btn .ap-stop {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: 15px; height: 15px; border-radius: 3.5px; background: #000;
}
#autoplay-btn.ap-running .ap-ico { display: none; }
#autoplay-btn.ap-running .ap-run-ico { display: flex; align-items: center; justify-content: center; }
/* Endless run (∞): no determinate progress → spin the ring instead. */
#autoplay-btn.ap-running.ap-endless .ap-ring { animation: ap-run-spin 1.8s linear infinite; }
@keyframes ap-run-spin { to { transform: rotate(270deg); } }

/* Rounds badge — white pill anchored to the RIGHT of the running button
   (left/bottom set from JS). Shows done/total, e.g. "4/10". */
#autoplay-count {
    position: fixed; z-index: 21; left: 0; top: auto; bottom: 84px;
    min-width: 16px; text-align: center;
    background: #FFFFFF; box-shadow: 0 4px 10px 3px rgba(0, 0, 0, 0.10);
    border-radius: 100px; padding: 8px 12px;
    font-family: 'Inter', sans-serif; font-weight: 600; font-size: 16px; line-height: 1;
    color: #000000; white-space: nowrap;
    display: none; user-select: none; pointer-events: none;
}
#autoplay-count.show { display: block; }

/* Strategy rounds note in the ap-sheet (shows override of program.rounds). */
.ap-rounds-note { margin: -4px 2px 9px; font-size: 11px; font-weight: 600; color: var(--label-3); }

/* Inline confirm bar (dangerous launch, discard-changes) — no native dialogs. */
.ap-inline-confirm {
    display: flex; align-items: center; gap: 8px; margin-top: 10px; padding: 10px 12px;
    border-radius: var(--r-chip); background: var(--surface); color: var(--ink);
    font-family: var(--ff-body); font-size: var(--fs-body); font-weight: 600;
}
.ap-inline-confirm span { flex: 1; min-width: 0; }
.ap-inline-confirm button {
    min-height: 34px; padding: 0 14px; border: none; border-radius: var(--r-copy);
    font-family: var(--ff-head); font-weight: 900; font-size: 12px;
    letter-spacing: .02em; text-transform: uppercase; cursor: pointer;
}
.ap-ic-no { background: transparent; color: var(--label-3); }
.ap-ic-yes { background: var(--pink); color: #FFFFFF; }
/* inside the editor panel it floats above the bottom bar */
.ap-editor .wf-modal .ap-inline-confirm {
    position: absolute; left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom));
    z-index: 5; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

#ap-sheet { transform-origin: left bottom; }
#ap-sheet .bet-presets { margin-bottom: 6px; }
#ap-start { display: flex; align-items: center; justify-content: center; gap: 7px; }
#ap-start .ap-play { display: inline-flex; line-height: 0; }
#ap-start .ap-play svg { display: block; width: 13px; height: auto; }
.ap-inf {
    width: 100%; height: 34px; border: none; border-radius: var(--r-chip);
    background: var(--surface-btn); color: #000; cursor: pointer; margin-bottom: 11px;
    display: flex; align-items: center; justify-content: center;
    transition: background 120ms var(--ease), transform 80ms var(--ease);
}
.ap-inf:active { transform: scale(0.98); background: var(--surface-press); }
.ap-inf.active { background: rgba(255, 0, 128, 0.10); }
.ap-inf-glyph {
    font-family: 'Inter', sans-serif; font-weight: 600; font-size: 22px; line-height: 1;
    color: #000;
}
.ap-inf.active .ap-inf-glyph { color: var(--pink); }

/* ===== BOTTOM SYSTEM BAR =========================================== */
#sysbar {
    position: fixed; left: 0; bottom: 0; width: 100%; height: 40px; z-index: 20;
    background: linear-gradient(to top,
        rgba(255, 255, 255, 0.88) 0%,
        rgba(255, 255, 255, 0) 100%);
    display: flex; align-items: flex-end; padding: 0 14px 7px 30px;
    font-family: 'Inter', sans-serif; color: #6E6E73;
    pointer-events: auto; cursor: default;
    -webkit-tap-highlight-color: transparent; user-select: none;
}
#sysbar .sys-ico { display: inline-flex; line-height: 0; }
#sysbar .sys-ico svg { display: block; width: 14px; height: 14px; }
/* Menu — grey rounded pill; a round sound-toggle of the same height sits next to it. */
#sysbar .sys-menu {
    display: inline-flex; align-items: center; gap: 6px;
    height: 26px; padding: 0 12px;
    background: #E5E5E9; border: none; border-radius: 100px;
    cursor: pointer; color: #3A3A3E;
    font-family: 'Inter', sans-serif; pointer-events: auto;
    transition: transform 100ms var(--ease), background .35s ease;
}
#sysbar .sys-menu:active { transform: scale(0.96); }
#sysbar .sys-sound {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 26px; width: 26px; height: 26px; margin-left: 8px; padding: 0;
    background: #E5E5E9; border: none; border-radius: 50%;
    cursor: pointer; color: #3A3A3E; pointer-events: auto;
    transition: transform 100ms var(--ease), background .35s ease, color .2s ease;
}
#sysbar .sys-sound:active { transform: scale(0.92); }
#sysbar .sys-sound .snd-ico { display: block; width: 17px; height: 17px; }
/* Muted (.muted) → the sound waves simply disappear (no slash). */
#sysbar .sys-sound.muted .snd-wave { display: none; }
#sysbar .sys-sound.muted { color: #8A8A8E; }
#sysbar .sys-label { font-size: 11.5px; font-weight: 700; letter-spacing: .02em; }
/* Same height as the menu/sound pills (26px) → with a bottom-aligned sysbar the
   stats vertically centre on the same level as the "MENU" text. */
#sysbar .sys-group { display: flex; align-items: center; height: 26px; gap: 14px; margin-left: 20px; }
#sysbar .sys-stat { display: inline-flex; align-items: center; gap: 5px; cursor: default; }
#sysbar .sys-val {
    font-size: 12.5px; font-weight: 700; letter-spacing: -0.01em;
    color: #4A4A4E; white-space: nowrap;
}
/* Ping — on a translucent pill of the same green as the text/icon: a soft
   alpha fill keeps the text readable, and a dot replaces the signal bars. */
#sysbar .sys-stat.ping {
    color: var(--ok);
    gap: 6px; height: 22px; padding: 0 10px;
    background: rgba(10, 163, 58, 0.12); border-radius: 100px;
}
/* Single source of colour: text + dot inherit the pill's `color`, which the
   base rule sets green and the `.ping-hot` rule below flips to red. */
#sysbar .sys-stat.ping .sys-val { color: inherit; }
#sysbar .sys-stat.ping .sys-ico svg { width: 9px; height: 9px; }
/* Stable width slot for the ping value so the pill never resizes as the number
   changes: min-width reserves room for the widest realistic string ("999ms") so
   1-, 2-, 3-digit values and the "--ms" placeholder all render without growing
   the pill. Deliberately NO tabular-nums / "tnum" override — the digits must use
   the SAME (default, proportional) Inter figures as the balance number so the two
   pills read with one identical typeface. */
#ping-display {
    display: inline-block;
    min-width: 5.5ch;
    text-align: left;
}
/* Balance — the grey sibling of the green ping pill: same shape/height, neutral
   fill and text. The drum digits inherit the .sys-val weight/size (700 / 12.5px,
   matching the ping), the USD unit is a muted grey at a slightly smaller cap. */
#sysbar .sys-stat.balance {
    gap: 6px; height: 22px; padding: 0 10px;
    background: rgba(0, 0, 0, 0.06); border-radius: 100px;
}
#sysbar .sys-stat.balance .sys-val { color: #4A4A4E; }
#sysbar .sys-stat.balance .pill-num.drum { color: #4A4A4E; }
#sysbar .sys-stat.balance .pill-unit {
    margin-left: 3px; font-size: 11px; font-weight: 700;
    color: rgba(0, 0, 0, 0.38);
}
/* Weak/bad link (#ping-display gets .ping-hot at RTT ≥ threshold): recolor the
   whole pill the same bright-pink as the #conn-pill weak-connection plaque, so
   the two link-health signals read as one visual language (not red-on-green). */
#sysbar .sys-stat.ping:has(#ping-display.ping-hot) {
    color: #FF2E88;
    background: rgba(255, 0, 128, 0.15);
}
@media (hover: none) and (pointer: coarse) {
    /* Pull the MENU/sound cluster toward the left edge (smaller left inset) so
       there is more horizontal runway for a very large balance number, which
       grows leftward from the right-pinned stats group. */
    #sysbar { padding-left: 12px; }
    /* margin-left:auto right-pins the stats; the tighter gap sits the balance
       closer to the ping pill so the pair reads as one unit and frees the space
       to its left. */
    #sysbar .sys-group { margin-left: auto; gap: 7px; }
}

/* ===== TOP FADE BAR (mirror of the bottom #sysbar) ====================
   Purely decorative white fade at the top, matching #sysbar at the bottom but with
   the gradient pointing down. No content. position:fixed + z-index BELOW the logo
   and balance pill so it never shifts them and stays underneath. */
#topfade {
    position: fixed; left: 0; top: 0; width: 100%; height: 40px; z-index: 12;
    background: linear-gradient(to bottom,
        rgba(255, 255, 255, 0.82) 0%,
        rgba(255, 255, 255, 0) 100%);
    pointer-events: none; user-select: none;
    transition: background .35s ease;
}

/* ===== BOTTOM CHROME DURING BONUS ====================================
   The bonus field is WHITE/light (not the old inverted black field), so
   sysbar/topfade keep their normal light look — no dark recolor here. Smooth
   transition kept so state changes stay soft. */
#sysbar { transition: background .35s ease, color .35s ease; }

/* ===== MODALS ========================================================== */
.wf-modal-backdrop {
    /* Above ALL game chrome, including bonus elements — otherwise they would poke
       through the blur. Below only the preloader. */
    position: fixed; inset: 0; z-index: 9900;
    /* Horizontal padding = the phone side-gap (8px); the wrap's calc(100vw - 16px)
       then resolves to exactly 8px per side. Vertical keeps 20px breathing room. */
    display: flex; align-items: center; justify-content: center; padding: 20px 8px;
    background: var(--scrim);
    backdrop-filter: blur(var(--blur-scrim)); -webkit-backdrop-filter: blur(var(--blur-scrim));
    opacity: 0; pointer-events: none; transition: opacity .2s var(--ease);
    font-family: 'Inter', sans-serif;
    overscroll-behavior: none; touch-action: none;
}
.wf-modal-backdrop.show { opacity: 1; pointer-events: auto; }
.wf-modal-wrap {
    display: flex; flex-direction: column; align-items: center; gap: 14px;
    width: calc(100vw - 16px); max-height: calc(100dvh - 40px);
    overscroll-behavior: none; touch-action: none;
}
/* Main MENU (with the Tapium logo) stays narrow/centered — content is a short
   list. Every other modal fills to 8px from the screen edges on phones. */
#menu-modal .wf-modal-wrap { width: min(360px, calc(100vw - 28px)); }
@media (min-width: 600px) {
    .wf-modal-wrap { width: 420px; }
}
.wf-logo {
    display: none; width: 174px; max-width: 62%; line-height: 0;
    opacity: 0; transform: translateY(4px);
    transition: opacity .26s var(--ease), transform .26s var(--ease);
    pointer-events: none;
}
.wf-logo svg, .wf-logo img { display: block; width: 100%; height: auto; }
.wf-modal-wrap.has-logo .wf-logo { display: block; }
.wf-modal-backdrop.show .wf-modal-wrap.has-logo .wf-logo { opacity: 1; transform: translateY(0); }
.wf-modal {
    position: relative;
    width: 100%; min-height: 0; display: flex; flex-direction: column;
    background: #FFFFFF; border-radius: var(--r-modal); padding: 5px;
    box-shadow: var(--shadow-modal);
    letter-spacing: -0.01em; -webkit-tap-highlight-color: transparent;
    opacity: 0; transform: translateY(10px) scale(.97);
    transition: transform .3s var(--ease-spring), opacity .22s var(--ease);
    overflow: hidden;
}
.wf-modal-backdrop.show .wf-modal { opacity: 1; transform: translateY(0) scale(1); }
.wf-close-out {
    flex: none; width: 46px; height: 46px; border-radius: 50%; border: none; cursor: pointer;
    background: #FFFFFF; color: var(--ink);
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 6px 18px -4px rgba(0, 0, 0, 0.25);
    opacity: 0; transform: translateY(-6px) scale(.9);
    transition: opacity .24s var(--ease) .04s, transform .3s var(--ease-spring) .04s, background .14s var(--ease);
}
.wf-close-out:hover { background: #F2F2F4; }
.wf-close-out:active { transform: scale(.9); }
.wf-close-out svg { width: 22px; height: 22px; }
.wf-modal-backdrop.show .wf-close-out { opacity: 1; transform: translateY(0) scale(1); }

/* Sub-menu close button → exact mirror of the back button (same 34px box,
   same 14px side inset, same vertical center). It lives inside .wf-head next
   to .wf-back, so it stays level with it at any header height. The MAIN menu
   (#menu-modal) keeps its bottom close pill. */
.wf-modal-backdrop:not(#menu-modal) .wf-close-out {
    position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
    width: 34px; height: 34px; border-radius: 50%;
    background: transparent; box-shadow: none; color: var(--ink);
    opacity: 1; z-index: 3;
}
.wf-modal-backdrop:not(#menu-modal) .wf-close-out svg { width: 18px; height: 18px; }
@media (hover: hover) {
    .wf-modal-backdrop:not(#menu-modal) .wf-close-out:hover { background: #EFEFF2; }
}

.wf-head {
    position: relative; display: flex; align-items: center; justify-content: center;
    padding: 14px 16px 14px; min-height: 34px;
    flex: none;   /* не сжиматься: иначе при длинном списке (body flex:1) верхний отступ шапки «съедался» */
}
.wf-titlewrap { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; width: 100%; }
.wf-title {
    min-width: 0; max-width: 100%;
    font-family: var(--ff-head);
    font-size: 18px; font-weight: 900;
    letter-spacing: -0.01em; color: var(--ink); line-height: 1.04;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    text-transform: uppercase; text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-subtitle {
    font-family: 'Inter', sans-serif; font-size: 12px; font-weight: 600;
    color: var(--label); text-transform: uppercase; letter-spacing: 0; text-align: center;
}
.wf-body {
    overflow-y: auto; -webkit-overflow-scrolling: touch; flex: 1 1 auto; min-height: 0;
    margin: 0; padding: 0 2px;
}

/* Menu items — flat list with dividers */
.wf-mcard { background: transparent; padding: 0 4px; margin: 0 2px; }
.wf-mcard + .wf-mcard { margin-top: 14px; }
.wf-mrow { display: flex; align-items: center; gap: 12px; padding: 18px 10px; cursor: pointer; }
.wf-mrow .mi {
    flex: none; width: 22px; height: 22px; color: #3A3A3E;
    display: flex; align-items: center; justify-content: center;
    transform: translateZ(0); transition: opacity .14s var(--ease);
}
.wf-mrow .mi svg { display: block; width: 22px; height: 22px; backface-visibility: hidden; }
.wf-mrow .mi svg * { stroke-width: 1.85px; }
.wf-mrow .ml {
    flex: 1; font-family: var(--ff-head); font-size: 14px; font-weight: 900;
    color: var(--ink); letter-spacing: 0.01em; text-transform: uppercase;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transition: opacity .14s var(--ease);
}
@media (hover: hover) {
    .wf-mrow:not(.has-toggle):hover .ml, .wf-mrow:not(.has-toggle):hover .mi { opacity: 0.55; }
}
.wf-mdiv2 { height: 2px; background: #E5E5E9; border-radius: 1px; margin: 0 14px; }

/* ── Settings: Sounds/Music toggles + volume sliders ──────────────────────── */
.wf-mrow.has-toggle { cursor: default; }
.wf-toggle {
    flex: none; width: 42px; height: 25px; border-radius: 100px;
    background: #E2E2E6; border: none; padding: 0; position: relative; cursor: pointer;
    transition: background .18s var(--ease); transform: translateZ(0); isolation: isolate;
}
.wf-toggle::after {
    content: ''; position: absolute; left: 3px; top: 3px; width: 19px; height: 19px;
    border-radius: 50%; background: #FFFFFF; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);
    transition: transform .2s var(--ease-spring);
}
.wf-toggle.on { background: var(--pink); }
.wf-toggle.on::after { transform: translateX(17px); }

/* Volume row: collapsed while the toggle is off; expands smoothly when on */
.wf-volrow {
    max-height: 0; opacity: 0; overflow: hidden; padding: 0 12px;
    transition: max-height .28s var(--ease), opacity .2s var(--ease), padding .28s var(--ease);
}
.wf-volrow.show { max-height: 52px; opacity: 1; padding: 6px 12px 16px; }
.wf-vol {
    -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 18px;
    background: transparent; cursor: pointer; outline: none; margin: 0;
}
/* WebKit: 6px track centred + pink fill on the left by --p, 18px thumb */
.wf-vol::-webkit-slider-runnable-track {
    height: 6px; border-radius: 100px;
    background: linear-gradient(var(--pink), var(--pink)) 0 / var(--p, 100%) 100% no-repeat, #E2E2E6;
}
.wf-vol::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none; margin-top: -6px;
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--pink); border: 2px solid #FFFFFF; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28); cursor: pointer;
}
/* Firefox: separate track/progress/thumb */
.wf-vol::-moz-range-track { height: 6px; border-radius: 100px; background: #E2E2E6; }
.wf-vol::-moz-range-progress { height: 6px; border-radius: 100px; background: var(--pink); }
.wf-vol::-moz-range-thumb {
    width: 18px; height: 18px; border-radius: 50%; background: var(--pink);
    border: 2px solid #FFFFFF; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28); cursor: pointer;
}

/* ── Settings: nickname field ─────────────────────────────────────────────── */
.wf-setcard { padding: 14px 14px 16px; }
.wf-setrow { display: flex; flex-direction: column; }
.wf-setlabel {
    font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--label-2); margin: 0 2px 8px;
}
.wf-nick {
    display: flex; align-items: center; gap: 10px; width: 100%; height: 52px; box-sizing: border-box; margin: 0;
    background: #F4F4F6; border: 2px solid transparent; border-radius: var(--r-field); padding: 0 9px 0 14px;
    transition: border-color .15s var(--ease), background .15s var(--ease);
}
/* border ONLY while editing, same thickness → height doesn't jump */
.wf-nick.editing { background: #FFFFFF; border-color: #C9C9CF; }
.wf-nick.err { border-color: var(--danger) !important; background: #FFFFFF; }
.wf-nick-ico { flex: none; width: 19px; height: 19px; color: var(--ink); display: flex; align-items: center; justify-content: center; }
.wf-nick-ico svg { width: 100%; height: 100%; }
.wf-nick-input {
    flex: 1; min-width: 0; height: 100%; border: none; background: transparent; outline: none; padding: 0; margin: 0;
    font-family: 'Inter', sans-serif; font-size: 16px; font-weight: 700;
    letter-spacing: -0.01em; color: var(--ink); text-align: left; cursor: pointer;
}
.wf-nick.editing .wf-nick-input { cursor: text; }
.wf-nick-input:read-only { pointer-events: none; }   /* click is caught by the container → enter edit */
/* pencil hint (display) ⇄ check (editing) — shared right slot */
.wf-nick-edit {
    flex: none; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
    color: #B6B6BC; transition: opacity .14s var(--ease);
}
.wf-nick-edit svg { width: 18px; height: 18px; }
@media (hover: hover) { .wf-nick:hover .wf-nick-edit { color: var(--label); } }
.wf-nick.editing .wf-nick-edit { display: none; }
.wf-nick-save {
    flex: none; width: 34px; height: 34px; border-radius: var(--r-copy); border: none; cursor: pointer;
    background: var(--pink); color: #FFFFFF; display: none; align-items: center; justify-content: center; padding: 0;
    transition: transform .08s var(--ease);
}
.wf-nick-save:active { transform: scale(.92); }
.wf-nick-save svg { width: 19px; height: 19px; }
.wf-nick.editing .wf-nick-save { display: flex; }
.wf-nick-err {
    display: none; margin: 7px 2px 0; font-family: 'Inter', sans-serif; font-size: 12.5px;
    font-weight: 600; color: var(--danger);
}
.wf-nick-err.show { display: block; }
/* Build version — вшита в index.html из ./VERSION (плейсхолдер 1.3.2,
   build-service.nix / dev-server.mjs), НЕ через API: помогает убедиться, что
   загрузился свежий бандл, а не закешированный. Намеренно почти невидима —
   мелкая, приглушённая, для «посвящённого» глаза. */
.wf-version {
    margin: 10px 2px 2px; text-align: center;
    font-family: 'Inter', sans-serif; font-size: 9px; font-weight: 500;
    letter-spacing: 0.06em; color: var(--label-3); opacity: 0.28;
    /* Выделяемость даёт атрибут data-selectable в разметке (SSoT — style.css). */
}
/* iOS won't zoom on focus when the field's font-size is ≥16px */
.wf-modal-backdrop input[type="text"] { font-size: 16px; }

/* ── Provably Fair submenu ────────────────────────────────────────────────── */
/* Chevron "has submenu" at end of item — slightly larger */
.wf-chev { flex: none; width: 14px; height: 14px; color: #B5B5BC; display: flex; align-items: center; justify-content: center; }
.wf-chev svg { display: block; width: 14px; height: 14px; }

/* "Back" arrow in submenu header (left, over centered title) */
.wf-back {
    position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
    width: 34px; height: 34px; border: none; background: transparent; cursor: pointer;
    color: var(--ink); display: flex; align-items: center; justify-content: center;
    border-radius: 50%; transition: background .14s var(--ease);
}
.wf-back svg { width: 18px; height: 18px; display: block; }
.wf-back svg * { stroke-width: 2.1px; }   /* визуально = крестику (2.3 в viewBox 20 при 18px ≈ 2.07) */
@media (hover: hover) { .wf-back:hover { background: #EFEFF2; } }

/* (?) в шапке PROVABLY FAIR — открывает explain-блок «How does this prove fairness?».
   Живёт ВНУТРИ .wf-title сразу после текста заголовка (зазор 6px = gap заголовка),
   иконка — SVG-знак вопроса в кружке. */
.wf-pf-help {
    flex: none; width: 22px; height: 22px; padding: 0;
    border: 2px solid var(--ink); background: transparent;
    cursor: pointer; color: var(--ink); border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    align-self: center; margin-top: -1px; /* оптика: caps-текст чуть выше центра строки */
    transition: background .14s var(--ease), color .14s var(--ease);
}
/* Реальный клиппер иконки — .wf-title (overflow:hidden ради ellipsis, высота
   строки 21px < кнопки 22px): срезал верх кружка «?». Заголовок PF статичный,
   ellipsis ему не нужен — снимаем клип точечно. */
#pf-modal .wf-title,
#ap-editor-modal .wf-title,
#ap-editor-help-modal .wf-title { overflow: visible; }
/* Editor titles are longer than "PROVABLY FAIR" — keep them clear of the
   absolute back/close buttons, same recipe as #pf-help-modal below. */
#ap-editor-modal .wf-titlewrap,
#ap-editor-help-modal .wf-titlewrap { padding: 0 46px; box-sizing: border-box; }
.wf-pf-help svg { width: 13px; height: 13px; display: block; overflow: visible; }
/* «?» той же визуальной толщины, что крестик/назад (~2.1px on-screen):
   2.6 в viewBox 16 при 13px ≈ 2.11. */
.wf-pf-help svg path { stroke-width: 2.6px; }
@media (hover: hover) { .wf-pf-help:hover { background: var(--ink); color: #fff; } }

/* ===== BET DETAIL WINDOW (new design; look from v115) ==================== */
.wf-shield { display: inline-flex; width: 16px; height: 16px; }
.wf-shield svg { width: 100%; height: 100%; }
/* Stat mini-blocks (bet / X / payout / time) */
.wf-stats { display: flex; flex-direction: column; gap: 7px; margin-bottom: 9px; }
.wf-stat {
    width: 100%; min-width: 0; background: var(--surface); border-radius: var(--r-field); padding: 14px;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.wf-stat .l { font-size: 12px; font-weight: 600; color: var(--label); text-transform: uppercase; letter-spacing: .01em; white-space: nowrap; }
.wf-stat .v {
    font-size: 16px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right;
}
/* Pink (Fairness) / grey (Show on field) full-width buttons */
.wf-graybtn {
    width: 100%; height: 46px; border: none; border-radius: var(--r-cta); background: var(--pink); color: #FFFFFF;
    cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 7px;
    font-family: var(--ff-head); font-size: 14px; font-weight: 900;
    letter-spacing: 0.01em; text-transform: uppercase; transition: transform .1s var(--ease), filter .12s var(--ease);
}
.wf-graybtn:active { transform: scale(.97); filter: brightness(.95); }
.wf-graybtn .wf-shield { width: 16px; height: 16px; color: #FFFFFF; }
.wf-graybtn.pf { margin-bottom: 16px; }
.wf-graybtn[disabled] { background: #E7E7EA; color: rgba(0, 0, 0, 0.42); cursor: default; }
.wf-graybtn[disabled] .wf-shield { color: rgba(0, 0, 0, 0.42); }
.wf-graybtn[disabled]:active { transform: none; filter: none; }
.wf-graybtn.pf[disabled] { margin-bottom: 6px; }
.wf-pf-hint {
    margin-bottom: 16px; text-align: center;
    font-family: 'Inter', sans-serif; font-size: 12px; color: var(--label-2);
}
.wf-graybtn.gray { background: #E7E7EA; color: rgba(0, 0, 0, 0.70); }
.wf-graybtn.gray:active { background: #DEDEE2; }
.wf-graybtn.allbets { margin-top: 16px; }
/* SHOW ON FIELD: grey secondary button with a leading crosshair (reference). Disabled
   when the bet can't be replayed yet (still-open epoch) — dimmed, not removed. */
.wf-graybtn.showfield { margin-top: 8px; }
.wf-aimic { width: 16px; height: 16px; display: flex; }
.wf-aimic svg { width: 16px; height: 16px; }
.wf-graybtn.disabled { opacity: .45; cursor: default; pointer-events: auto; }
.wf-graybtn.disabled:active { transform: none; filter: none; }
/* Read-only "input" fields: label inside on the left + value (ellipsised) + copy button */
.wf-field {
    display: flex; align-items: center; gap: 10px; min-width: 0; margin-bottom: 7px;
    background: var(--surface); border-radius: var(--r-field); padding: 7px 6px 7px 14px;
    transition: background .2s var(--ease), box-shadow .2s var(--ease);
}
.wf-field-status { padding: 12px 14px; }   /* verdict row — no copy button */
.wf-finlabel { flex: none; font-size: 12px; font-weight: 600; color: var(--label); text-transform: uppercase; letter-spacing: .01em; white-space: nowrap; }
.wf-fval {
    flex: 1 1 auto; min-width: 0; font-family: 'Inter', sans-serif; font-size: 16px; font-weight: 600; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: -0.01em; text-align: right;
}
.wf-field-status.ok .wf-fval { color: var(--ok); }
.wf-field-status.fail .wf-fval { color: var(--danger); }
.wf-field-status.pending .wf-fval { color: var(--label); }
.wf-copy {
    flex: none; width: 34px; height: 34px; border: none; border-radius: var(--r-copy); background: none; color: var(--label-2);
    cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background .12s, color .2s, transform .1s;
}
.wf-copy svg { width: 16px; height: 16px; }
.wf-copy:hover { background: rgba(0, 0, 0, 0.05); }
.wf-copy:active { transform: scale(.9); }
.wf-field.copied { background: rgba(0, 225, 20, 0.10); box-shadow: inset 0 0 0 1.5px rgba(0, 225, 20, 0.45); }
.wf-field.copied .wf-copy { color: var(--ok); }
/* Divider */
.wf-divider { height: 2px; background: #ECECEF; border-radius: 1px; margin: 16px 2px; }
/* Page-swap animation inside the window (bet card ↔ fairness) — same spring as the menu */
@keyframes wfSwapIn { from { opacity: .35; transform: translateY(10px) scale(.97); } to { opacity: 1; transform: none; } }
.wf-modal.wf-swap { animation: wfSwapIn .3s var(--ease-spring); }

/* ── Cell-popup "All bets" list (crowd/empty marker popup) ─────────────────── */
.wf-list-h { font-family: var(--ff-head); font-size: 14px; font-weight: 900;
    color: var(--ink); opacity: 0.5; text-transform: uppercase; margin: 0 2px 14px; text-align: center; }
.wf-sub { font-size: 12px; font-weight: 600; color: var(--label); text-transform: uppercase; letter-spacing: .01em; margin: 4px 2px 10px; }
.wf-modal.allbets .wf-body { display: flex; flex-direction: column; overflow: hidden; }
.wf-modal.allbets { max-height: min(calc(100vh - 130px), 600px); }
.wf-modal.allbets .wf-fixed { margin-top: 12px; }
.wf-modal.allbets .wf-scroll { padding-right: 6px; margin-right: 0;
    scrollbar-width: thin; scrollbar-color: rgba(176, 176, 184, 0.7) transparent; }
.wf-modal.allbets .wf-scroll::-webkit-scrollbar { width: 6px; }
.wf-modal.allbets .wf-scroll::-webkit-scrollbar-track { background: transparent; }
.wf-modal.allbets .wf-scroll::-webkit-scrollbar-thumb { background: rgba(176, 176, 184, 0.7); border-radius: 8px; }
.wf-fixed { flex: none; }
.wf-colhead, .wf-prow { display: grid; grid-template-columns: minmax(0, 1fr) 62px 44px 84px; align-items: center; column-gap: 8px; }
.wf-colhead { padding: 0 13px 12px; font-size: 11px; font-weight: 600; color: var(--label); text-transform: uppercase; letter-spacing: .01em; }
.wf-colhead .who, .wf-colhead .s, .wf-colhead .x { text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-colhead .c { text-align: right; white-space: nowrap; }
.wf-scrollwrap { position: relative; flex: 1 1 auto; min-height: 0; display: flex; overflow: hidden; }
.wf-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch; padding-right: 8px; margin-right: -8px;
    scrollbar-width: thin; scrollbar-color: #D2D2D7 transparent; }
.wf-scroll::-webkit-scrollbar { width: 4px; }
.wf-scroll::-webkit-scrollbar-thumb { background: #D2D2D7; border-radius: 8px; }
.wf-plist { display: flex; flex-direction: column; gap: 6px; padding-bottom: 4px; }
.wf-prow { background: var(--surface); border-radius: var(--r-chip); padding: 13px; cursor: pointer;
    transition: background .12s var(--ease), transform .08s var(--ease); }
.wf-prow:hover { background: #EFEFF1; }
.wf-prow:active { transform: scale(.99); background: #EAEAEC; }
.wf-prow .who, .wf-prow .s, .wf-prow .x, .wf-prow .c { font-size: 12.5px; font-weight: 600; color: var(--ink); letter-spacing: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wf-prow .c { text-align: right; }
/* Выплата — зелёным (как в эталоне): +$50.34. Общее для stat-плашек и строк списка. */
.wf-stat .v.pos, .wf-prow .c.pos { color: var(--ok); }

/* Key–value rows (label on left, monospace value on right) */
.wf-kv { cursor: default; }
.wf-kv .ml { flex: none; text-transform: none; font-weight: 700; font-size: 13px; color: var(--label); }
.wf-val {
    flex: 1; text-align: right; min-width: 0;
    font-family: 'SFMono-Regular', ui-monospace, Menlo, Consolas, monospace;
    font-size: 12px; font-weight: 600; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (hover: hover) { .wf-kv:hover .ml, .wf-kv:hover .mi { opacity: 1; } }

/* Cryptographic proof — always visible under the hero (макет: без разделителя,
   только воздух между степпером и POINT A). */
.wf-pf-proof { padding: 10px 0 2px; }

/* ── Round stepper + flat proof rows (mobile-first) ───────────────────────── */
.wf-pf-body { padding-top: 2px; }
/* Тонкий скроллбар (3px), прижат к правому краю, без трека-«контейнера».
   scrollbar-gutter: stable оставлен: правый паддинг .wf-body всего 2px (<3px),
   без gutter'а полоса при появлении скролла сдвигала бы/перекрывала контент
   при перелистывании раундов (у одних есть скролл, у других нет) — с резервом
   3px контент стабилен и полоса не ложится на текст. */
#pf-modal .wf-body {
    scrollbar-gutter: stable;
    scrollbar-width: thin; scrollbar-color: #D2D2D7 transparent;
}
#pf-modal .wf-body::-webkit-scrollbar { width: 3px; }
#pf-modal .wf-body::-webkit-scrollbar-track { background: transparent; }
#pf-modal .wf-body::-webkit-scrollbar-thumb { background: #D2D2D7; border-radius: 8px; }

/* Stepper header (макет): ◀ ROUND #N (● LIVE под ним) ▶ + квадратная pause/play. */
.wf-pf-stepper {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin: 2px 2px 6px; min-height: 40px;
}
/* Стрелки prev/next — те же серые кнопки, что pause/play (.wf-pf-live),
   но без зелёного «is-paused»-состояния. */
.wf-pf-step {
    flex: none; width: 46px; height: 40px; border: none; border-radius: 13px;
    background: var(--surface); color: var(--ink); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: background .14s var(--ease), opacity .14s var(--ease), transform .1s var(--ease);
}
.wf-pf-step svg { width: 15px; height: 15px; }
@media (hover: hover) { .wf-pf-step:hover { background: #EFEFF1; } }
.wf-pf-step:active { transform: scale(.94); }
.wf-pf-step.disabled { opacity: .3; cursor: default; }
.wf-pf-step.disabled:hover { background: var(--surface); }
.wf-pf-step.disabled:active { transform: none; }
/* Центр тянется на всю ширину — стрелки прижаты к краям. */
.wf-pf-stepmid {
    flex: 1 1 auto; min-width: 0;
    display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.wf-pf-stepnum {
    font-family: var(--ff-head); font-size: 13.5px; font-weight: 900;
    line-height: 20px; text-box-trim: trim-both; text-box-edge: cap alphabetic;
    color: var(--ink); letter-spacing: 0.01em; text-transform: uppercase; white-space: nowrap;
}
.wf-pf-livetag {
    display: inline-flex; align-items: center; gap: 5px;
    font-family: 'Inter', sans-serif; font-size: 10.5px; font-weight: 700;
    letter-spacing: 0.05em; text-transform: uppercase; color: var(--ok);
}
.wf-pf-livetag .dot {
    width: 6px; height: 6px; border-radius: 50%; background: currentColor;
}
/* На паузе тег «● PAUSED» — серый целиком (точка красится через currentColor). */
.wf-pf-livetag.off { color: #B0B0B8; }
/* Квадратная кнопка pause/play — 46×40, серый фон var(--surface); на паузе зеленоватая. */
.wf-pf-live {
    flex: none; width: 46px; height: 40px; border: none; border-radius: 13px; cursor: pointer;
    background: var(--surface); color: var(--ink);
    display: flex; align-items: center; justify-content: center;
    transition: background .14s var(--ease), color .14s var(--ease), transform .1s var(--ease);
}
.wf-pf-live svg { width: 15px; height: 15px; }
.wf-pf-live:active { transform: scale(.94); }
.wf-pf-live .wf-pf-live-play { display: none; }
.wf-pf-live.is-paused { background: rgba(10,163,58,0.13); color: var(--ok); }
.wf-pf-live.is-paused .wf-pf-live-pause { display: none; }
.wf-pf-live.is-paused .wf-pf-live-play { display: block; }
@media (hover: hover) { .wf-pf-live:hover { background: #EFEFF1; } }
@media (hover: hover) { .wf-pf-live.is-paused:hover { background: rgba(10,163,58,0.18); } }
/* FAIRNESS CHECK (одиночная ставка) — без степпера. */
.wf-pf-single .wf-pf-stepper { display: none; }

/* The one round proof (live head / stepper neighbour / jump target). Flat — sits
   directly on the white sheet, grouped only by hairline dividers, no card fill. */
/* Горизонтальный паддинг 2px: суммарный отступ контента от края модалки =
   10px (.wf-modal) + 2px (.wf-body) + 2px = 14px по бокам. */
.wf-pf-card {
    margin: 0; padding: 12px 2px 4px; border: none;
}
.wf-pf-card-head {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    margin-bottom: 10px;
}
.wf-pf-formula {
    font-family: 'Inter', sans-serif; font-size: 11px; color: var(--label-2);
}
.wf-pf-verdict {
    flex: none;
    font-family: var(--ff-head); font-size: 11px; font-weight: 900;
    text-transform: uppercase; letter-spacing: 0.02em; white-space: nowrap;
}
.wf-pf-verdict.ok   { color: var(--ok-2); }
.wf-pf-verdict.fail { color: var(--danger); }
.wf-pf-verdict.pend { color: var(--label); }

.wf-pf-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.wf-pf-row-mark { font-weight: 800; font-size: 13px; }
.wf-pf-row-mark.ok { color: var(--ok-2); }
.wf-pf-row-mark.fail { color: var(--danger); }
.wf-pf-row-mark.pend { color: var(--label); }
.wf-pf-row-lbl {
    flex: 1 1 auto;
    font-family: var(--ff-head); font-size: 11px; font-weight: 800;
    text-transform: uppercase; letter-spacing: 0.04em; color: #6A6A70;
}
.wf-pf-copy {
    flex: none; width: 34px; height: 34px; border: none; border-radius: var(--r-copy);
    background: none; color: var(--label-2); cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background .12s, color .2s, transform .1s;
}
.wf-pf-copy svg { width: 16px; height: 16px; display: block; }
@media (hover: hover) { .wf-pf-copy:hover { background: rgba(0, 0, 0, 0.05); color: #6A6A70; } }
.wf-pf-copy:active { transform: scale(.9); }
.wf-pf-copy.copied { color: var(--ok); }

/* Зелёный фидбэк копирования — как в оригинале: при копировании вся плашка
   вспыхивает мятным + зелёная обводка (класс .copied ставится на кнопку ⧉,
   родителя ловим через :has). Мятный НЕПРОЗРАЧНЫЙ (#E5FCE9 = rgba(0,225,20,.10)
   поверх белого) — иначе на зелёной рамке SEED просвечивал бы ярко-зелёным. */
.wf-pfp-sha, .wf-pfp-seedrow, .wf-pfp-cnode, .wf-pfp-coordbox {
    transition: background .15s var(--ease), box-shadow .15s var(--ease);
}
.wf-pfp-sha:has(.wf-pf-copy.copied),
.wf-pfp-coordbox:has(.wf-pf-copy.copied),
.wf-pfp-cnode:has(.wf-pf-copy.copied) {
    background: #E5FCE9; box-shadow: inset 0 0 0 1.5px rgba(10, 163, 58, 0.45);
}
.wf-pfp-seedrow:has(.wf-pf-copy.copied) { background: #E5FCE9; }
.wf-pfp-cnode.commit:has(.wf-pf-copy.copied) {
    background: #E5FCE9;
    box-shadow: 0 0 0 2.5px var(--ok), inset 0 0 0 1.5px rgba(10, 163, 58, 0.45);
}

/* Hash value — plain text with a hairline underline (a field, not a box). ВСЕГДА
   сокращён (без раскрытия по клику); полное значение — только через ⧉ копирование. */
.wf-pf-hex {
    padding: 2px 2px 10px; margin-bottom: 4px;
    background: transparent; border: none; border-bottom: 1.5px solid #EDEDF1;
    font-family: 'Inter', sans-serif; font-size: 13px; line-height: 1.5; color: #2A2A2E;
    letter-spacing: 0.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    /* Выделяемость даёт атрибут data-selectable в разметке (SSoT — style.css). */
}

.wf-pf-series-note {
    margin-top: 6px; text-align: left; font-family: 'Inter', sans-serif;
    font-size: 11px; color: #C08A1C;
}
.wf-pf-msg {
    padding: 18px 8px; text-align: center; font-family: 'Inter', sans-serif;
    font-size: 12px; color: var(--label-2);
}

/* Per-point honesty rows. */
.wf-pf-nobets {
    display: inline-block; margin-top: 2px;
    font-family: var(--ff-head); font-size: 10px; font-weight: 800;
    text-transform: uppercase; letter-spacing: 0.04em; color: var(--label-2);
}

/* ── Proof card redesign (PROVABLY FAIR / FAIRNESS CHECK mockup) ──────────────
   POINT A/B section → SHA256 (dim) + green ▼ connector + SEED card w/ coord bar →
   fixed-height A→B viz → SEED CHAIN / COMMITS collapsibles. */

/* Section header "POINT A / ROUND #N". */
.wf-pfp-pthead {
    margin: 14px 2px 9px;
    font-family: var(--ff-head); font-size: 13.5px; font-weight: 900;
    line-height: 20px; text-box-trim: trim-both; text-box-edge: cap alphabetic;
    letter-spacing: 0.01em; text-transform: uppercase; color: var(--ink);
}
.wf-pfp-pthead:first-child { margin-top: 4px; }
.wf-pfp-pthead .sl { margin: 0 2px; }   /* макет: «/» тем же чёрным, что и текст */

/* Common hash-row primitives (SHA256 pill + SEED row). */
.wf-pfp-hxlbl {
    flex: none; display: inline-flex; align-items: center; gap: 4px;
    font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 600;
    line-height: 20px; text-box-trim: trim-both; text-box-edge: cap alphabetic;
    letter-spacing: 0.01em; text-transform: uppercase; color: var(--label);
}
.wf-pfp-hxlbl.green { color: var(--ok); }
.wf-pfp-hxok   { color: var(--ok); font-size: 11px; font-weight: 900; }
.wf-pfp-hxfail { color: var(--danger); font-size: 11px; font-weight: 900; }
.wf-pfp-hxval {
    /* Макет: хеши обычным sans (Inter), не mono; значение прижато ВПРАВО перед
       кнопкой копирования — как поля .wf-fval во всех остальных модалках.
       БЕЗ text-box-trim: он резал верх глифов внутри 20px-строки. */
    flex: 1 1 auto; min-width: 0; text-align: right;
    font: 600 15px/20px 'Inter', sans-serif;
    color: var(--ink); letter-spacing: -0.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-pfp-hxval.dim { color: #B4B4BA; font-weight: 600; }

.wf-pfp-hbox { margin: 0; }
/* SHA256 box (dim, "committed" hash) — единый стиль полей модалок .wf-field:
   серый var(--surface), лейбл слева, значение вправо, копи-кнопка даёт правый отступ. */
.wf-pfp-sha {
    display: flex; align-items: center; gap: 10px;
    background: var(--surface); border-radius: var(--r-field); padding: 7px 6px 7px 14px;
    /* Структурный резерв = высота копи-кнопки (34px): строка с пустым хешем «—»
       (без ⧉) той же высоты, что заполненная — карточка не прыгает при догрузке. */
    min-height: 34px;
}
/* Green pill connector ▼ на шве SHA256 → SEED (наезжает на оба поля). */
.wf-pfp-conn {
    position: relative; z-index: 2; width: 34px; height: 19px; margin: -6px auto;
    box-shadow: 0 0 0 3px #FFFFFF;
    display: flex; align-items: center; justify-content: center;
    color: #FFFFFF; line-height: 1;
    background: var(--ok); border-radius: var(--r-copy);
}
.wf-pfp-conn svg { width: 12px; height: 12px; display: block; }
/* Green SEED card (the revealed secret) — зелёная рамка вокруг серого поля + плашка координат. */
.wf-pfp-seedcard {
    border-radius: 16px; overflow: hidden; background: var(--ok);
    padding: 2.5px; transition: box-shadow .12s ease;
}
/* Внутреннее поле SEED — тот же серый var(--surface), что у SHA256-бокса. */
.wf-pfp-seedrow {
    display: flex; align-items: center; gap: 10px; padding: 7px 6px 7px 14px;
    background: var(--surface); border-radius: 13px;
    min-height: 34px;   /* тот же структурный резерв, что .wf-pfp-sha */
}
.wf-pfp-coordbar {
    display: flex; align-items: center; justify-content: center; gap: 36px;
    padding: 3px 12px 4px; background: var(--ok); color: #FFFFFF;
    font: 700 13px/20px 'Inter', sans-serif;
    text-box-trim: trim-both; text-box-edge: cap alphabetic;
    white-space: nowrap;
}
.wf-pfp-coordbar i { font-style: normal; font-weight: 700; opacity: 0.9; }
/* Point B awaiting reveal placeholder. Структурный резерв высоты = полный дуэт
   боксов точки (SHA 48 + коннектор 7 + seedcard 2.5·2+48+coordbar 27 = 135px,
   минус свой padding 16·2 при content-box): при раскрытии B / переключении
   раундов плейсхолдер и заполненный бокс занимают одинаковую высоту. */
.wf-pfp-bpend {
    padding: 16px 12px; min-height: 103px;
    display: flex; align-items: center; justify-content: center; text-align: center;
    font: 600 11.5px 'Inter', sans-serif; color: var(--label-2);
    background: var(--surface); border-radius: var(--r-field);
}

/* Copy button sits inside the hash rows. */
.wf-pfp-sha .wf-pf-copy, .wf-pfp-seedrow .wf-pf-copy, .wf-pfp-cnode .wf-pf-copy { flex: none; }

/* A→B viz — FIXED HEIGHT so the zone never jumps when the 2nd seed loads. */
.wf-pfp-viz {
    margin: 18px 0 4px; height: 200px; background: var(--surface); border-radius: 16px;
    padding: 8px; color: var(--ink); overflow: hidden;
    display: flex; align-items: center; justify-content: center;
}
.wf-pfp-viz svg { display: block; width: 100%; height: 100%; }
/* Заголовок POINT B идёт сразу после виджета/предупреждения — чуть больше воздуха сверху. */
.wf-pfp-viz + .wf-pfp-pthead,
.wf-pfp-warn + .wf-pfp-pthead,
.wf-pfp-coordbox + .wf-pfp-pthead { margin-top: 24px; }
.wf-pfp-vizmsg {
    text-align: center; padding: 0 16px;
    font: 600 12px 'Inter', sans-serif; color: var(--label);
}
.wf-pfp-vizmsg.err { color: var(--danger); }
.wf-pfp-warn {
    margin: 8px 0 0; padding: 8px 10px; border-radius: var(--r-copy); text-align: center;
    background: rgba(255,59,92,0.10); color: var(--danger);
    font: 700 11px 'Inter', sans-serif;
}

/* COORDINATES pill (FAIRNESS CHECK single-bet only). */
.wf-pfp-coordbox {
    display: flex; align-items: center; gap: 10px; margin: 10px 0 0;
    background: var(--surface); border-radius: var(--r-field); padding: 7px 6px 7px 14px;
    /* Резерв под копи-кнопку (34px): плейсхолдер «—» без ⧉ не ниже заполненного. */
    min-height: 34px;
}
.wf-pfp-coordbox .k {
    flex: none; font: 600 11px/20px 'Inter', sans-serif;
    text-box-trim: trim-both; text-box-edge: cap alphabetic;
    letter-spacing: 0.01em; text-transform: uppercase; color: var(--label);
}
.wf-pfp-coordbox .v {
    flex: 1 1 auto; text-align: right;
    font: 600 15px/20px 'Inter', sans-serif; color: var(--ink); letter-spacing: -0.01em;
}

/* Collapsible section (SEED CHAIN / COMMITS) — native <details>. Разделитель —
   только МЕЖДУ секциями (над первой, SEED CHAIN, линии нет — как в эталоне). */
.wf-pfp-collap { margin: 4px 0 0; }
.wf-pfp-collap + .wf-pfp-collap { border-top: 2px solid #ECECEF; }
.wf-pfp-collhead {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 2px; cursor: pointer; list-style: none;
    font: 900 13.5px var(--ff-head);
    letter-spacing: 0.01em; text-transform: uppercase; color: var(--ink);
}
.wf-pfp-collhead::-webkit-details-marker { display: none; }
.wf-pfp-caret { display: inline-flex; align-items: center; color: #B5B5BC; transition: transform .26s var(--ease); }
.wf-pfp-caret svg { display: block; width: 18px; height: 18px; }
.wf-pfp-collap[open] .wf-pfp-caret { transform: rotate(180deg); }
.wf-pfp-collbody { display: flex; flex-direction: column; gap: 0; padding: 0 0 10px; }

/* Chain / anchor node row — единый стиль полей .wf-field. */
.wf-pfp-cnode {
    display: flex; align-items: center; gap: 10px;
    background: var(--surface); border-radius: var(--r-field); padding: 7px 6px 7px 14px;
}
/* Соседние узлы без коннектора между ними (COMMITS: CURRENT/NEXT) — тот же
   зазор, что даёт пилюля-коннектор в цепи (~5px). */
.wf-pfp-cnode + .wf-pfp-cnode { margin-top: 5px; }
/* COMMIT (якорь #0) — простое зелёное кольцо вокруг поля (небольшой инсет,
   чтобы кольцо не резалось overflow'ом скролла). */
.wf-pfp-cnode.commit { margin: 2px 3px 3px; box-shadow: 0 0 0 2.5px var(--ok); }
.wf-pfp-cnode.next { opacity: 0.55; }
.wf-pfp-cidx {
    flex: none;
    font: 600 11px 'Inter', sans-serif; letter-spacing: 0.01em;
    text-transform: uppercase; color: var(--label); white-space: nowrap;
}
/* COMMIT / NEXT — тот же шрифт, что у остальных меток; отличаются только цветом. */
.wf-pfp-cnode.commit .wf-pfp-cidx { color: var(--ok); }
.wf-pfp-cnode.next .wf-pfp-cidx { color: var(--label-2); }
.wf-pfp-chx {
    flex: 1 1 auto; min-width: 0; text-align: right;
    font: 600 15px 'Inter', sans-serif;
    color: var(--ink); letter-spacing: -0.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-pfp-cnode.next .wf-pfp-chx { color: #B4B4BA; }
/* Связка-плашка «SHA-256» между узлами — наезжает на швы соседних полей
   (пилюля лежит НА границе), серая. */
.wf-pfp-cconn {
    display: flex; justify-content: center; padding: 0; margin: -7px 0;
    position: relative; z-index: 2;
}
.wf-pfp-cconn span {
    display: inline-flex; align-items: center; gap: 5px;
    background: #A9A9B0; color: #FFFFFF; border-radius: var(--r-copy); padding: 4px 11px;
    font: 800 10px 'Inter', sans-serif; letter-spacing: 0.05em; text-transform: uppercase;
    position: relative; box-shadow: 0 0 0 3px #FFFFFF;
}
/* Стрелка ▼ в плашках цепи — тот же SVG, что в зелёном коннекторе SHA256→SEED. */
.wf-pfp-cconn span svg, .wf-pfp-cmore svg { width: 11px; height: 11px; flex: none; display: block; }
/* «… N MORE SEEDS» — та же связка-плашка, зелёная. */
.wf-pfp-cmore {
    align-self: center; margin: -7px 0; background: var(--ok); color: #FFFFFF;
    display: inline-flex; align-items: center; gap: 5px;
    border-radius: var(--r-copy); padding: 5px 11px;
    font: 800 10px 'Inter', sans-serif; letter-spacing: 0.05em; text-transform: uppercase;
    position: relative; z-index: 2; box-shadow: 0 0 0 3px #FFFFFF;
}
.wf-pfp-note { margin-top: 8px; font-family: 'Inter', sans-serif; font-size: 12px; line-height: 1.5; color: #5A5A60; }

/* Подсветка одинаковых хешей: наведение на любой хеш (data-full) подсвечивает все
   его вхождения в карточке — напр. сид точки и то же звено в seed chain. */
[data-pf-card] [data-full] { transition: background .12s ease, box-shadow .12s ease; }
[data-pf-card] .wf-hex-peer {
    background: rgba(255,0,128,0.16); border-radius: 4px;
    box-shadow: 0 0 0 2px rgba(255,0,128,0.30);
}
/* Двусторонняя подсветка точка↔сид (кольцо маркера — розовое, цвет линии):
   ховер маркера A/B в SVG или SEED-карточки показывает кольцо на точке. Сам SEED-хеш
   при ховере маркера красится розовым через .wf-hex-peer (_onHexHover), а НЕ зелёной
   обводкой блока — единый розовый акцент, как при обычном ховере хеша. */
.wf-pfp-mk { cursor: pointer; }
.wf-pfp-mk .ring { transition: opacity .12s ease; }
.wf-pfp-mk:hover .ring,
[data-pf-card]:has([data-pf-seed="A"]:hover) [data-pf-pt="A"] .ring,
[data-pf-card]:has([data-pf-seed="B"]:hover) [data-pf-pt="B"] .ring { opacity: 1 !important; }
/* Плашка-подложка под кодом координат A/B — цвет фона виджета (макет: подписи
   лежат на чистом фоне, без видимой рамки), но всё ещё маскирует линию под текстом. */
.wf-pfp-ptlbl rect {
    fill: var(--surface);
    stroke: none;
}
.wf-pfp-cellmk { cursor: pointer; }
.wf-pfp-cellmk .cellring { transition: opacity .12s ease; }
.wf-pfp-cellmk:hover .cellring { opacity: 1 !important; }

/* Series anchor line + next-round one-line promise. */
.wf-pf-anchor {
    display: flex; align-items: baseline; gap: 8px; margin: 14px 14px 6px;
}
.wf-pf-anchor-lbl {
    flex: none; font-family: var(--ff-head); font-size: 11px; font-weight: 800;
    text-transform: uppercase; letter-spacing: 0.04em; color: var(--label-2);
}
.wf-pf-anchor-val {
    flex: 1 1 auto; text-align: right; cursor: pointer;
    font-family: 'Inter', sans-serif; font-size: 12px; color: #6A6A70;
}
.wf-pf-anchor-val.copied { color: var(--ok-2); }

/* Заблаговременный якорь СЛЕДУЮЩЕЙ серии — скромная вторая строка под текущим якорем.
   Тот же layout (.wf-pf-anchor), лишь чуть приглушённее и плотнее — не привлекает внимания. */
.wf-pf-anchor-next { margin-top: 0; opacity: 0.75; }

/* "How does this prove fairness?" collapsible explainer — flat list row with a
   hairline top divider, not a filled box. */
/* Fairness-instruction window: long title must wrap and clear the back button. */
#pf-help-modal .wf-titlewrap { padding: 0 46px; box-sizing: border-box; }
#pf-help-modal .wf-title {
    font-size: 15px; line-height: 1.15; white-space: normal; overflow: visible;
    text-overflow: clip; text-transform: none;
}

/* Fairness-instruction window body (opened by "?"). */
.wf-pf-explain {
    margin: 4px 4px 12px;
    font-family: 'Inter', sans-serif; font-size: 13px; line-height: 1.55; color: #5A5A60;
}
.wf-pf-explain p { margin: 12px 0; }
.wf-pf-explain b { color: var(--ink); font-weight: 800; }

.wf-pf-history {
    margin: 10px 14px 0; font-family: 'Inter', sans-serif;
    font-size: 11px; line-height: 1.4; color: var(--label); text-align: left; min-height: 14px;
}
.wf-pf-history.ok { color: var(--ok-2); }
.wf-pf-history.fail { color: var(--danger); }
.wf-pf-history:empty { display: none; }

/* ── My Bet History submenu ───────────────────────────────────────────────── */
/* Column header + rows — the reference MY BET HISTORY grid (.wf-colhead.hist /
   .wf-prow.hist): time is the widest column, money is squeezed, and a trailing
   34px column holds the per-row fairness-check (shield) button. Shared grid
   template so the header cells line up exactly over the row cells. */
.wf-hist-head, .wf-hist-row {
    display: grid;
    /* TIME and PAYOUT get equal flexible tracks so the BET/X column sits centred in
       the row. BET/X grows from 66 up to 96px when the (compacted) stake needs it —
       scaled currencies (IDR "15.0K IDR", code suffix, no glyph) overflowed the old
       fixed 66px even though the flexible 1fr columns had spare room. */
    grid-template-columns: minmax(0, 1fr) minmax(66px, 96px) minmax(0, 1fr) 34px;
    column-gap: 6px; align-items: center;
}
.wf-hist-head {
    /* Left padding = row margin-left (11px, the B-badge overhang) + row padding-left
       (8px) so the header labels line up exactly over the row cells. */
    /* Symmetric side gaps: left = row margin-left(6) + row padding-left(8) = 14px,
       right = row margin-right(6) + row padding-right(4) = 10px, so labels sit over
       the row cells while both screen-edge gaps read equal. */
    flex: none; padding: 0 10px 12px 14px; margin: 2px 2px 0;
    font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.01em; color: var(--label);
}
.wf-hist-head .wf-hist-c-time {
    text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wf-hist-head .wf-hist-c-betx { text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-hist-head .wf-hist-c-result { text-align: right; white-space: nowrap; }
/* The list viewport scrolls; a thin brand scrollbar is the navigation affordance. */
.wf-hist-scroll { scrollbar-width: thin; scrollbar-color: #D2D2D7 transparent; }
.wf-hist-scroll::-webkit-scrollbar { width: 4px; }
.wf-hist-scroll::-webkit-scrollbar-thumb { background: #D2D2D7; border-radius: 8px; }
/* Rows as grey rounded cards spaced by a gap (reference .wf-prow.hist look). */
.wf-hist-row {
    position: relative;
    /* Match rows that carry the 34px aim button (34px + 6px top/bottom padding,
       border-box) so bonus rows (no button) don't collapse shorter than the rest. */
    min-height: 46px;
    /* Left margin = exactly the bonus "B" badge's 11px left overhang (badge is
       centred on the row edge); everything else squeezed so the content gets the
       maximum usable width. */
    padding: 6px 4px 6px 8px; margin: 0 6px;
    background: var(--surface); border-radius: var(--r-chip);
    font-family: 'Inter', sans-serif; color: var(--ink);
}
/* All four data cells share the reference typography: 12px, semibold, dark ink.
   Scoped to rows so the header keeps its 11px grey label styling. */
.wf-hist-row .wf-hist-c-time, .wf-hist-row .wf-hist-c-betx,
.wf-hist-row .wf-hist-c-result {
    font-size: 12px; font-weight: 600; color: var(--ink); letter-spacing: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.wf-hist-row .wf-hist-c-result { text-align: right; }
/* BET (stake) stacked over X (mult) in a single centred column. */
.wf-hist-c-betx {
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; min-width: 0; line-height: 1.2;
}
.wf-hist-row .wf-hist-c-stake { text-align: center; color: var(--label); font-size: 11px; }
.wf-hist-row .wf-hist-c-stake.wf-hist-bonus { color: #9a4ab8; font-weight: 800; }
.wf-hist-row .wf-hist-c-mult { text-align: center; color: var(--ink); font-weight: 700; }
/* BET TIME cell — two stacked lines: time on top (dark ink), smaller/dimmer date below. */
.wf-hist-row .wf-hist-c-time { white-space: normal; line-height: 1.25; }
.wf-hist-t-date, .wf-hist-t-clock {
    display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wf-hist-t-date { font-size: 10px; font-weight: 500; color: var(--label); }
/* Bonus-trigger bet (bonus-trigger-cell): a normal bet that ALSO fired a bonus. Its
   field cell shows a green "B"; mirror that in the history list with a green coefficient
   + a green left rail on the row. Purely presentational (money/outcome unchanged). */
.wf-hist-c-mult.wf-hist-trigger { color: var(--ok-2); font-weight: 800; }
.wf-hist-row.wf-hist-trigger-row { box-shadow: inset 3px 0 0 0 var(--ok-2); }
/* Tappable "B" badge on a bonus-trigger row → opens the Bonus detail sub-page. Hangs
   half outside the row's left edge (before BET TIME) so it reads as a rail marker
   and never consumes a grid track. */
.wf-hist-bonus-btn {
    position: absolute; left: 0; top: 50%; transform: translate(-50%, -50%);
    width: 22px; height: 22px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: none; border-radius: 50%; background: var(--ok-2); color: #FFFFFF;
    font-family: var(--ff-head); font-size: 13px; font-weight: 900;
    line-height: 1; cursor: pointer; -webkit-tap-highlight-color: transparent;
    transition: background .14s var(--ease), transform .1s var(--ease);
}
.wf-hist-bonus-btn:hover { background: #159257; }
.wf-hist-bonus-btn:active { transform: translate(-50%, -50%) scale(.9); }
.wf-hist-row .wf-hist-c-result.win  { color: var(--ok); }
.wf-hist-row .wf-hist-c-result.loss { color: #B0B0B8; }

.wf-hist-list { margin: 0; min-height: 8px; display: flex; flex-direction: column; gap: 6px; padding-top: 2px; }
.wf-hist-sentinel { height: 1px; }
.wf-hist-status {
    margin: 12px 8px; text-align: center;
    font-family: 'Inter', sans-serif; font-size: 12px; color: var(--label-2);
}
.wf-hist-status.error { color: var(--pink); }

/* Trailing per-row shield button (wf-rowaim slot): opens this bet's Fairness Check.
   The ONLY tappable element in a row (the row body itself is inert); it is the last
   grid cell, pinned to the right of its track. Ink = the modal title (var(--ink)). */
.wf-rowaim {
    width: 34px; height: 34px; padding: 0; justify-self: end;
    display: flex; align-items: center; justify-content: center;
    border: none; border-radius: var(--r-copy); background: none; color: var(--ink);
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    transition: background .12s, color .2s, transform .1s;
}
.wf-rowaim svg { width: 18px; height: 18px; }
.wf-rowaim:hover { background: rgba(0, 0, 0, 0.05); color: var(--ink); }
.wf-rowaim:active { transform: scale(.9); }
.wf-rowaim.disabled { color: #D3D3D8; cursor: default; }
.wf-rowaim.disabled:hover { background: none; }
.wf-rowaim.disabled:active { transform: none; }

/* ── Field-peek: dock the SAME history window to the bottom, drop the blur, and let
      pan gestures reach the canvas, so the player can move the field + bet while
      viewing a replayed past round (PixiRenderer.enterReplay). It is NOT a separate
      window — the identical card (header + list + page/time/date scrubbers) is simply
      re-anchored to the bottom and height-capped so the field shows above it. The cap
      = --replay-peek-frac, published by Modals from UI_CONFIG.REPLAY_PEEK_FRAC, the
      same constant the replay camera centres against (replayMixin). ── */
#history-modal.field-peek {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: transparent;
    /* Backdrop no longer captures pointers → canvas pan works behind the panel. */
    pointer-events: none;
    align-items: flex-end; justify-content: center;
    padding: 0 0 12px;
}
/* The card itself is NOT shown in field mode: all interaction happens on the
   field (tap a bet cell to re-anchor). Exit = Escape / _exitField(). */
#history-modal.field-peek .wf-modal-wrap { display: none; }
/* Persistent highlight of the SELECTED replay bet row — kept in sync with the field
   selection in BOTH directions (field cell tap ↔ history row click). */
.wf-hist-row.wf-hist-selected {
    background: rgba(255, 0, 128, 0.18);
    box-shadow: inset 3px 0 0 rgba(255, 0, 128, 0.9);
}
/* Brief highlight when the list auto-scrolls to a bet picked on the field (replay). */
.wf-hist-row.wf-hist-flash {
    animation: wf-hist-flash-kf 1.2s ease-out;
}
@keyframes wf-hist-flash-kf {
    0%   { background: rgba(255, 0, 128, 0.35); }
    100% { background: transparent; }
}

/* ── Full-screen bonus PLAQUE ("BONUS GAME" intro) ─────────────────────────────
   #bonus-zone is glued to the right edge (right:0); JS animates only `left`. On the
   intro it pulls left→15px, expanding full-screen. The vertical wait line/badge stay
   in Pixi — this overlay is layered on top and only shown during the intro. */
#bonus-zone {
    position: fixed;
    /* WAIT phase: a tall strip (not full height) with inset top/bottom; LEFT corners
       rounded. The intro (.intro) below stretches it full-screen and drops the inset. */
    top: 7vh; bottom: 7vh;
    right: 0; left: 100%;
    border-top-left-radius: 22px;
    border-bottom-left-radius: 22px;
    z-index: 21;
    overflow: hidden;
    pointer-events: none;
    display: none;
    /* Fallback plaque tint (WebGL mesh canvas .bz-mesh draws over this). */
    background: linear-gradient(to right, #FF3F9F 0%, var(--pink) 100%);
    will-change: left, transform;
}
/* WAIT phase: vertical "BONUS" label rotated 90° left (reads bottom-up), near the LEFT
   edge of the strip (left set from JS), vertically centered. Hidden during the intro. */
.bz-zone-label {
    position: absolute;
    top: 50%;
    transform: translateY(-50%) rotate(180deg);
    writing-mode: vertical-rl;
    font-family: var(--ff-head);
    font-weight: 900;
    line-height: 1;
    letter-spacing: 0.02em;
    color: #fff;
    white-space: nowrap;
    pointer-events: none; user-select: none;
    opacity: 0.92;
    z-index: 2;
    transition: opacity .3s ease;
}
#bonus-zone.intro .bz-zone-label { opacity: 0; }
/* Entrance of the wait strip: quick but soft slide in from the right + fade. */
@keyframes bzAppear {
    from { opacity: 0; transform: translateX(36px); }
    to   { opacity: 1; transform: translateX(0); }
}
#bonus-zone.appearing { animation: bzAppear .32s cubic-bezier(.2, .9, .25, 1); }
/* Intro (full-screen): 15px inset all around + rounded corners; layered above all
   chrome. right=15px overrides base right:0; left→15px set by JS (_fireBonusIntro). */
#bonus-zone.intro {
    z-index: 9700;
    top: 15px; bottom: 15px; right: 15px;
    border-radius: var(--r-modal);
    background: #FF1E7A;   /* fallback if WebGL unavailable */
}
/* WebGL mesh-gradient background under the content. */
.bz-mesh { position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 0; pointer-events: none; }
#bonus-zone .bz-title { z-index: 2; }
.bz-title {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--ff-head);
    font-weight: 900;
    /* Base size only: fitted down in JS (_fitTitleToWidth) if it overflows the card. */
    font-size: min(72px, 11vw, 9vh);
    line-height: 1.05;
    color: #FFFFFF;
    text-align: center;
    letter-spacing: 0.02em;
    /* Wrap to balanced lines within the card; JS only shrinks a single overlong word. */
    white-space: normal;
    text-wrap: balance;
    padding: 0 16px; box-sizing: border-box;
    opacity: 0;                     /* visible only in the intro phase */
    transition: opacity .3s ease;
}
#bonus-zone.intro .bz-title { opacity: 1; }
/* Closing the intro — a SOFT wipe (gradient mask with a blurred edge) instead of a
   hard slide: the edge erases left→right. Cheap (mask composited on GPU). */
#bonus-zone.bz-wipeout {
    -webkit-mask: linear-gradient(90deg, #000 45%, transparent 55%) left / 240% 100% no-repeat;
            mask: linear-gradient(90deg, #000 45%, transparent 55%) left / 240% 100% no-repeat;
    animation: bzWipeOut .34s cubic-bezier(.7, 0, .84, 0) forwards;
}
@keyframes bzWipeOut {
    from { -webkit-mask-position: left;  mask-position: left; }
    to   { -webkit-mask-position: right; mask-position: right; }
}

/* ===== Bonus round chrome ============================================================
   During the bonus the bet/autoplay chrome is hidden (bets are not accepted). The class
   body.bonus-mode is toggled by TapiumUI on store.bonusActive. */
body.bonus-mode #pill-bet,
body.bonus-mode #pill-balance,
body.bonus-mode #autoplay-btn,
body.bonus-mode #autoplay-count { display: none !important; }

/* No top-centre notifications during the bonus: the outcome is predetermined
   server-side and no longer depends on the socket, so neither the pink
   link-quality pill nor any grey toast (nor a "Connecting…" reconnect hint)
   may cover the frozen bonus board. Belt-and-suspenders with the JS gates in
   TapiumUI._refreshConnPill / CentrifugeClient._refreshConnBanner — this also
   catches generic toasts that render into #notif-stack. */
body.bonus-mode #notif-stack { display: none !important; }

/* START button — the bonus is paused (snake/grid static) until pressed; it hides and the
   on-screen X counter (#bonus-x) appears in its place. */
#bonus-start {
    position: fixed;
    left: 50%; bottom: 64px;
    transform: translateX(-50%) scale(0.9);
    height: min(66px, 15vw);
    padding: 0 min(42px, 10.5vw);
    box-sizing: border-box;
    align-items: center; justify-content: center;
    background: var(--pink);
    border: 3px solid #FFFFFF;
    border-radius: 999px;
    box-shadow: 0 4px 10px 3px rgba(255, 0, 128, 0.20);
    font-family: var(--ff-head);
    font-weight: 700; font-size: min(30px, 6.6vw); line-height: 1;
    color: #FFFFFF;
    cursor: pointer;
    z-index: 9600;
    display: none; opacity: 0;
    -webkit-tap-highlight-color: transparent;
    transition: opacity 200ms var(--ease), transform 220ms var(--ease-spring);
}
#bonus-start .bs-label { display: block; transform: translateY(0.09em); }
#bonus-start.show { display: flex; opacity: 1; transform: translateX(-50%) scale(1); }
@media (hover: hover) and (pointer: fine) {
    #bonus-start.show:hover { transform: translateX(-50%) scale(1.06); }
}
#bonus-start.show:active { transform: translateX(-50%) scale(0.95); }

/* On-screen bonus X counter — top-center, dropped BELOW the logo zone (#logo: top 14px
   + 53px pill height → bottom ≈ 67px, plus a small gap) so the big X never paints over
   the logo on desktop or mobile. The width is clamped to the viewport; since a nowrap
   line ignores max-width, JS (_fitBonusXToWidth) also shrinks the font when a long
   value ("1234.56X") would still overflow on a narrow phone. */
#bonus-x {
    position: fixed; left: 50%;
    top: calc(max(14px, env(safe-area-inset-top)) + 62px);
    transform: translateX(-50%);
    z-index: 9500;
    font-family: var(--ff-head); font-weight: 900;
    font-size: min(76px, 15vw); line-height: 1;
    color: var(--pink);
    -webkit-text-stroke: 4.5px #FFFFFF;
    paint-order: stroke fill;
    filter: drop-shadow(0 4px 8px rgba(255, 0, 128, 0.30));
    pointer-events: none; user-select: none;
    white-space: nowrap;
    max-width: calc(100vw - 24px);
    display: none;
}
#bonus-x.show {
    display: block;
    animation: bxRise .42s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes bxRise {
    from { opacity: 0; transform: translateX(-50%) translateY(-20px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* ===== End-of-bonus screen (#bonus-end, "MEGA WIN!") — static closer over the game. */
#bonus-end {
    position: fixed; inset: 15px;
    border-radius: var(--r-modal);
    z-index: 9800;
    display: none;
    overflow: hidden;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0 24px;
    box-sizing: border-box;
    background: #FF1E7A;
    -webkit-tap-highlight-color: transparent;
}
/* Full-screen click catcher BEHIND the plaque so clicks in the 15px gap don't reach the
   field (no accidental bet). */
#bonus-end::before { content: ''; position: fixed; inset: 0; z-index: -1; }
#bonus-end .be-win, #bonus-end .be-mult { position: relative; z-index: 1; }
#bonus-end .be-continue { z-index: 1; }
#bonus-end.show {
    display: flex;
    -webkit-mask: linear-gradient(90deg, #000 45%, transparent 55%) left / 240% 100% no-repeat;
            mask: linear-gradient(90deg, #000 45%, transparent 55%) left / 240% 100% no-repeat;
    animation: beWipeIn 0.5s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes beWipeIn {
    from { -webkit-mask-position: right; mask-position: right; }
    to   { -webkit-mask-position: left;  mask-position: left; }
}
#bonus-end.closing {
    -webkit-mask: linear-gradient(90deg, transparent 45%, #000 55%) left / 240% 100% no-repeat;
            mask: linear-gradient(90deg, transparent 45%, #000 55%) left / 240% 100% no-repeat;
    animation: beWipeOut 0.42s cubic-bezier(.7, 0, .84, 0) forwards;
}
@keyframes beWipeOut {
    from { -webkit-mask-position: right; mask-position: right; }
    to   { -webkit-mask-position: left;  mask-position: left; }
}
.be-title {
    position: absolute; top: 64px; left: 50%; transform: translateX(-50%); z-index: 1;
    font-family: var(--ff-head); font-weight: 900;
    /* Base size only: the FINAL size is fitted in JS (_fitTitleToWidth) so ANY headline
       ("CONGRATULATIONS!", "SUPER MEGA WIN!") fits the card with ~5% side padding. */
    font-size: min(54px, 8.5vw, 8vh); line-height: 1.05; color: #FFFFFF;
    /* Wrap multi-word titles ("SUPER MEGA WIN!") to 2 balanced lines at full size instead
       of shrinking to a thin one-liner; JS only shrinks a single overlong word. */
    max-width: calc(100vw - 30px); white-space: normal; text-align: center;
    text-wrap: balance; letter-spacing: .02em;
    padding: 0 16px; box-sizing: border-box;
}
.be-win {
    margin-top: 0;
    font-family: var(--ff-head); font-weight: 900;
    font-size: min(96px, 12vw, 11vh); line-height: 1; color: #FFFFFF; white-space: nowrap;
}
.be-mult {
    margin-top: min(34px, 5vw, 4vh);
    font-family: var(--ff-head); font-weight: 900;
    font-size: min(48px, 6.5vw, 5.5vh); line-height: 1; color: #FFFFFF; opacity: 0.5; white-space: nowrap;
}
.be-continue {
    position: absolute;
    left: 50%; bottom: 64px;
    transform: translateX(-50%);
    height: min(66px, 15vw);
    padding: 0 min(42px, 10.5vw);
    box-sizing: border-box;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; border-radius: 999px;
    background: #FFFFFF;
    font-family: var(--ff-head); font-weight: 900;
    font-size: min(30px, 6.6vw); line-height: 1;
    color: var(--pink);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: transform 220ms var(--ease-spring);
}
.be-continue .bc-label { display: block; transform: translateY(0.09em); }
@media (hover: hover) and (pointer: fine) {
    .be-continue:hover { transform: translateX(-50%) scale(1.06); }
}
.be-continue:active { transform: translateX(-50%) scale(0.95); }

/* ── Autoplay editor — LIGHT Tapium identity (tokens: tapium.css :root) ──────
   White surface like .bet-sheet / .wf-modal; magenta --accent / --hover-fill for
   selection & primary; green --bet-fill for placed bets (same as the field). No
   dark panel, no invented colours. */

/* strategy row in the ap-sheet (the sheet itself is white) */
.ap-strategy-row {
    display: flex; align-items: center; gap: 8px; width: 100%;
    margin: 0 0 9px; padding: 9px 14px 9px 9px; min-height: 44px;
    background: var(--surface-btn); border: none; border-radius: var(--r-field); color: var(--ink); cursor: pointer;
    font-family: 'Inter', sans-serif; -webkit-tap-highlight-color: transparent;
    transition: background 120ms var(--ease), transform 80ms var(--ease);
}
.ap-strategy-row:active { transform: scale(0.98); background: var(--surface-press); }
/* Figure glyph plate — a bit darker than the row, slightly rounded corners. */
.ap-strategy-ico {
    flex: none; display: flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 8px;
    background: #E2E2E6; color: #B4B4BC;
}
.ap-strategy-ico .ap-ico { width: 18px; height: 18px; }
/* Name is left-aligned on the sheet-content edge (same left as the −/+ counter). */
.ap-strategy-name { flex: 1; text-align: left; font-size: 14px; font-weight: 600; letter-spacing: normal; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ap-strategy-caret { color: var(--placeholder); font-size: 17px; }
/* running → engaged dark-magenta (--hover-ink) so STOP reads distinct from START */
#ap-start.ap-running { background: var(--hover-ink); }

/* The editor card, scrim, sizing and open/close animation all come from the
   framework .wf-modal-wrap/.wf-modal now; the editor only fills .wf-body with
   its screens. The body is a flex column so .ape-screen fills it (needed for the
   fixed-height CELLS screen). */
.ap-editor .wf-body { display: flex; flex-direction: column; flex: 1; min-height: 0; padding: 0; }
/* [hidden] must beat the flex display rules below (screens, rulebar, mode toggle) */
.ap-editor [hidden] { display: none !important; }
/* Header = the reference .wf-head / .wf-back / .wf-pf-help / .wf-close-out (the
   markup uses those classes directly — no .ape-* header styles exist anymore).
   Shared by all editor screens (lib/edit/cells/repeat). The drill-down sub-screens
   (cells/repeat) are back-only per the reference: no header cross there. */
.ap-editor .wf-modal[data-screen="cells"] .wf-close-out,
.ap-editor .wf-modal[data-screen="repeat"] .wf-close-out,
.ap-editor .wf-modal[data-screen="preview"] .wf-close-out { display: none; }

/* "How it works" body list — lives in #ap-editor-help-modal (a separate
   reference modal opened by the header "?", same pattern as #pf-help-modal). */
.ap-help-list {
    list-style: none; margin: 4px 2px 12px; padding: 0;
    font-family: 'Inter',sans-serif; font-size: 13px; line-height: 1.45; color: #3A3A3E;
}
.ap-help-list li { position: relative; padding-left: 16px; }
.ap-help-list li + li { margin-top: 9px; }
.ap-help-list li::before { content: '•'; position: absolute; left: 2px; color: var(--hover-fill); font-weight: 700; }
.ape-screen {
    flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
    /* the card no longer fills the screen → content scrolls inside the body */
    overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y;
}
/* Drill-down EDIT STRATEGY sub-screens (name list, cells, repeat) share padding. */
.ape-editlist, .ape-cells-screen, .ape-repeat-screen { padding: 10px 12px 12px; }

/* EDIT STRATEGY list: stacked field label + name + navigator rows, SAVE pinned bottom. */
.ape-list { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
/* Navigator plates = the PF SHA256/SEED info-plate look (.wf-pfp-sha): grey
   var(--surface) plate, small dim uppercase label left (.wf-pfp-hxlbl), dark 15px value
   right (.wf-pfp-hxval) — NOT an input look (inputs are taller + focus caret). */
.ape-nav {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    min-height: 52px; padding: 0 10px 0 14px; border: none; border-radius: var(--r-field); cursor: pointer;
    background: var(--surface); color: var(--ink); font-family: inherit;
    transition: background .12s var(--ease);
}
.ape-nav:active { background: #ECECEE; }
.ape-nav-l {
    flex: none; font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 600;
    letter-spacing: 0.01em; text-transform: uppercase; color: var(--label);
}
.ape-nav-r { display: flex; align-items: center; gap: 6px; min-width: 0; }
.ape-nav-prev {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font: 600 15px/20px 'Inter', sans-serif; letter-spacing: -0.01em; color: var(--ink);
}
.ape-nav-chev { width: 18px; height: 18px; color: var(--label); flex: none; }

/* BET CELLS PRESET is a FIXED-height panel: no vertical scroll of the modal — only
   the field pans horizontally inside .ape-gridwrap (grid fits vertically). */
.ape-cells-screen.ape-fixed { overflow: hidden; touch-action: none; }
/* BET CELLS PRESET is NEAR-FULL-SCREEN (only on this sub-screen — data-screen drives
   it, the other editor screens keep their natural card height): the panel stretches
   to the viewport minus the backdrop padding so the field gets maximum room. */
.ap-editor .wf-modal[data-screen="cells"],
.ap-editor .wf-modal[data-screen="preview"] { height: calc(100dvh - 28px); }
/* Desktop (≥600px): the coefficient grid needs only half the viewport, not the full
   height — the phone keeps the near-full-screen panel above, untouched. */
@media (min-width: 600px) {
    .ap-editor .wf-modal[data-screen="cells"],
    .ap-editor .wf-modal[data-screen="preview"] { height: 50dvh; }
}
/* The field box fills ALL the room between the label and TOTAL/SAVE (no cap), and
   bleeds edge-to-edge: negative margins cancel the screen's 12px side padding so the
   canvas spans the full modal width. Cells fit by height inside (EditorGrid). */
.ape-cells-screen .ape-gridwrap {
    flex: 1 1 auto; height: auto; max-height: none; min-height: 180px;
    margin: 0 -12px; border-radius: 0; border-left: none; border-right: none;
}
.ape-fieldnote { margin-bottom: 8px; }
/* TOTAL: N BET(S) — centered, heading font Black, title ink. */
.ape-total {
    flex: none; text-align: center; margin: 10px 2px 2px;
    font-family: var(--ff-head); font-weight: 900; font-size: 14px;
    letter-spacing: 0.01em; text-transform: uppercase; color: var(--ink);
}
/* REPEAT: keep the cadence at the top, SAVE anchored at the bottom of the panel. */
.ape-repeat-screen .ape-bottom { margin-top: auto; }

/* editor screen */
.ape-namerow { display: flex; gap: 8px; flex: none; margin-bottom: 0; }
/* Standard modal text input (the settings nickname field .wf-nick): 52px tall,
   grey #F4F4F6, radius 14, Inter 16/700 (≥16px also kills the iOS focus zoom). */
.ape-name {
    flex: 1; min-width: 0; height: 52px; box-sizing: border-box; padding: 0 14px;
    border-radius: var(--r-field); border: none; background: #F4F4F6; color: var(--ink);
    font-family: 'Inter', sans-serif; font-size: 16px; font-weight: 700;
    letter-spacing: -0.01em; caret-color: var(--hover-fill);
}
.ape-name::placeholder { color: var(--placeholder); }
.ape-rounds { display: flex; align-items: center; gap: 6px; color: var(--label-3); font-size: 11px; font-weight: 700; text-transform: uppercase; }
.ape-rounds-in {
    width: 60px; height: 40px; padding: 0 8px; border-radius: var(--r-chip); text-align: center; border: none;
    background: var(--surface-btn); color: var(--ink); font-size: 15px; font-family: inherit; caret-color: var(--hover-fill);
}
.ape-rounds-in::placeholder { color: var(--placeholder); }
.ape-stoprow { display: flex; gap: 8px; flex: none; margin-bottom: 8px; }
.ape-stop { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: 6px; color: var(--label-3); font-size: 11px; font-weight: 700; text-transform: uppercase; }
.ape-stop-in {
    width: 74px; height: 38px; padding: 0 8px; border-radius: var(--r-chip); text-align: center; border: none;
    background: var(--surface-btn); color: var(--ink); font-size: 14px; font-family: inherit; caret-color: var(--hover-fill);
}
.ape-stop-in::placeholder { color: var(--placeholder); }
/* Auto-start bonus toggle row: label left, checkbox right (same rhythm as the stop inputs). */
.ape-autobonus { cursor: pointer; }
.ape-autobonus input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--hover-fill); cursor: pointer; flex: none; }
/* The grid box flex-fills the room left inside the panel (after the form, cadence,
   per-round note and action buttons) and never forces the window taller than the
   screen: the grid pans/zooms INSIDE this fixed box. min-height keeps it tappable on
   short screens; max-height caps it so the coefficient grid stays inside the card. */
.ape-gridwrap { position: relative; flex: 1 1 auto; min-height: 190px; max-height: 52vh; border-radius: var(--r-field); overflow: hidden; background: var(--bg); border: 1px solid var(--hairline); }
.ape-grid { display: block; width: 100%; height: 100%; touch-action: none; }
.ape-chip {
    min-height: 34px; padding: 0 12px; border-radius: var(--r-copy); border: none;
    background: var(--surface-btn); color: var(--ink); font-family: inherit; font-weight: 600; font-size: 12px; cursor: pointer;
    transition: background 120ms var(--ease);
}
.ape-chip:active { background: var(--surface-press); }

/* v2.1 repeat-cadence control — segmented toggle + big stepper (mobile-first) */
.ape-cadence { flex: none; display: flex; flex-direction: column; gap: 8px; margin: 10px 0 2px; }
.ape-field-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--label-2); }
.ape-seg { display: flex; gap: 4px; padding: 4px; background: var(--surface-btn); border-radius: 16px; }
.ape-seg-btn {
    flex: 1; min-height: 48px; border: none; border-radius: var(--r-chip); background: transparent; color: var(--label-3);
    font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer;
    transition: background .14s var(--ease), color .14s var(--ease), transform 100ms var(--ease);
}
.ape-seg-btn.active { background: var(--bg); color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,0.12); }
.ape-seg-btn:active { transform: scale(0.98); }
.ape-stepper { display: flex; align-items: center; justify-content: center; gap: 14px; padding: 4px 0 2px; }
.ape-step-btn {
    flex: none; width: 52px; height: 52px; border: none; border-radius: 16px; background: var(--surface-btn); color: var(--ink);
    font-size: 26px; font-weight: 700; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center; transition: background .12s var(--ease), transform 100ms var(--ease);
}
.ape-step-btn:active { background: #E3E3E6; transform: scale(0.95); }
.ape-step-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.ape-step-val { min-width: 44px; text-align: center; font-family: var(--ff-head); font-weight: 900; font-size: 26px; color: var(--ink); }
.ape-step-unit { color: var(--label-3); font-size: 12px; font-weight: 700; text-transform: uppercase; }
/* Plain-language mode hint — centered block with breathing room above/below. */
.ape-cadence-hint {
    font-size: 11px; line-height: 1.4; color: var(--label-3);
    text-align: center; align-self: center; max-width: 88%; margin: 14px auto 16px;
}

/* shared inline-SVG icons (autoplay/icons.js) — inherit currentColor */
.ap-ico { width: 20px; height: 20px; flex: none; pointer-events: none; }
.ap-ico-sm { width: 16px; height: 16px; }
.ap-op, .ap-loop, .ap-step-add, .ap-rep-btn, .ap-step-nav, .ap-dot, .ape-dry, .ape-chip-x {
    display: inline-flex; align-items: center; justify-content: center;
}
.ap-lib-new, .ap-lib-import, .ape-script { display: inline-flex; align-items: center; justify-content: center; gap: 7px; }

/* step lane */
.ape-lane { flex: none; padding: 8px 0; }
.ap-steplane { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ap-step-dots { display: flex; align-items: center; gap: 4px; }
.ap-step-nav { width: 34px; height: 34px; border: none; border-radius: 9px; background: transparent; color: var(--label-3); cursor: pointer; }
.ap-step-nav:active { background: var(--surface-press); }
.ap-step-nav:disabled { opacity: 0.3; cursor: default; }
.ap-dot { min-width: 34px; height: 34px; border: none; background: transparent; color: var(--placeholder); font-size: 16px; cursor: pointer; }
.ap-dot.cur { color: var(--accent); }
.ap-step-add { width: 40px; height: 40px; border-radius: var(--r-chip); border: 1px dashed var(--placeholder); background: transparent; color: var(--ink); font-size: 20px; cursor: pointer; }
.ap-step-meta { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.ap-step-repeat { display: flex; align-items: center; gap: 4px; }
.ap-rep-btn { width: 34px; height: 34px; border-radius: 9px; border: none; background: var(--surface-btn); color: var(--ink); font-size: 16px; cursor: pointer; }
.ap-rep-btn:active { background: var(--surface-press); }
.ap-rep-n { min-width: 18px; text-align: center; font-weight: 800; color: var(--ink); }
.ap-rep-lbl { color: var(--label-3); }
.ap-step-sum { font-size: 13px; font-weight: 700; color: var(--bet-coef-ink); }
.ap-loop { width: 40px; height: 40px; border-radius: var(--r-chip); border: none; background: var(--surface-btn); color: var(--label-3); font-size: 18px; cursor: pointer; }
.ap-loop.on { background: var(--accent); color: #fff; }

/* dot long-press menu (white sheet) */
.ap-dot-menu {
    position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 10000;
    display: flex; flex-direction: column; gap: 6px; padding: 10px; width: min(260px, 90vw);
    background: var(--bg); border-radius: 20px; box-shadow: 0 12px 40px 4px rgba(0,0,0,0.2);
    font-family: 'Inter', sans-serif;
}
.ap-dot-menu button { min-height: 46px; border: none; border-radius: var(--r-chip); background: var(--surface-btn); color: var(--ink); font-family: inherit; font-weight: 600; font-size: 14px; cursor: pointer; }
.ap-dot-menu button:active { background: var(--surface-press); }
.ap-dot-cancel { background: transparent !important; color: var(--label-3) !important; }

/* bottom action bar */
.ape-bottom { flex: none; display: flex; gap: 8px; padding: 10px 0 calc(2px + env(safe-area-inset-bottom)); }
.ape-btn { min-height: 48px; border: none; border-radius: 24px; font-family: var(--ff-head); font-weight: 900; font-size: 14px; letter-spacing: 0.01em; text-transform: uppercase; cursor: pointer; transition: transform 100ms var(--ease), filter 120ms var(--ease); }
.ape-btn:active { transform: scale(0.97); }
/* Run — the main call-to-action: large, full-width primary button. */
.ape-run { flex: 1; background: var(--hover-fill); color: #FFFFFF; }
.ape-run:active { filter: brightness(0.95); }
.ape-script { flex: none; padding: 0 16px; background: var(--surface-btn); color: var(--ink); border-radius: 24px; }
.ape-dry { flex: none; width: 52px; background: var(--surface-btn); color: var(--ink); font-size: 18px; border-radius: 24px; }
.ape-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* script tab (T3) — same light Tapium identity, monospace editor */
.ape-script-screen { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.ape-script-hint { flex: none; font-size: 11px; color: var(--label-3); margin: 2px 2px 6px; }
.ape-script-hint b { color: var(--ink); font-weight: 800; }
.ape-script-hint code { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; background: var(--surface-btn); padding: 1px 5px; border-radius: 6px; color: var(--heat-ink); }
.ape-ta {
    flex: 1 1 auto; min-height: 120px; width: 100%; resize: none; box-sizing: border-box;
    padding: 12px; border-radius: var(--r-field); border: 1px solid var(--hairline); background: #FAFAFB; color: var(--ink);
    font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 13px; line-height: 1.5;
    caret-color: var(--hover-fill); tab-size: 2; -webkit-text-size-adjust: 100%;
}
.ape-ta:focus { outline: none; border-color: var(--accent); }
.ape-ta::placeholder { color: var(--placeholder); }
.ape-script-errs { flex: none; margin: 8px 0 0; padding: 10px 12px; border-radius: var(--r-chip); font-size: 12px; line-height: 1.45; font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; }
.ape-script-errs.ok { background: #EAF7EE; color: #1B7A3D; }
.ape-script-errs.err { background: #FBEBEE; color: #B0243B; }
.ape-script-errs.busy { background: var(--surface-btn); color: var(--label-3); }
.ape-script-err { white-space: pre-wrap; word-break: break-word; }
.ape-script-actions { flex: none; display: flex; gap: 8px; padding: 10px 0 0; }
.ape-script-actions .ape-chip { flex: 1; justify-content: center; display: flex; align-items: center; min-height: 40px; }

/* shared transient toast (single grey row inside #notif-stack) — the grey slot
   sits directly under #conn-pill. Grey = "same grey as the coefficients"
   (#4D4D4D), 15%-alpha glass, Inter Semibold 14. */
.wf-toast-host {
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    max-width: 100%;
    pointer-events: none;
}
.wf-toast {
    /* width budget = the stack's 20px side gutters — no tighter cap. */
    max-width: 100%;
    /* radius = half the single-line box height (line-height 1.25em + 16px vertical
       padding). One line → perfect pill (side caps are full semicircles); two+
       lines → the SAME fixed radius, so the corners stay evenly rounded instead of
       ballooning into huge side arcs. */
    padding: 8px 16px; border-radius: calc((1.25em + 16px) / 2); box-sizing: border-box;
    background: rgba(77, 77, 77, 0.15); color: #4D4D4D;
    backdrop-filter: blur(var(--blur-glass)); -webkit-backdrop-filter: blur(var(--blur-glass));
    font-family: 'Inter', sans-serif; font-size: 14px; font-weight: 600;
    text-align: center; line-height: 1.25;
    opacity: 0; transform: translateY(-10px);
    transition: opacity .2s var(--ease), transform .26s var(--ease-spring);
}
/* the 2-line clamp lives on an INNER element: with clamp+padding on the pill
   itself, overflow:hidden clips at the padding box and a sliver of the third
   line bleeds into the bottom padding. Here overflow clips exactly at line 2. */
.wf-toast-text {
    display: -webkit-box; -webkit-box-orient: vertical;
    -webkit-line-clamp: 2; line-clamp: 2;
    overflow: hidden;
    white-space: normal; overflow-wrap: anywhere;
    /* hard fallback for engines where line-clamp doesn't kick in: the span has
       NO padding, so this clips exactly on the line-2 boundary (no sliver). */
    max-height: calc(1.25em * 2);
}
.wf-toast.show { opacity: 1; transform: translateY(0); }
/* Never more than ONE grey row: if several pills coexist for any reason, only the
   latest (last in DOM) is visible — "show the last one". */
.wf-toast-host .wf-toast:not(:last-child) { display: none; }
/* desktop: cap both pills at a quarter of the screen; mobile keeps full
   width minus the stack's 20px gutters. */
@media (min-width: 768px) {
    .wf-toast, #conn-pill { max-width: 25vw; }
}

/* library screen */
.ap-lib { display: flex; flex-direction: column; height: 100%; min-height: 0; padding: 10px; }
.ap-lib-actions { display: flex; gap: 8px; flex: none; margin-bottom: 10px; }
.ap-lib-new { flex: 1; min-height: 48px; border: none; border-radius: 24px; background: var(--hover-fill); color: #FFFFFF; font-family: var(--ff-head); font-weight: 900; font-size: 14px; text-transform: uppercase; cursor: pointer; }
.ap-lib-new:active { transform: scale(0.98); }
.ap-lib-import { flex: none; padding: 0 16px; min-height: 48px; border: none; border-radius: 24px; background: var(--surface-btn); color: var(--ink); font-family: var(--ff-head); font-weight: 900; font-size: 14px; text-transform: uppercase; cursor: pointer; }
.ap-lib-import:active { background: var(--surface-press); }
/* icon strokes bold enough to sit next to 900-weight labels */
.ap-lib-new svg *, .ap-lib-import svg * { stroke-width: 2.8px; }
/* the list scrolls with the standard modal scrollbar (.wf-scroll is on the node) */
.ap-lib-list { display: flex; flex-direction: column; gap: 8px; }
/* every card is the SAME size in any state (normal / active / preset): fixed
   box-sizing + min-height so the pink ring or preset fill never changes bounds. */
.ap-card { position: relative; box-sizing: border-box; display: flex; align-items: center; gap: 10px; min-height: 64px; padding: 12px; border-radius: 16px; background: var(--bg); border: 1px solid var(--hairline); }
/* selected → 2px INNER brand-pink ring */
.ap-card.active { border-color: transparent; box-shadow: inset 0 0 0 2px var(--hover-fill); }
/* preset (built-in) → grey fill, no outline */
.ap-card.preset { background: var(--surface-btn); border-color: transparent; }
/* minimalist radio: outlined dot, filled brand-pink on the selected card */
.ap-card-radio {
    flex: none; width: 18px; height: 18px; border-radius: 50%;
    border: 2px solid var(--placeholder); display: flex; align-items: center; justify-content: center;
}
.ap-card.active .ap-card-radio { border-color: var(--hover-fill); }
.ap-card.active .ap-card-radio::after {
    content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--hover-fill);
}
.ap-card-main { flex: 1; min-width: 0; display: block; text-align: left; border: none; background: transparent; color: inherit; font: inherit; padding: 0; margin: 0; cursor: pointer; }
.ap-card-name {
    font-family: 'Inter', sans-serif; font-weight: 700; font-size: var(--fs-value); line-height: 1.2; color: var(--ink);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
    overflow: hidden; overflow-wrap: anywhere;
}
.ap-card-meta { font-size: 11px; color: var(--label-3); margin-top: 3px; }
.ap-card-ops { flex: none; display: flex; gap: 3px; }
.ap-op { width: 40px; height: 40px; border: none; border-radius: var(--r-copy); background: var(--surface-btn); color: var(--ink); font-size: 15px; cursor: pointer; transition: background 120ms var(--ease); }
.ap-op:active { background: var(--surface-press); }
.ap-op-run { color: var(--bet-coef-ink); }
.ap-op-del { color: var(--label-3); }
/* armed delete confirm (✓) — brand pink, not maroon */
.ap-op.arm { background: var(--hover-fill); color: #FFFFFF; }
.ap-op:disabled { opacity: 0.3; cursor: not-allowed; }

/* import pane (replaces the native prompt()) */
.ap-import-pane { display: flex; flex-direction: column; gap: 8px; flex: none; margin-bottom: 10px; }
.ap-import-ta {
    min-height: 110px; resize: none; padding: 10px 12px; border-radius: var(--r-chip);
    border: 1px solid var(--hairline); background: #FAFAFB; color: var(--ink);
    font-family: 'Inter', sans-serif; font-size: 13px; line-height: 1.5;
    caret-color: var(--hover-fill);
}
.ap-import-ta::placeholder { color: var(--placeholder); }
.ap-import-ta:focus { outline: none; border-color: var(--placeholder); }
.ap-import-actions { display: flex; gap: 8px; }
.ap-import-actions .ape-chip {
    flex: 1; min-height: 40px; border-radius: 20px;
    font-family: var(--ff-head); font-weight: 900; font-size: 13px;
    letter-spacing: 0.01em; text-transform: uppercase;
}
.ap-import-go { background: var(--hover-fill); color: #FFFFFF; }

/* one-time gesture hint above the editor grid */
.ape-hint { flex: none; font-size: 11px; font-weight: 600; color: var(--label-3); margin: 0 2px 6px; }

/* save validation error flash (replaces the native alert()) */
.ape-btn.ape-err { background: #B0243B; color: #FFFFFF; }

/* a11y: visible focus rings (keyboard) + ≥44px touch hit-areas on small controls */
.ape-btn:focus-visible, .ap-op:focus-visible, .ape-chip:focus-visible,
.ape-seg-btn:focus-visible, .ape-step-btn:focus-visible,
.ap-dot:focus-visible, .ap-rep-btn:focus-visible, .ap-loop:focus-visible, .ap-step-nav:focus-visible,
.ap-step-add:focus-visible, .ap-lib-new:focus-visible, .ap-lib-import:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px;
}
.ap-dot, .ap-rep-btn, .ape-chip { position: relative; }
.ap-dot::before, .ap-rep-btn::before, .ape-chip::before {
    content: ''; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: max(100%, 44px); height: max(100%, 44px);
}
