/* ============================================================================
 * SellerFlowLive — Redesign Design Tokens  (Phase 1 · foundation only)
 *
 * SCOPED + ADDITIVE. Every rule below is namespaced under [data-redesign], an
 * attribute the CURRENT app never sets — so this file has ZERO effect on the
 * existing production UI (.app / --sf-* / --m-* / .theme-dark / .theme-regular).
 * Nothing here is applied to any existing screen. Later phases (P2+) will mount
 * the redesigned screens under a [data-redesign] root and consume these tokens.
 *
 * Values are byte-for-byte from the design handoff:
 *   - design-redesign/README.md (Themes / Accent / Tokens tables)
 *   - design-redesign/SellerFlowLive.dc.html token engine (lines 871–1019),
 *     rgba() helper at line 989: rgba(hex,a) -> rgba(r,g,b,a).
 *
 * Defaults: Light theme + Indigo accent (per README "default is Light + Indigo").
 * Theme is selected via [data-theme="light"|"dark"]; accent via
 * [data-accent="indigo"|"violet"|"emerald"|"rose"|"sky"|"amber"].
 * ============================================================================ */

/* ── Accent presets: base / light / dark shades (+ rgb for soft alphas) ──────
 * Source: dc.html L871–876. `--_accent*` are PRIVATE (underscore) inputs; the
 * theme blocks below derive the public --accent* tokens from them. */
[data-redesign][data-accent="indigo"]  { --_accent:#4f46e5; --_accent-light:#a5b4fc; --_accent-dark:#3730a3; --_accent-rgb:79,70,229; }
[data-redesign][data-accent="violet"]  { --_accent:#7c3aed; --_accent-light:#c4b5fd; --_accent-dark:#5b21b6; --_accent-rgb:124,58,237; }
[data-redesign][data-accent="emerald"] { --_accent:#059669; --_accent-light:#34d399; --_accent-dark:#065f46; --_accent-rgb:5,150,105; }
[data-redesign][data-accent="rose"]    { --_accent:#e11d48; --_accent-light:#fda4af; --_accent-dark:#9f1239; --_accent-rgb:225,29,72; }
[data-redesign][data-accent="sky"]     { --_accent:#0284c7; --_accent-light:#7dd3fc; --_accent-dark:#075985; --_accent-rgb:2,132,199; }
[data-redesign][data-accent="amber"]   { --_accent:#d97706; --_accent-light:#fcd34d; --_accent-dark:#b45309; --_accent-rgb:217,119,6; }

/* Default accent = Indigo when [data-accent] is absent. */
[data-redesign]:not([data-accent]) { --_accent:#4f46e5; --_accent-light:#a5b4fc; --_accent-dark:#3730a3; --_accent-rgb:79,70,229; }

/* ── LIGHT theme (default) — dc.html L1010–1019 + common L996–997 ────────────
 * Applies to [data-redesign] with no theme attr OR [data-theme="light"]. */
[data-redesign],
[data-redesign][data-theme="light"] {
  /* surfaces / text */
  --app-bg: #f3f4fb;
  --surface: #ffffff;
  --surface-2: #f6f7fc;
  --surface-3: #eef0f9;
  --border: rgba(28,26,53,.09);
  --border-strong: rgba(28,26,53,.16);
  --text: #1c1a35;
  --text-dim: #5a5872;
  --text-muted: #9795ad;
  --on-header: #ffffff;
  --nav-bg: #ffffff;
  --shadow: 0 1px 3px rgba(28,26,53,.08), 0 12px 28px rgba(28,26,53,.07);
  --chip-bg: #f1f2fa;
  --ok: #059669;
  --warn: #d97706;
  --danger: #e11d48;
  /* U10 — danger tint (danger @ 10%): screens referenced var(--danger-soft, …)
     with divergent inline fallbacks; defining it makes the tint theme-consistent. */
  --danger-soft: rgba(225,29,72,.1);
  --btag-old-fg: #166534; /* buyer-tag pill text (fb_polish_v2) */
  --btag-new-fg: #991b1b;
  --warn-soft: rgba(217,119,6,.1); /* Buyer Alert amber row tint (warn @ 10%) */
  /* Miner-risk chips (theme-adaptive FILL tokens; a filled chip needs a
     saturated background that keeps its ink legible — the --danger/--warn TEXT
     tokens are tuned for text-on-surface, not fills, so risk chips get their
     own fill pair per theme). risky = loud crimson, watch = amber, unknown =
     muted neutral. */
  --risk-risky-bg: #e11d48; --risk-risky-fg: #ffffff;
  --risk-watch-bg: #d97706; --risk-watch-fg: #ffffff;
  --risk-unknown-bg: rgba(28,26,53,.06); --risk-unknown-fg: #6f6d84; --risk-unknown-bd: rgba(28,26,53,.15);
  /* accent-derived — light theme: accent *text* uses the DARK shade;
     soft = base @ 12%, softer = base @ 7%; header band = solid accent. */
  --accent: var(--_accent);
  --accent-text: #ffffff;
  --accent-fg: var(--_accent-dark);
  --handle: var(--_accent-dark);
  --accent-soft: rgba(var(--_accent-rgb), .12);
  --accent-softer: rgba(var(--_accent-rgb), .07);
  --header-bg: var(--_accent);
  --glow-a: rgba(var(--_accent-rgb), .5);
}

/* ── DARK theme (neutral slate — Linear/Vercel direction, 2026) ──────────────
 * Neutral near-black base + off-white text; the brand accent stays the single
 * saturated color. Elevation via lighter SOLID surfaces, not shadow. The old
 * purple-saturated radial app-bg + cyan/grid decoration are gone. accent tokens
 * are UNCHANGED (accent *text* = LIGHT shade, soft = base @ 24/14%) — on the flat
 * neutral base each accent reads cleaner. */
[data-redesign][data-theme="dark"] {
  /* neutral / structural */
  --app-bg: #0e1017;
  --surface: #181b23;
  --surface-2: #14161d;
  --surface-3: #20242e;
  --border: rgba(255,255,255,.09);
  --border-strong: rgba(255,255,255,.16);
  --text: #e6e8ee;
  --text-dim: #9aa3b2;
  --text-muted: #6b7280;
  --on-header: #ffffff;
  --nav-bg: rgba(18,21,28,.92);
  --shadow: 0 8px 24px rgba(0,0,0,.35);
  --chip-bg: rgba(255,255,255,.06);
  --ok: #34d399;
  --warn: #fbbf24;
  --danger: #fb7185;
  --danger-soft: rgba(251,113,133,.16);
  --btag-old-fg: #86efac; /* buyer-tag pill text (fb_polish_v2) — light on the dark pill */
  --btag-new-fg: #fecaca;
  --warn-soft: rgba(251,191,36,.14);
  /* Miner-risk chips — dark theme. The FILL stays SATURATED (crimson/deep amber,
     NOT the lightened --danger/--warn text tokens) so white ink reads AND the
     chip pops against the near-black base; unknown = subtle light-on-dark tint. */
  --risk-risky-bg: #e11d48; --risk-risky-fg: #ffffff;
  --risk-watch-bg: #b45309; --risk-watch-fg: #ffffff;
  --risk-unknown-bg: rgba(255,255,255,.08); --risk-unknown-fg: #aab2c0; --risk-unknown-bd: rgba(255,255,255,.16);
  --accent: var(--_accent);
  --accent-text: #ffffff;
  --accent-fg: var(--_accent-light);
  --handle: var(--_accent-light);
  --accent-soft: rgba(var(--_accent-rgb), .24);
  --accent-softer: rgba(var(--_accent-rgb), .14);
  --header-bg: rgba(18,21,28,.85);
  /* decorative glows/grid NEUTRALIZED (no loud haze on the neutral base). The
     tokens are KEPT (not deleted) because .sfl-glow-a / .sfl-glow-cyan and the
     .sfl-grid overlay in redesign.css still reference them via var(); set to a
     minimal accent glow / transparent so nothing breaks and nothing shouts. */
  --glow-a: rgba(var(--_accent-rgb), .10);
  --glow-cyan: transparent;
  --grid-line: transparent;
}

/* ── Typography families (Google Fonts loaded via index.html; NOT applied to
 * any existing screen — later phases set font-family on redesigned elements).
 * README "Typography": Space Grotesk = display/titles/big numbers; Plus Jakarta
 * Sans = all UI/body; JetBrains Mono = numeric/tabular (₱, #order, counts). */
[data-redesign] {
  --font-display: 'Space Grotesk', sans-serif;
  --font-ui: 'Plus Jakarta Sans', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
}
/* ============================================================================
 * Redesign runtime styles (Phase 2). SCOPED under [data-redesign]; consumes the
 * tokens from src/styles/design-tokens.css. Loaded ONLY by the separate
 * redesign entry (redesign.html -> src/redesign/main.tsx). Has ZERO effect on
 * the existing app (index.html -> App.tsx), which never renders [data-redesign].
 * Keyframes verbatim from design-redesign/SellerFlowLive.dc.html L20–26.
 * ============================================================================ */

@keyframes sflLive { 0%,100% { box-shadow: 0 0 0 0 rgba(225,29,72,.55); } 50% { box-shadow: 0 0 0 7px rgba(225,29,72,0); } }
@keyframes sflDot  { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: .5; transform: scale(.7); } }
@keyframes sflComm { from { opacity: .35; transform: translateY(-7px); } to { opacity: 1; transform: translateY(0); } }
@keyframes sflRise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@keyframes sflGrid { from { background-position: 0 0; } to { background-position: 38px 38px; } }
@keyframes sflGlow { 0%,100% { transform: translate(0,0) scale(1); opacity: .8; } 50% { transform: translate(14px,-10px) scale(1.12); opacity: 1; } }
@keyframes sflSheet { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* ════════════════════════════════════════════════════════════════════════════
 * ANIMATED UI SYSTEM — Slice 1 (prototype). GPU-friendly BY CONSTRUCTION: loops
 * animate ONLY transform/opacity; the LIVE ring is a scaling ::after (STATIC
 * box-shadow, animated transform/opacity) NOT an animated box-shadow; the sheen
 * is a translating skewed highlight NOT background-position; NO filter:blur on
 * the app-shell path. Every LOOP class is gated by BOTH prefers-reduced-motion
 * AND the in-app kill switch [data-motion="off"]. One-shot entrances (screen
 * fade, rise stagger, bottom sheet) are NOT gated — they are not motion-sickness
 * loops. Handoff reds map to var(--accent) so motion follows the seller's accent
 * + light/dark theme; the LIVE badge keeps its intentional #e11d48.
 * ════════════════════════════════════════════════════════════════════════════ */
/* one-shots */
@keyframes sflScreenIn { from { opacity: 0; } to { opacity: 1; } } /* sticky-safe: opacity only (never a transform on a sticky-header ancestor → sticky stays intact) */
@keyframes sflBeat { 0% { opacity: .25; transform: scale(.96); } 40% { opacity: 1; transform: scale(1); } 54% { transform: scale(1.07); } 66% { transform: scale(.98); } 78% { transform: scale(1.04); } 100% { opacity: 1; transform: scale(1); } }
/* loops — transform/opacity only */
@keyframes sflFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes sflRingPulse { 0% { transform: scale(1); opacity: .55; } 70%,100% { transform: scale(2.3); opacity: 0; } }
@keyframes sflSheen { 0% { transform: translateX(-180%) skewX(-18deg); } 100% { transform: translateX(320%) skewX(-18deg); } }
@keyframes sflLift { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-1.5px); } }

/* universal per-navigation entrance — opacity fade (safe above sticky headers) */
[data-redesign] .sfl-anim-screen { animation: sflScreenIn .42s ease both; }

/* UNIVERSAL slide + fade for screen CONTENT (whole app, every screen). The
 * screen root's FIRST child is the sticky header; content is nth-child(n+2).
 * We slide the content (a SIBLING of the header) — never the header or any of
 * its ancestors — so every sticky header stays pinned on scroll. sflRise =
 * opacity 0→1 + translateY 12px→0, staggered .04s→.4s. transform/opacity only,
 * one-shot, GPU-friendly. Gated by prefers-reduced-motion + [data-motion=off]. */
/* fill: BACKWARDS (not both) so NO transform persists after the entrance — this
 * protects any content-INTERNAL sticky element (e.g. Products' sub-header): a
 * lingering translateY(0) would otherwise make it stick to the transformed
 * content box instead of the scroll viewport. The main screen header is child(1),
 * never in this set, so it is always safe regardless. */
[data-redesign] .sfl-anim-screen > * > *:nth-child(n+2) { animation: sflRise .5s cubic-bezier(.22,1,.36,1) backwards; }
[data-redesign] .sfl-anim-screen > * > *:nth-child(2){animation-delay:.04s}
[data-redesign] .sfl-anim-screen > * > *:nth-child(3){animation-delay:.10s}
[data-redesign] .sfl-anim-screen > * > *:nth-child(4){animation-delay:.16s}
[data-redesign] .sfl-anim-screen > * > *:nth-child(5){animation-delay:.22s}
[data-redesign] .sfl-anim-screen > * > *:nth-child(6){animation-delay:.28s}
[data-redesign] .sfl-anim-screen > * > *:nth-child(7){animation-delay:.34s}
[data-redesign] .sfl-anim-screen > * > *:nth-child(n+8){animation-delay:.40s}

/* staggered rise for NON-sticky content lists (opt-in utility; Slice 2) */
[data-redesign] .sfl-anim-stagger > * { animation: sflRise .5s cubic-bezier(.22,1,.36,1) both; }
[data-redesign] .sfl-anim-stagger > *:nth-child(1){animation-delay:.04s}
[data-redesign] .sfl-anim-stagger > *:nth-child(2){animation-delay:.10s}
[data-redesign] .sfl-anim-stagger > *:nth-child(3){animation-delay:.16s}
[data-redesign] .sfl-anim-stagger > *:nth-child(4){animation-delay:.22s}
[data-redesign] .sfl-anim-stagger > *:nth-child(5){animation-delay:.28s}
[data-redesign] .sfl-anim-stagger > *:nth-child(6){animation-delay:.34s}
[data-redesign] .sfl-anim-stagger > *:nth-child(n+7){animation-delay:.40s}

/* title heartbeat */
[data-redesign] .sfl-anim-beat { animation: sflBeat 3.4s ease-in-out infinite; transform-origin: left center; }
/* Settings "Need help?" badge — CONTINUOUS attention beat while the Settings
   screen is mounted (infinite; owner wanted it to keep pulsing, not stop after 3).
   Reuses the sflBeat keyframe; center-origin so the square badge pulses evenly.
   Gated below like every loop (kill switch + prefers-reduced-motion). */
[data-redesign] .sfl-anim-beat3 { animation: sflBeat 1.05s ease-in-out infinite; transform-origin: center; }
/* logo/avatar bob */
[data-redesign] .sfl-anim-float { animation: sflFloat 4.5s ease-in-out infinite; }
/* status-dot pulse — duration via --sfl-dur; reuses the existing sflDot keyframe */
[data-redesign] .sfl-anim-dot { animation: sflDot var(--sfl-dur, 1.1s) ease-in-out infinite; }

/* LIVE badge ring — GPU: scaling ::after (static box-shadow, animated transform/opacity) */
[data-redesign] .sfl-anim-live { position: relative; }
[data-redesign] .sfl-anim-live::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 0 0 2px #e11d48; pointer-events: none; animation: sflRingPulse 1.8s ease-out infinite; }

/* Session V2 (owner) "End Session" — gentle red glow that breathes. GPU-safe: a STATIC
   red glow box-shadow on a ::after, only OPACITY animates (no per-frame box-shadow
   repaint). Single header button, never a per-row loop. Gated below with the others. */
@keyframes sflEndGlow { 0%, 100% { opacity: .3; } 50% { opacity: .85; } }
[data-redesign] .sfl-anim-endpulse { position: relative; }
[data-redesign] .sfl-anim-endpulse::after { content: ""; position: absolute; inset: -1px; border-radius: inherit; box-shadow: 0 0 9px 1px rgba(214,69,69,.9); pointer-events: none; animation: sflEndGlow 2s ease-in-out infinite; }

/* "Session continues …" loading dots — opacity-only, staggered (sub-step 5).
   Gated below with every other loop (kill switch + prefers-reduced-motion). */
@keyframes sflEllip { 0%, 80%, 100% { opacity: .2; } 40% { opacity: 1; } }
[data-redesign] .sfl-anim-ellip > i { opacity: .2; animation: sflEllip 1.4s ease-in-out infinite; }
[data-redesign] .sfl-anim-ellip > i:nth-child(2) { animation-delay: .2s; }
[data-redesign] .sfl-anim-ellip > i:nth-child(3) { animation-delay: .4s; }

/* diagonal sheen — GPU: a translating skewed highlight (host must clip: overflow hidden) */
[data-redesign] .sfl-anim-sheen { position: relative; overflow: hidden; }
[data-redesign] .sfl-anim-sheen::after { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 35%; background: linear-gradient(100deg, transparent, rgba(255,255,255,.28), transparent); transform: translateX(-180%) skewX(-18deg); pointer-events: none; animation: sflSheen 3.6s linear infinite; }

/* button glow-lift — transform lift loop ONLY; the glow is a STATIC shadow (set
 * inline where used), so there is zero per-frame box-shadow repaint. */
[data-redesign] .sfl-anim-glow { animation: sflLift 2.3s ease-in-out infinite; }

/* bottom-sheet entrance (migrated from Admin inline) — one-shot */
[data-redesign] .sfl-anim-sheet { animation: sflSheet .26s cubic-bezier(.22,1,.36,1); }

/* springy global button press (handoff micro-interaction) */
[data-redesign] button { transition: transform .14s cubic-bezier(.34,1.56,.64,1), filter .18s ease; }
[data-redesign] button:active { transform: scale(.92); }
@media (hover: hover) { [data-redesign] button:hover { filter: brightness(1.06); } }

/* ════════════ Slice 2 — remaining animations (same GPU discipline) ═══════════
 * transform/opacity only; NO box-shadow/background-position/text-shadow/blur
 * loops on the app-shell path. The 1-Click button is deliberately NOT looped
 * (its accent glow is a STATIC inline box-shadow) so a 150-row feed never runs
 * ~150 concurrent loops. Every loop below is gated by BOTH switches (further
 * down). Handoff reds map to var(--accent); the LIVE badge stays #e11d48. */
@keyframes sflHeart { 0%,28%,100% { transform: scale(1); } 14% { transform: scale(1.22); } 21% { transform: scale(1.05); } 35% { transform: scale(1.16); } 42% { transform: scale(1); } }
@keyframes sflTextGlow { 0%,100% { opacity: .66; } 50% { opacity: 1; } } /* opacity-pulse — NOT a text-shadow repaint loop */
@keyframes sflWiggle { 0%,86%,100% { transform: translateY(0) rotate(0); } 90% { transform: translateY(-2px) rotate(-11deg); } 95% { transform: translateY(-1px) rotate(8deg); } }

/* TikTok/Facebook channel-chip double-thump — scale only */
[data-redesign] .sfl-anim-heart { animation: sflHeart 1.7s ease-in-out infinite; }
/* section-label / "Need help?" glow — GENTLE opacity pulse (no text-shadow loop) */
[data-redesign] .sfl-anim-textglow { animation: sflTextGlow 2.8s ease-in-out infinite; }
/* Telegram support icon — one element, GPU rotate, infrequent */
[data-redesign] .sfl-anim-wiggle { animation: sflWiggle 3.2s ease-in-out infinite; }

/* Live comment enter: .sfl-comm-row already carries `animation: sflComm`
 * (opacity + translateY, no blur). Add content-visibility so off-viewport rows
 * skip layout+paint; the `auto` intrinsic size remembers the real row height
 * after first render, keeping scroll jump minimal. */
[data-redesign] .sfl-comm-row { content-visibility: auto; contain-intrinsic-size: auto 56px; }

/* micro-interactions — hover/active transitions, NOT loops */
[data-redesign] .sfl-navbtn svg { transition: transform .2s cubic-bezier(.34,1.56,.64,1); }
[data-redesign] .sfl-navbtn:active svg { transform: scale(.86); }
@media (hover: hover) {
  [data-redesign] .sfl-navbtn:hover svg { transform: translateY(-3px) scale(1.16); }
  [data-redesign] img { transition: transform .25s cubic-bezier(.34,1.56,.64,1); }
  [data-redesign] img:hover { transform: scale(1.06) rotate(-2deg); }
}
/* receipt previews (ReceiptSheet + Receipt format): a large picture must never tilt or grow on
   hover (it covered the Send button and added a horizontal scrollbar). Other images unchanged. */
[data-redesign] img.sfl-no-hover,
[data-redesign] img.sfl-no-hover:hover { transition: none; transform: none; }

/* kill switch — in-app motion toggle disables LOOPS only (one-shots stay) */
[data-redesign][data-motion="off"] .sfl-anim-beat,
[data-redesign][data-motion="off"] .sfl-anim-beat3,
[data-redesign][data-motion="off"] .sfl-anim-float,
[data-redesign][data-motion="off"] .sfl-anim-dot,
[data-redesign][data-motion="off"] .sfl-anim-glow,
[data-redesign][data-motion="off"] .sfl-anim-live::after,
[data-redesign][data-motion="off"] .sfl-anim-endpulse::after,
[data-redesign][data-motion="off"] .sfl-anim-sheen::after,
[data-redesign][data-motion="off"] .sfl-anim-heart,
[data-redesign][data-motion="off"] .sfl-anim-textglow,
[data-redesign][data-motion="off"] .sfl-anim-wiggle,
[data-redesign][data-motion="off"] .sfl-comm-row,
[data-redesign][data-motion="off"] .sfl-glow-a,
[data-redesign][data-motion="off"] .sfl-glow-cyan,
[data-redesign][data-motion="off"] .sfl-anim-ellip > i,
[data-redesign][data-motion="off"] .sfl-grid { animation: none !important; }
[data-redesign][data-motion="off"] .sfl-anim-ellip > i { opacity: .6 !important; } /* static dots */
/* content slide collapses to visible (no slide) under the kill switch */
[data-redesign][data-motion="off"] .sfl-anim-screen > * > *:nth-child(n+2) { animation: none !important; opacity: 1 !important; transform: none !important; }

/* prefers-reduced-motion — kill loops; keep a minimal one-shot fade */
@media (prefers-reduced-motion: reduce) {
  [data-redesign] .sfl-anim-beat,
  [data-redesign] .sfl-anim-beat3,
  [data-redesign] .sfl-anim-float,
  [data-redesign] .sfl-anim-dot,
  [data-redesign] .sfl-anim-glow,
  [data-redesign] .sfl-anim-live::after,
  [data-redesign] .sfl-anim-endpulse::after,
  [data-redesign] .sfl-anim-sheen::after,
  [data-redesign] .sfl-anim-heart,
  [data-redesign] .sfl-anim-textglow,
  [data-redesign] .sfl-anim-wiggle,
  [data-redesign] .sfl-comm-row,
  [data-redesign] .sfl-glow-a,
  [data-redesign] .sfl-glow-cyan,
  [data-redesign] .sfl-anim-ellip > i,
  [data-redesign] .sfl-grid { animation: none !important; }
  [data-redesign] .sfl-anim-ellip > i { opacity: .6; } /* static dots */
  [data-redesign] .sfl-anim-textglow { opacity: 1; } /* label stays fully visible */
  [data-redesign] .sfl-anim-stagger > * { animation: none; opacity: 1; transform: none; }
  [data-redesign] .sfl-anim-screen > * > *:nth-child(n+2) { animation: none; opacity: 1; transform: none; }
  [data-redesign] button { transition: none; }
  [data-redesign] button:active { transform: none; }
  [data-redesign] .sfl-navbtn svg, [data-redesign] img { transition: none; }
  [data-redesign] .sfl-navbtn:hover svg, [data-redesign] img:hover { transform: none; }
}

[data-redesign] {
  font-family: var(--font-ui);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
[data-redesign] * { box-sizing: border-box; }
[data-redesign] button { font-family: var(--font-ui); }
[data-redesign] input { font-family: var(--font-ui); }

/* iOS app shell ONLY (html.sfl-ios-shell — set by applyIOSShellClass, incl. the
 * ?ios=1 browser preview). WKWebView auto-zooms the whole page when a focused
 * form control's font-size is <16px; every redesign input is 9.5–15px, so a
 * 16px floor removes the zoom trigger at the source (the accessibility-correct
 * fix; the viewport zoom lock remains only as a backstop). !important because
 * most controls carry an inline fontSize. Android/web: class never set → 0 diff. */
html.sfl-ios-shell [data-redesign] input,
html.sfl-ios-shell [data-redesign] select,
html.sfl-ios-shell [data-redesign] textarea { font-size: 16px !important; }

/* Header-band search inputs (Orders / Products / Customers) sit on the indigo
 * --header-bg with color:var(--on-header) (white) typed text. The PLACEHOLDER
 * had no rule → browser-default dark gray → barely visible on indigo. Scope a
 * readable translucent-white placeholder to these inputs only (form inputs on
 * light --surface backgrounds keep their default dark placeholder). opacity:1
 * because Firefox dims placeholders by default. PRE-EXISTING contrast fix. */
[data-redesign] .sfl-header-search::placeholder { color: rgba(255,255,255,.72); opacity: 1; }

/* Phone column: status bar -> scrollable content (flex:1) -> bottom nav.
 * max-width 430px keeps the mobile design phone-accurate on desktop preview;
 * on a real phone it is full-bleed. (No workbench/sidebar — per the spec.) */
[data-redesign] .sfl-stage {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  justify-content: center;
  background: var(--app-bg);
}
[data-redesign] .sfl-phone {
  position: relative;
  width: 100%;
  /* No max-width: the column fills the viewport. Phones (<430px) are byte-identical
   * (width:100% already < 430). Tablets now FILL the screen instead of pinning a
   * 430px column to the left with blank space. Desktop/laptop get the sidebar via the
   * pointer:fine @media below; touch devices (tablets/phones) stay full-width mobile. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--app-bg);
}
[data-redesign] .sfl-scroll {
  position: relative;
  z-index: 2;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}
[data-redesign] .sfl-scroll::-webkit-scrollbar { width: 0; height: 0; }

/* ── Bottom nav (mobile baseline). These classes are BYTE-EQUAL to the previous
 * inline styles (container = the old nav <div>; .sfl-navbtn = the old navBtn();
 * .is-active = the old active background/color). Moving them to classes lets the
 * desktop @media below restyle the SAME nav into a left sidebar with no !important
 * and no duplicated component. ≤899px renders exactly as before. */
[data-redesign] .sfl-nav {
  position: relative;
  z-index: 3;
  flex-shrink: 0;
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  padding: 8px 8px calc(8px + env(safe-area-inset-bottom));
  background: var(--nav-bg);
  border-top: 1px solid var(--border);
  backdrop-filter: saturate(1.4) blur(14px);
}
[data-redesign] .sfl-navbtn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 7px 0;
  border: none;
  border-radius: 12px;
  cursor: pointer;
  font-family: var(--font-ui);
  background: transparent;
  color: var(--text-muted);
}
[data-redesign] .sfl-navbtn.is-active {
  background: var(--accent-soft);
  color: var(--accent-fg);
}
/* Sidebar-only elements — hidden on mobile (must come AFTER .sfl-navbtn so the
 * Admin button's display:none wins over .sfl-navbtn's display:flex). */
[data-redesign] .sfl-nav-logo { display: none; }
[data-redesign] .sfl-nav-admin { display: none; }

/* 🛒 basket badge (Live feed) — size is PLATFORM-SCOPED (Jeff-verified on real
 * devices): the DEFAULT is the slightly larger pill (Android APK + web/desktop
 * both read too small at the compact size); the iOS shell alone keeps the
 * compact pill via the html.sfl-ios-shell override below (same proven scoping
 * as the iOS 16px input fix). */
[data-redesign] .sfl-basket-badge { font-size: 12.5px; gap: 3px; padding: 3px 9px; }
html.sfl-ios-shell [data-redesign] .sfl-basket-badge { font-size: 10px; gap: 2px; padding: 1px 6px; }

/* ── DESKTOP/LAPTOP ONLY (≥900px AND a fine pointer = mouse/trackpad): the bottom
 * nav becomes a LEFT SIDEBAR and content goes full-width. `pointer: fine` excludes
 * ALL touch devices — Samsung tablets (portrait OR landscape) + phones + the APK
 * (pointer: coarse) NEVER get the sidebar; they stay full-width mobile. This fixes
 * the tablet-portrait bug where ~800px width hit min-width:900 partially / left a
 * 430px column pinned left. Mobile (<900 or any touch) is byte-identical to before. */
@media (min-width: 900px) and (pointer: fine) {
  [data-redesign] .sfl-phone {
    max-width: none;            /* full-width content on desktop */
    flex-direction: row;        /* sidebar | content */
  }
  [data-redesign] .sfl-nav {
    order: -1;                  /* move to the LEFT without changing DOM order */
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    width: 240px;
    flex-shrink: 0;
    height: 100%;
    padding: 16px 12px;
    gap: 4px;
    border-top: none;
    border-right: 1px solid var(--border);
    overflow-y: auto;
  }
  [data-redesign] .sfl-nav-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px 16px;
    margin-bottom: 4px;
  }
  [data-redesign] .sfl-navbtn {
    flex: 0 0 auto;             /* don't stretch tall like the bottom row did */
    flex-direction: row;
    justify-content: flex-start;
    gap: 12px;
    padding: 11px 14px;
    position: relative;        /* for the active accent bar */
  }
  [data-redesign] .sfl-navbtn span {
    font-size: 13px !important; /* override the inline 10px label — desktop only */
  }
  [data-redesign] .sfl-navbtn.is-active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 9px;
    bottom: 9px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--accent-fg);
  }
  [data-redesign] .sfl-nav-admin { display: flex; }  /* show in the sidebar (owner) */
}

/* Decorative dark-bg layers (dark theme only) — dc.html L84–87. */
[data-redesign] .sfl-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 38px 38px;
  animation: sflGrid 7s linear infinite;
  opacity: .6;
}
[data-redesign] .sfl-glow-a {
  position: absolute;
  width: 360px; height: 360px; top: -130px; right: -130px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--glow-a) 0%, rgba(79,70,229,0) 70%);
  animation: sflGlow 9s ease-in-out infinite;
}
[data-redesign] .sfl-glow-cyan {
  position: absolute;
  width: 300px; height: 300px; bottom: 10px; left: -120px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--glow-cyan) 0%, rgba(34,211,238,0) 70%);
  animation: sflGlow 11s ease-in-out infinite reverse;
}

[data-redesign] .sfl-comm-row { animation: sflComm .4s ease-out; }

/* ── Auth pop-up split-screen (web landing only — AuthModal). DEFAULT = single column:
 * the brand panel is hidden and the form fills the card (BYTE-IDENTICAL to before, so
 * phones/narrow web + the APK full-screen path are unchanged). At ≥720px viewport the
 * card widens and becomes a two-column split: brand panel | form. CSS-only collapse —
 * no JS, no media query in inline styles. Renders ONLY when screen === "landing". */
[data-redesign] .sfl-authcard { max-width: 420px; }
[data-redesign] .sfl-authbrand { display: none; }       /* hidden on narrow */
[data-redesign] .sfl-authform { width: 100%; }
@media (min-width: 720px) {
  [data-redesign] .sfl-authcard { max-width: 860px; }
  [data-redesign] .sfl-authsplit { display: flex; align-items: stretch; }
  [data-redesign] .sfl-authbrand { display: flex; flex: 1 1 0; }
  [data-redesign] .sfl-authform { flex: 1 1 0; min-width: 0; }
}

/* ═══ Landing page animations (ADDITIVE — landing-only .sfl-lp-* classes).
   Reuses the existing sflRise / sflGlow / sflLive / sflDot keyframes (untouched);
   only the landing-specific loops below are new. The landing never renders in the
   app shell (anonScreen gate), so none of this affects the APK/iOS. */
@keyframes sflLpFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes sflLpPrint {
  0%   { transform: translateY(-88%); opacity: 1; }
  62%  { transform: translateY(0);    opacity: 1; }
  86%  { transform: translateY(0);    opacity: 1; }
  100% { transform: translateY(6%);   opacity: 0; }
}
@keyframes sflLpBub {
  0%   { opacity: 0; transform: translateY(14px) scale(.92); }
  14%  { opacity: 1; transform: translateY(4px)  scale(1); }
  62%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-46px) scale(1.02); }
}

/* hero entrance (staggered via inline animation-delay) */
.sfl-lp-rise { animation: sflRise .6s ease-out both; }

/* soft floating glow blobs behind the hero scene */
.sfl-lp-blob { position: absolute; border-radius: 50%; filter: blur(46px); pointer-events: none; z-index: 0; }
.sfl-lp-blob-a { width: 260px; height: 260px; top: -40px; left: -50px; background: radial-gradient(circle, rgba(99,102,241,.42), rgba(99,102,241,0) 70%); animation: sflGlow 9s ease-in-out infinite; }
.sfl-lp-blob-b { width: 220px; height: 220px; bottom: -30px; right: -40px; background: radial-gradient(circle, rgba(45,212,191,.36), rgba(45,212,191,0) 70%); animation: sflGlow 11s ease-in-out infinite reverse; }

/* gentle device float (card B offset so the two scenes de-sync) */
.sfl-lp-float   { animation: sflLpFloat 5.5s ease-in-out infinite; }
.sfl-lp-float-b { animation: sflLpFloat 6s   ease-in-out infinite; animation-delay: .8s; }

/* thermal printer: label continuously printing out of the slot */
.sfl-lp-print   { animation: sflLpPrint 3.2s ease-in-out infinite; }
.sfl-lp-print-b { animation-delay: 1.6s; }

/* floating live-comment bubbles */
.sfl-lp-bub { position: absolute; z-index: 2; padding: 6px 12px; border-radius: 999px; background: #fff; border: 1px solid #E0DDF0; color: #4F46E5; font-size: 12px; font-weight: 700; box-shadow: 0 10px 24px -10px rgba(23,21,48,.25); pointer-events: none; opacity: 0; animation: sflLpBub 6s ease-in-out infinite; white-space: nowrap; }

/* status dots (reuse existing pulse/blink keyframes) */
.sfl-lp-livedot    { width: 7px; height: 7px; border-radius: 50%; background: #F43F5E; animation: sflLive 1.8s infinite, sflDot 1.8s infinite; }
.sfl-lp-printlight { width: 6px; height: 6px; border-radius: 50%; background: #34D399; animation: sflDot 1.4s infinite; }

/* micro-interactions: hover lift (cards + CTAs) */
.sfl-lp-lift { transition: transform .25s ease, box-shadow .25s ease; }
.sfl-lp-lift:hover { transform: translateY(-3px); }
.sfl-lp-hovshadow:hover { box-shadow: 0 18px 40px -18px rgba(23,21,48,.2); }

/* scroll-triggered reveal (IntersectionObserver adds .sfl-lp-in once) */
.sfl-lp-reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s ease; transition-delay: var(--rv-delay, 0s); }
.sfl-lp-reveal.sfl-lp-in { opacity: 1; transform: translateY(0); }

/* reduced motion: static fallback — kill every loop, show everything immediately */
@media (prefers-reduced-motion: reduce) {
  .sfl-lp-rise, .sfl-lp-blob-a, .sfl-lp-blob-b, .sfl-lp-float, .sfl-lp-float-b,
  .sfl-lp-print, .sfl-lp-livedot, .sfl-lp-printlight { animation: none; }
  .sfl-lp-bub { display: none; }
  .sfl-lp-reveal { opacity: 1; transform: none; transition: none; }
  .sfl-lp-lift, .sfl-lp-lift:hover { transition: none; transform: none; }
}

/* ═══ Landing heartbeat pulse (ADDITIVE — Indigo Classic accent). Cards "beat"
   with a soft indigo glow + a 1px indigo ring at the peak. Lives on the CARD
   element while reveal/hover-lift live on a WRAPPER, so the transforms compose
   (animation transform would otherwise override the reveal/lift transforms). */
@keyframes sflLpBeat {
  0%, 100% { transform: scale(1);    box-shadow: 0 10px 26px -14px rgba(83,74,183,.12), 0 0 0 1px rgba(99,102,241,0); }
  50%      { transform: scale(1.02); box-shadow: 0 14px 34px -12px rgba(83,74,183,.28), 0 0 0 1px rgba(99,102,241,.22); }
}
/* "Most Popular" (Pro) — slightly stronger beat; keeps the card's big indigo
   drop-shadow inside the keyframe so the pulse never flattens its depth. */
@keyframes sflLpBeatPro {
  0%, 100% { transform: scale(1);     box-shadow: 0 30px 60px -24px rgba(79,70,229,.45), 0 0 0 1px rgba(99,102,241,.08); }
  50%      { transform: scale(1.035); box-shadow: 0 32px 64px -20px rgba(79,70,229,.62), 0 0 0 1px rgba(99,102,241,.35); }
}
.sfl-lp-beat     { animation: sflLpBeat 2.2s ease-in-out infinite;    animation-delay: var(--beat-delay, 0s); }
.sfl-lp-beat-pro { animation: sflLpBeatPro 2.2s ease-in-out infinite; animation-delay: var(--beat-delay, 0s); }
@media (prefers-reduced-motion: reduce) {
  .sfl-lp-beat, .sfl-lp-beat-pro { animation: none; } /* static: inline shadows show as before */
}

/* Raffle compact header — below 360px the center "Collecting · n" TEXT hides
   (the pulsing dot stays) so the one-line header never wraps or overflows. */
@media (max-width: 359px) {
  [data-redesign] .sfl-raffle-collect-txt { display: none; }
}

/* ═══ Landing v2 (ADDITIVE — .sfl-l2-* classes only; blueprint
   design-landing/sellerflow-landing-preview.html is the authoritative source
   for every timing/easing below). Landing never renders in the app shell, so
   none of this affects the APK/iOS. Generic helpers (.sfl-lp-reveal/.sfl-lp-lift/
   .sfl-lp-rise/.sfl-lp-livedot) are REUSED from the v1 block above. */

/* hero phone feed — comments slide in, order chips pop after (12s shared loop) */
@keyframes sflL2Feed { 0% { opacity: 0; transform: translateY(14px); } 4% { opacity: 1; transform: translateY(0); } 86% { opacity: 1; } 94%, 100% { opacity: 0; } }
@keyframes sflL2Chip { 0%, 6% { opacity: 0; transform: scale(.85); } 9% { opacity: 1; transform: scale(1); } 86% { opacity: 1; } 94%, 100% { opacity: 0; } }
.sfl-l2-crow { opacity: 0; animation: sflL2Feed 12s linear infinite; }
.sfl-l2-chip { opacity: 0; animation: sflL2Chip 12s linear infinite; }
.sfl-l2-r1 { animation-delay: .4s; }  .sfl-l2-r1 .sfl-l2-chip { animation-delay: 1.1s; }
.sfl-l2-r2 { animation-delay: 2.1s; }
.sfl-l2-r3 { animation-delay: 3.4s; } .sfl-l2-r3 .sfl-l2-chip { animation-delay: 4.1s; }
.sfl-l2-r4 { animation-delay: 5.2s; }
.sfl-l2-r5 { animation-delay: 6.6s; } .sfl-l2-r5 .sfl-l2-chip { animation-delay: 7.3s; }
.sfl-l2-r6 { animation-delay: 8.4s; } .sfl-l2-r6 .sfl-l2-chip { animation-delay: 9.1s; }

/* ring light glow behind the phone */
@keyframes sflL2Ring {
  0%, 100% { box-shadow: 0 0 0 6px rgba(139,92,246,.12), 0 0 90px 30px rgba(139,92,246,.26), inset 0 0 70px rgba(255,255,255,.9); }
  50%      { box-shadow: 0 0 0 6px rgba(139,92,246,.18), 0 0 120px 44px rgba(139,92,246,.38), inset 0 0 90px rgba(255,255,255,1); }
}
.sfl-l2-ring { animation: sflL2Ring 4.5s ease-in-out infinite; }

/* floating hearts rising beside the phone */
@keyframes sflL2Heart { 0% { opacity: 0; transform: translateY(0) scale(.7); } 12% { opacity: 1; } 70% { opacity: .9; } 100% { opacity: 0; transform: translateY(-190px) scale(1.15) rotate(8deg); } }
.sfl-l2-heart { position: absolute; bottom: 0; left: 8px; font-size: 1.15rem; opacity: 0; animation: sflL2Heart 3.6s linear infinite; }
.sfl-l2-h2 { animation-delay: .9s; left: 0; }
.sfl-l2-h3 { animation-delay: 1.7s; left: 16px; }
.sfl-l2-h4 { animation-delay: 2.6s; left: 6px; }

/* gentle bobbing (slip card, seller photo, printer) */
@keyframes sflL2Slip { 0%, 100% { transform: rotate(4deg) translateY(0); } 50% { transform: rotate(4deg) translateY(-8px); } }
@keyframes sflL2Seller { 0%, 100% { transform: rotate(-5deg) translateY(0); } 50% { transform: rotate(-5deg) translateY(-7px); } }
@keyframes sflL2Bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
.sfl-l2-slipfloat { animation: sflL2Slip 5s ease-in-out infinite; }
.sfl-l2-sellerbob { animation: sflL2Seller 4.5s ease-in-out infinite; }
.sfl-l2-printerbob { animation: sflL2Bob 5s ease-in-out infinite; }

/* thermal printer emitting a slip (grows from the slot, tears off, repeats) */
@keyframes sflL2Print { 0% { transform: scaleY(.06); } 10% { transform: scaleY(.06); } 55% { transform: scaleY(1); } 86% { transform: scaleY(1); opacity: 1; } 92% { opacity: 0; } 93%, 100% { transform: scaleY(.06); opacity: 0; } }
.sfl-l2-prpaper { transform-origin: top; animation: sflL2Print 5.5s ease-in-out infinite; }

/* door-closing dashboard assembly — pieces slide in when .sfl-l2-on lands
   (IntersectionObserver), then the chart bars grow with a stagger */
.sfl-l2-piece { transition: transform .9s cubic-bezier(.22,.9,.3,1), opacity .9s; opacity: 0; }
.sfl-l2-ptop { transform: translateY(-140%); }
.sfl-l2-pleft { transform: translateX(-130%); }
.sfl-l2-pright { transform: translateX(130%); }
.sfl-l2-on .sfl-l2-piece { transform: none; opacity: 1; }
.sfl-l2-on .sfl-l2-ptop { transition-delay: .05s; }
.sfl-l2-on .sfl-l2-pleft, .sfl-l2-on .sfl-l2-pright { transition-delay: .3s; }
.sfl-l2-bar { transform: scaleY(0); transform-origin: bottom; transition: transform .7s cubic-bezier(.22,.9,.3,1); }
.sfl-l2-on .sfl-l2-bar { transform: scaleY(1); }
.sfl-l2-on .sfl-l2-bar:nth-child(1) { transition-delay: .9s; }
.sfl-l2-on .sfl-l2-bar:nth-child(2) { transition-delay: 1s; }
.sfl-l2-on .sfl-l2-bar:nth-child(3) { transition-delay: 1.1s; }
.sfl-l2-on .sfl-l2-bar:nth-child(4) { transition-delay: 1.2s; }
.sfl-l2-on .sfl-l2-bar:nth-child(5) { transition-delay: 1.3s; }
.sfl-l2-on .sfl-l2-bar:nth-child(6) { transition-delay: 1.4s; }
.sfl-l2-on .sfl-l2-bar:nth-child(7) { transition-delay: 1.5s; }

/* nav features dropdown (hover-open on desktop; hidden with the nav links on mobile) */
.sfl-l2-dd { position: relative; }
.sfl-l2-ddmenu { position: absolute; top: 130%; left: -14px; background: #fff; border: 1px solid #e6e5f4; border-radius: 14px; box-shadow: 0 18px 44px rgba(23,20,58,.14); padding: 10px; min-width: 230px; opacity: 0; visibility: hidden; transform: translateY(8px); transition: .22s; z-index: 45; }
.sfl-l2-dd:hover .sfl-l2-ddmenu, .sfl-l2-dd:focus-within .sfl-l2-ddmenu { opacity: 1; visibility: visible; transform: none; }

/* FAQ +/summary marker rotation is inline (React state); hover lifts reuse .sfl-lp-lift */

/* responsive — mirror the blueprint's breakpoints */
.sfl-l2-hero { display: grid; grid-template-columns: 1.05fr .95fr; gap: 56px; align-items: center; }
.sfl-l2-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.sfl-l2-bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 18px; }
.sfl-l2-span3 { grid-column: span 3; } .sfl-l2-span2 { grid-column: span 2; }
.sfl-l2-dash { display: grid; grid-template-columns: 170px 1fr; gap: 14px; max-width: 860px; margin: 0 auto; }
.sfl-l2-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.sfl-l2-deep { display: grid; grid-template-columns: 1fr 1fr; gap: 46px; align-items: center; }
.sfl-l2-guides { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.sfl-l2-quotes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.sfl-l2-sellers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.sfl-l2-fgrid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 34px; }
@media (max-width: 900px) {
  .sfl-l2-hero { grid-template-columns: 1fr; gap: 44px; }
  .sfl-l2-guides { grid-template-columns: repeat(2, 1fr); }
  .sfl-l2-slip { right: 2px !important; }
  .sfl-l2-printer { right: -6px !important; width: 124px !important; top: 96px !important; }
  .sfl-l2-sellercard { left: -10px !important; width: 150px !important; }
  .sfl-l2-sellercard .sfl-l2-sellerimg { height: 165px !important; }
}
@media (max-width: 820px) {
  .sfl-l2-navlinks { display: none !important; }
  .sfl-l2-steps, .sfl-l2-quotes, .sfl-l2-deep, .sfl-l2-sellers { grid-template-columns: 1fr; }
  .sfl-l2-deep { gap: 26px; }
  .sfl-l2-span3, .sfl-l2-span2 { grid-column: span 6; }
  .sfl-l2-fgrid { grid-template-columns: 1fr 1fr; }
  .sfl-l2-deepflip .sfl-l2-deepvis { order: 0; }
}
@media (min-width: 821px) { .sfl-l2-deepflip .sfl-l2-deepvis { order: 2; } }
@media (max-width: 760px) { .sfl-l2-dash { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .sfl-l2-kpis, .sfl-l2-guides { grid-template-columns: 1fr; } }

/* reduced motion — kill every v2 loop; assembly + bars land fully visible */
@media (prefers-reduced-motion: reduce) {
  .sfl-l2-crow, .sfl-l2-chip { animation: none; opacity: 1; }
  .sfl-l2-ring, .sfl-l2-slipfloat, .sfl-l2-sellerbob, .sfl-l2-printerbob, .sfl-l2-prpaper { animation: none; }
  .sfl-l2-heart { display: none; }
  .sfl-l2-piece, .sfl-l2-bar { transition: none; opacity: 1 !important; transform: none !important; }
  .sfl-l2-ddmenu { transition: none; }
}

/* ── LIVE SESSION settings — centered explainer modal + spring toggle (approved mockup) ──
   Modal: centered on every size, width min(420px, 90vw), radius 20, over a ~40% backdrop.
   Motion: fade + scale .96→1 in 200ms ease-out + backdrop fade; toggle knob 180ms small
   spring; toast entrance 200ms. CSS transitions only. All off under prefers-reduced-motion. */
.sfl-lsm-backdrop { position: fixed; inset: 0; z-index: 1300; display: grid; place-items: center; padding: 16px; box-sizing: border-box; background: rgba(20, 22, 40, .42); opacity: 0; transition: opacity .2s ease; }
.sfl-lsm-backdrop.show { opacity: 1; }
.sfl-lsm-modal { width: min(420px, 90vw); max-height: calc(100vh - 32px); overflow-y: auto; box-sizing: border-box; background: var(--surface); border-radius: 20px; padding: 22px 20px 18px; box-shadow: 0 20px 60px rgba(0, 0, 0, .28); opacity: 0; transform: scale(.96); transition: transform .2s ease-out, opacity .2s ease-out; }
.sfl-lsm-backdrop.show .sfl-lsm-modal { opacity: 1; transform: scale(1); }
.sfl-lsm-field { display: flex; align-items: center; gap: 8px; border: 1.5px solid var(--border); border-radius: 14px; padding: 12px 14px; margin-bottom: 6px; background: var(--surface-2); }
.sfl-lsm-field:focus-within { border-color: var(--accent); }
.sfl-ls-track { transition: background .18s ease; }
.sfl-ls-knob { transition: transform .18s cubic-bezier(.34, 1.56, .64, 1); }
.sfl-ls-rows > :last-child { border-bottom: 0 !important; }
.sfl-toast-in { animation: sflToastIn .2s ease both; }
@keyframes sflToastIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .sfl-lsm-backdrop, .sfl-lsm-modal, .sfl-ls-track, .sfl-ls-knob { transition: none; }
  .sfl-toast-in { animation: none; }
}


/* Pickup Status — "Checking…" on the Check now button while a job is active.
   Hourglass flips (1.4s), dots pulse in sequence (1.2s, .2s apart). transform/opacity
   only; static hourglass + dots under prefers-reduced-motion and [data-motion=off]. */
@keyframes rdPtHgFlip { 0% { transform: rotate(0); } 40% { transform: rotate(180deg); } 55% { transform: rotate(180deg); } 95% { transform: rotate(360deg); } 100% { transform: rotate(360deg); } }
@keyframes rdPtHgDot { 0%, 100% { opacity: .15; } 50% { opacity: 1; } }
[data-redesign] .rd-pt-hg { flex-shrink: 0; transform-origin: center; animation: rdPtHgFlip 1.4s linear infinite; }
[data-redesign] .rd-pt-hg-label::before { content: attr(data-label); }
[data-redesign] .rd-pt-hg-dots { display: inline-flex; width: 1.1em; }
[data-redesign] .rd-pt-hg-dots > i { font-style: normal; opacity: .15; animation: rdPtHgDot 1.2s infinite; }
[data-redesign] .rd-pt-hg-dots > i::before { content: "."; }
[data-redesign] .rd-pt-hg-dots > i:nth-child(2) { animation-delay: .2s; }
[data-redesign] .rd-pt-hg-dots > i:nth-child(3) { animation-delay: .4s; }
[data-redesign] .rd-pt-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
[data-redesign][data-motion="off"] .rd-pt-hg,
[data-redesign][data-motion="off"] .rd-pt-hg-dots > i { animation: none; opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  [data-redesign] .rd-pt-hg,
  [data-redesign] .rd-pt-hg-dots > i { animation: none; opacity: 1; }
}

/* Build 13 — Connect button tap feedback (Dashboard ConnectButton): a small spinner beside
   "Connecting…". transform only; prefers-reduced-motion and [data-motion=off] → no spinner,
   the text alone says it. */
@keyframes sflConnSpin { to { transform: rotate(360deg); } }
[data-redesign] .sfl-conn-spin { display: inline-block; flex-shrink: 0; width: 10px; height: 10px; box-sizing: border-box; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: sflConnSpin .8s linear infinite; }
[data-redesign][data-motion="off"] .sfl-conn-spin { display: none; }
@media (prefers-reduced-motion: reduce) {
  [data-redesign] .sfl-conn-spin { display: none; }
}

/* ── LIVE PLATFORM PICKER (admin preview; Dashboard lpkPicker) ─────────────────────
 * Durations + mode come from adapters/livePicker.ts as CSS variables (--lpk-*).
 * Keyframes are the owner-approved ones, prefixed sflLpk* so they never replace the
 * app's existing sflBeat. Idle emblem/name/blink loops run only while the four tiles
 * are shown, no tile is chosen, the tile is enabled and the mode isn't "off". */
@keyframes sflLpkBeat{0%,100%{transform:scale(1)}10%{transform:scale(1.1)}20%{transform:scale(1)}30%{transform:scale(1.06)}40%{transform:scale(1)}}
@keyframes sflLpkBob{0%,100%{transform:translateY(2px)}50%{transform:translateY(-6px)}}
@keyframes sflLpkSway{0%,100%{transform:rotate(-9deg)}50%{transform:rotate(9deg)}}
@keyframes sflLpkFlip{0%,55%{transform:rotateY(0deg)}85%,100%{transform:rotateY(360deg)}}
@keyframes sflLpkWordBeat{0%,100%{transform:scale(1);letter-spacing:0}10%{transform:scale(1.06);letter-spacing:.03em}20%{transform:scale(1);letter-spacing:0}30%{transform:scale(1.03)}40%{transform:scale(1)}}
@keyframes sflLpkWordSlide{0%,100%{transform:translateX(0)}50%{transform:translateX(7px)}}
@keyframes sflLpkWordLean{0%,100%{transform:skewX(0deg)}50%{transform:skewX(-12deg)}}
@keyframes sflLpkWordHop{0%,55%,100%{transform:translateY(0)}65%{transform:translateY(-6px)}75%{transform:translateY(0)}85%{transform:translateY(-3px)}}
@keyframes sflLpkBlink{0%,100%{opacity:1}50%{opacity:.25}}
@keyframes sflLpkPop{0%{opacity:0;transform:translateY(-10px) scale(.96)}100%{opacity:1;transform:translateY(0) scale(1)}}
@keyframes sflLpkFly{0%{opacity:.35;transform:translateY(120px) scale(1.06)}70%{opacity:1}100%{opacity:1;transform:translateY(0) scale(1)}}

[data-redesign] .sfl-lpk-slot {
  display: flex; flex-direction: column; flex: 1 1 0; min-height: 64px; max-height: 170px; opacity: 1;
  transition: opacity var(--lpk-fade) ease, flex-grow var(--lpk-collapse) ease, max-height var(--lpk-collapse) ease,
    min-height var(--lpk-collapse) ease, margin var(--lpk-collapse) ease;
}
[data-redesign] .sfl-lpk-slot > .sfl-lpk-tile { flex: 1; min-height: 0; }
[data-redesign] .sfl-lpk-slot.is-hidden {
  opacity: 0; flex-grow: 0; max-height: 0; min-height: 0; margin-top: 0 !important; overflow: hidden; pointer-events: none;
  transition: opacity var(--lpk-fade) ease, flex-grow var(--lpk-collapse) ease var(--lpk-collapse-delay),
    max-height var(--lpk-collapse) ease var(--lpk-collapse-delay), min-height var(--lpk-collapse) ease var(--lpk-collapse-delay),
    margin var(--lpk-collapse) ease var(--lpk-collapse-delay);
}
/* Chosen slot: held at its tap-time height (inline height, flex 0 0 auto) until the
   collapse starts, then shrinks to --lpk-chosen-to together with the others' collapse. */
@keyframes sflLpkChosen{to{height:var(--lpk-chosen-to);margin-top:0}}
@keyframes sflLpkHold{from{max-height:0;margin-top:0;padding-top:0;padding-bottom:0;border-width:0;overflow:hidden;pointer-events:none}to{max-height:1200px}}
[data-redesign] .sfl-lpk-slot.is-chosen { max-height: none; transition: none; animation: sflLpkChosen var(--lpk-collapse) ease var(--lpk-collapse-delay) forwards; }
[data-redesign] .sfl-lpk-slot.is-chosen > .sfl-lpk-tile { transform: scale(.98); transition: transform var(--lpk-collapse) ease var(--lpk-collapse-delay); }
[data-redesign] .sfl-lpk-tile:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
[data-redesign] .sfl-lpk-panel { animation: sflLpkPop var(--lpk-pop) ease-out var(--lpk-pop-delay) both, sflLpkHold 1ms linear var(--lpk-pop-delay) both; }
[data-redesign] .sfl-lpk-panel.sfl-lpk-panel--now { animation: sflLpkPop var(--lpk-pop) ease-out both; }

/* Emblem column: one scale unit (--lpk-u = 1px at full size) tied to the tile's height
   (container query), so emblem + LIVE tag always sit inside the tile. Full size =
   78×82 (emblem area 74, tag overlapping its bottom edge). Shapes incl. ring ≤ 74. */
[data-redesign] .sfl-lpk-col { --lpk-u: 1px; position: relative; flex-shrink: 0; width: calc(var(--lpk-u) * 78); height: calc(var(--lpk-u) * 82); }
@supports (container-type: size) {
  [data-redesign] .sfl-lpk-tile { container-type: size; }
  [data-redesign] .sfl-lpk-col { --lpk-u: calc(min(82px, 100cqh) / 82); }
}
[data-redesign] .sfl-lpk-emb { position: absolute; top: 0; left: 0; width: 100%; height: calc(var(--lpk-u) * 74); display: flex; align-items: center; justify-content: center; }
[data-redesign] .sfl-lpk-tag {
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); z-index: 1;
  display: inline-flex; align-items: center; gap: calc(var(--lpk-u) * 4); white-space: nowrap;
  background: #000; color: #fff; border: 2px solid var(--surface); border-radius: calc(var(--lpk-u) * 6);
  font-size: calc(var(--lpk-u) * 9); font-weight: 800; letter-spacing: .08em; line-height: 1;
  padding: calc(var(--lpk-u) * 2.5) calc(var(--lpk-u) * 6);
}
[data-redesign] .sfl-lpk-blink { width: calc(var(--lpk-u) * 5); height: calc(var(--lpk-u) * 5); border-radius: 50%; background: #e11d48; }
[data-redesign] .sfl-lpk-shape { display: flex; align-items: center; justify-content: center; box-sizing: border-box; }
[data-redesign] .sfl-lpk-letter { color: #fff; font-weight: 800; line-height: 1; }
[data-redesign] .sfl-lpk-shape--tt { width: calc(var(--lpk-u) * 64); height: calc(var(--lpk-u) * 64); border-radius: 50%; background-clip: padding-box !important; border: calc(var(--lpk-u) * 6) double var(--text); }
[data-redesign] .sfl-lpk-shape--tt .sfl-lpk-letter { font-size: calc(var(--lpk-u) * 28); }
[data-redesign] .sfl-lpk-shape--fb, [data-redesign] .sfl-lpk-shape--ig {
  width: calc(var(--lpk-u) * 58); height: calc(var(--lpk-u) * 58);
  box-shadow: 0 0 0 calc(var(--lpk-u) * 3) var(--surface), 0 0 0 calc(var(--lpk-u) * 7) var(--lpk-brand);
}
[data-redesign] .sfl-lpk-shape--fb { border-radius: calc(var(--lpk-u) * 22); }
[data-redesign] .sfl-lpk-shape--fb .sfl-lpk-letter { font-size: calc(var(--lpk-u) * 30); font-family: var(--font-display); }
[data-redesign] .sfl-lpk-shape--ig { border-radius: 50% 50% 50% 14%; }
[data-redesign] .sfl-lpk-shape--ig .sfl-lpk-letter { font-size: calc(var(--lpk-u) * 19); }
/* diamond: (38 + 2×7) × √2 ≈ 73.5 ≤ 74 incl. the ring */
[data-redesign] .sfl-lpk-shape--sh {
  width: calc(var(--lpk-u) * 38); height: calc(var(--lpk-u) * 38); transform: rotate(45deg); border-radius: calc(var(--lpk-u) * 4);
  box-shadow: 0 0 0 calc(var(--lpk-u) * 3) var(--surface), 0 0 0 calc(var(--lpk-u) * 7) var(--lpk-brand);
}
[data-redesign] .sfl-lpk-shape--sh .sfl-lpk-letter { font-size: calc(var(--lpk-u) * 19); transform: rotate(-45deg); }
[data-redesign] .sfl-lpk-fly { animation: sflLpkFly var(--lpk-fly) cubic-bezier(.2,.8,.2,1); }

[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-emb--tt { animation: sflLpkBeat var(--lpk-tt) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-emb--fb { animation: sflLpkBob var(--lpk-fb) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-emb--ig { animation: sflLpkSway var(--lpk-ig) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-emb--sh { animation: sflLpkFlip var(--lpk-sh) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-name--tt { animation: sflLpkWordBeat var(--lpk-tt) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-name--fb { animation: sflLpkWordSlide var(--lpk-fb) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-name--ig { animation: sflLpkWordLean var(--lpk-ig) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-name--sh { animation: sflLpkWordHop var(--lpk-sh) ease-in-out var(--lpk-iter); }
[data-redesign] .sfl-lpk:not(.sfl-lpk--m-off):not(.sfl-lpk--chosen) .sfl-lpk-tile:not(:disabled) .sfl-lpk-blink { animation: sflLpkBlink var(--lpk-blink) ease-in-out var(--lpk-iter); }

[data-redesign][data-motion="off"] .sfl-lpk, [data-redesign][data-motion="off"] .sfl-lpk *,
[data-redesign][data-motion="off"] .sfl-lpk-fly { animation: none !important; transition: none !important; }
@media (prefers-reduced-motion: reduce) {
  [data-redesign] .sfl-lpk, [data-redesign] .sfl-lpk *, [data-redesign] .sfl-lpk-fly { animation: none !important; transition: none !important; }
}

/* Help bot bubble — ONE gentle pulse when Settings opens (not a loop). */
@keyframes sflHbPulse { 0% { transform: scale(1); } 35% { transform: scale(1.12); } 70% { transform: scale(.97); } 100% { transform: scale(1); } }
[data-redesign] .sfl-hb-pulse { animation: sflHbPulse .9s ease-out .4s 1 both; }
[data-redesign][data-motion="off"] .sfl-hb-pulse { animation: none !important; }
@media (prefers-reduced-motion: reduce) { [data-redesign] .sfl-hb-pulse { animation: none !important; } }

/* Help bot hint — pop/slide in, fade out; the bot icon waves once. Off with motion off. */
@keyframes sflHbHintIn { 0% { opacity: 0; transform: scale(.8); } 70% { opacity: 1; transform: scale(1.04); } 100% { opacity: 1; transform: scale(1); } }
@keyframes sflHbHintOut { to { opacity: 0; transform: scale(.94); } }
@keyframes sflHbWave { 0%, 100% { transform: rotate(0); } 20% { transform: rotate(-16deg); } 40% { transform: rotate(13deg); } 60% { transform: rotate(-9deg); } 80% { transform: rotate(5deg); } }
[data-redesign] .sfl-hb-hint { animation: sflHbHintIn .32s ease-out both; }
[data-redesign] .sfl-hb-hint-out { animation: sflHbHintOut .3s ease-in forwards; }
[data-redesign] .sfl-hb-wave { animation: sflHbWave .9s ease-in-out 1; transform-origin: 50% 80%; }
[data-redesign][data-motion="off"] .sfl-hb-hint,
[data-redesign][data-motion="off"] .sfl-hb-hint-out,
[data-redesign][data-motion="off"] .sfl-hb-wave { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  [data-redesign] .sfl-hb-hint, [data-redesign] .sfl-hb-hint-out, [data-redesign] .sfl-hb-wave { animation: none !important; }
}

/* Orders filter row (mobile-first, Oct 14 2026): chips + the 🗓 button on ONE line at every
   width. The chips scroll sideways when they don't fit (no scrollbar shown) — never wrap.
   The chip box gets 9px of vertical room (margin cancels it) so the 44px tap areas below are
   not clipped by the sideways scroll. */
[data-redesign] .sfl-ord-filters { flex-wrap: nowrap; min-width: 0; }
[data-redesign] .sfl-ord-chips {
  display: flex; align-items: center; gap: 6px; flex: 1 1 auto; min-width: 0;
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; padding: 9px 14px 9px 0; margin: -9px 0;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  /* soft fade at the right edge = "there is more, swipe"; when everything fits the fade only
     covers the empty end padding */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 14px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 14px), transparent);
}
[data-redesign] .sfl-ord-chips::-webkit-scrollbar { display: none; }
/* 44px tap area around a small pill without changing its size or the header height. */
[data-redesign] .sfl-tap44 { position: relative; }
[data-redesign] .sfl-tap44::after { content: ""; position: absolute; left: -3px; right: -3px; top: 50%; height: 44px; transform: translateY(-50%); }
