/* AceChange Telegram Mini App — Dark Theme (forced, always)
 *
 * Colors are hardcoded (NOT linked to Telegram theme vars) so the
 * Mini App looks identical whether the user's Telegram is in light
 * or dark mode. Matching setHeaderColor/setBackgroundColor calls in
 * app.js keep the native Telegram shell in sync.
 */
* { margin:0; padding:0; box-sizing:border-box; }
html { overflow-x:hidden; background:#1a1a2e; min-height:100vh; color-scheme:dark; }
:root {
  --bg: #1a1a2e;         /* AceChange dark — always, regardless of user's Telegram theme */
  --surface: #16213e;    /* AceChange surface — inputs, cards, modals */
  --text: #ffffff;       /* Always white for max contrast on dark */
  --hint: #8b949e;       /* Mid-gray — readable on #1a1a2e */
  --link: #d4af37;       /* AceChange gold */
  --btn: #d4af37;        /* AceChange gold — HTML buttons (MainButton set via JS) */
  --btn-text: #000000;   /* Black on gold — AA contrast */
  --gold: #d4af37;
  --danger: #e74c3c;
  --success: #27ae60;
  --radius: 12px;
}
/* v7.5.13 — skip-to-content link (WCAG 2.4.1 Bypass Blocks).
   Off-screen by default so mouse + touch users never see it; slides
   into the top-left on :focus so keyboard users tabbing into the
   page immediately get a "skip menu, jump to main" affordance.
   The link target (<main id="main-content">) wraps every step + tab
   content section. */
.skip-link {
  position: absolute;
  top: -40px;
  left: 12px;
  z-index: 10001;
  background: var(--gold);
  color: var(--btn-text);
  padding: 10px 16px;
  border-radius: 0 0 8px 8px;
  font-weight: 700;
  font-size: .95rem;
  text-decoration: none;
  transition: top .15s ease;
}
.skip-link:focus {
  top: 0;
  outline: 3px solid #fff;
  outline-offset: -3px;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  /* v7.5.10 — vertical rhythm baseline.
     font-size 16px is REQUIRED on inputs to prevent iOS Safari from
     auto-zooming when an input is focused (WebKit known behavior).
     Setting it on body keeps every descendant readable + iOS-zoom-safe.
     line-height 1.5 follows WCAG 2.2 §1.4.12 (Text Spacing) — paragraph
     line-height must be at least 1.5× font-size for AA conformance. */
  font-size: 16px;
  line-height: 1.5;
  /* v7.5.10 — top padding bumped from 12px → max(24px, env()) so the
     hamburger / logo no longer hugs the status bar on devices without
     a notch. Bottom padding is now safe-area-aware so content above
     the iOS home indicator never sits flush with the bottom edge. */
  padding: max(24px, env(safe-area-inset-top, 24px)) 16px max(24px, env(safe-area-inset-bottom, 24px));
  -webkit-font-smoothing: antialiased;
  /* v7.5.10 — kill the default iOS Safari blue tap-highlight rectangle
     on every interactive element. We provide our own tap feedback per
     button class (transform: scale + opacity) for a consistent feel.
     Apple HIG "Touch Feedback" — feedback should be immediate (<100ms),
     proportional, and visually consistent across the app. */
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}
/* Center the app shell on wide viewports (browser preview, Telegram
   Desktop). On mobile this is a no-op because the viewport is narrow
   enough that max-width never applies. Keeps the UI readable rather
   than stretching inputs and CTAs across 1400px of desktop space. */
#app {
  max-width: 520px;
  margin: 0 auto;
  width: 100%;
}
/* Position short swap steps slightly above center vertically so users
   see inputs + content immediately without scrolling, but with enough
   breathing room for the MainButton below. */
.tg-app #app {
  min-height: calc(100vh - 24px);
  display: flex;
  flex-direction: column;
}
/* Inner action steps (address, confirm) use flex to push the primary
   CTA into the thumb-reach zone. Based on Steven Hoober's study
   (n=1333, 2013): the bottom third of the viewport is the only area
   with 95%+ one-handed comfort. We target the top of that third
   (~60-66% from top) so the button never hugs the screen edge. */
.tg-app #step-address.active,
.tg-app #step-confirm.active {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 120px);
  margin-top: 0;
  margin-bottom: 0;
}
.tg-app #step-deposit.active {
  margin-top: 0;
  margin-bottom: 0;
  /* Reserve space so the final timer row doesn't hide behind the
     native MainButton "🔄 New Swap" + iOS home indicator. */
  padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
}
/* clamp() keeps the button 90-220px above the bottom safe-area on
   ANY viewport height (iPhone SE → iPad). Above the MainButton,
   below the form content, squarely in the natural thumb zone.
   No safe-area padding on the button itself — it's in the middle
   of the viewport, not at the bottom edge; the MainButton overlay
   at the bottom has its own safe-area handling from Telegram. */
.tg-app #step-address.active > .primary-btn,
.tg-app #step-confirm.active > .primary-btn {
  display: block !important;
  margin-top: auto;
  margin-bottom: clamp(90px, 25vh, 220px);
}
/* v7.5.10 — header bottom padding bumped 16px → 24px so logo / subtitle
   don't visually crash into the first content card. Top padding is
   absorbed by body's safe-area envelope. */
#header { text-align:center; padding:8px 0 24px; position:relative; }
.logo { font-size:1.4rem; font-weight:700; color:var(--gold); }
.subtitle { font-size:.85rem; color:var(--hint); margin-top:2px; }

/* v7.5.15 — .home-banner / .home-banner-img CSS removed. The
   misnamed v7.5.0 banner feature was replaced by FFE_PWA_Icon_Manager
   which controls the actual home-screen install icon via the
   manifest icons array + apple-touch-icon link tags. */

/* ─── Hamburger menu ─── */
.ham-btn {
  position:absolute; top:6px; right:0;
  width:44px; height:44px;
  background:transparent; border:0; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  color:#fff; padding:0;
}
.ham-icon { position:relative; width:22px; height:2px; background:#fff; display:block; }
.ham-icon::before, .ham-icon::after {
  content:""; position:absolute; left:0; width:22px; height:2px; background:#fff;
}
.ham-icon::before { top:-7px; }
.ham-icon::after  { top: 7px; }
.ham-btn:focus-visible { outline:2px solid var(--gold); outline-offset:2px; border-radius:6px; }
.ham-btn:active { opacity:.7; }

.ham-overlay {
  position:fixed; inset:0; background:rgba(0,0,0,.55);
  z-index:9998; opacity:0; transition:opacity .22s ease;
}
.ham-overlay.open { opacity:1; }
.ham-overlay[hidden] { display:none; }

.ham-panel {
  position:fixed; top:0; right:0; bottom:0; width:min(82vw, 320px);
  background:#1f2238; border-left:1px solid #2a2e4d;
  box-shadow:-6px 0 24px rgba(0,0,0,.4);
  z-index:9999;
  transform:translateX(100%); transition:transform .25s ease;
  display:flex; flex-direction:column;
  /* Padding-top respects iOS Dynamic Island / notch via the W3C CSS
     Environment Variables L1 spec (env(safe-area-inset-top)). Without
     this the close × button at the top of the panel renders BEHIND
     the status-bar / battery indicator on iPhone X+ (visible in the
     installed PWA standalone mode). Apple HIG "Layout" — never place
     interactive controls inside the safe-area inset zone:
       https://developer.apple.com/design/human-interface-guidelines/layout
       https://www.w3.org/TR/css-env-1/
     The 14px constant matches the previous design baseline; we ADD
     the inset rather than max() so the panel always has at least
     14px of breathing room below the system UI. */
  padding:calc(14px + env(safe-area-inset-top, 0px)) 12px env(safe-area-inset-bottom, 14px);
  overflow-y:auto;
}
.ham-panel.open { transform:translateX(0); }
.ham-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:6px 10px 14px; border-bottom:1px solid #2a2e4d; margin-bottom:10px;
}
.ham-title { font-size:1.1rem; font-weight:700; color:var(--gold); letter-spacing:.5px; }
.ham-close {
  background:transparent; border:0; color:#fff; font-size:1.6rem; line-height:1;
  width:36px; height:36px; cursor:pointer; border-radius:8px;
}
.ham-close:hover  { background:rgba(255,255,255,.08); }
.ham-close:focus-visible { outline:2px solid var(--gold); outline-offset:2px; }

.ham-item {
  display:flex; align-items:center; gap:14px;
  width:100%; text-align:left;
  background:transparent; border:0;
  padding:14px 14px;
  margin:2px 0;
  border-radius:10px;
  color:#fff; font-size:1rem;
  min-height:48px; cursor:pointer;
  transition:background .15s ease;
}
.ham-item .tab-icon { font-size:1.25rem; flex-shrink:0; }
.ham-item .tab-label { flex:1; }
.ham-item:hover  { background:rgba(255,255,255,.05); }
.ham-item:active { background:rgba(255,255,255,.1); }
.ham-item.active {
  background:rgba(212,175,55,.12);
  color:var(--gold);
  font-weight:600;
}
.ham-item:focus-visible { outline:2px solid var(--gold); outline-offset:-2px; }

@media (prefers-reduced-motion: reduce) {
  .ham-panel, .ham-overlay { transition:none; }
}
.step { display:none; animation:fadeIn .25s ease; }
.step.active { display:block; }
@keyframes fadeIn { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }

/* WCAG 2.2 SC 2.3.3 — respect users who request less motion. The
   app stays functional with near-zero animation time. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* WCAG 2.4.7 Focus Visible — keyboard users need a clear outline.
   :focus-visible only shows the ring on keyboard focus, not mouse
   clicks, so the touch UI stays clean. Gold ring matches brand. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 6px;
}

/* v7.5.10 — form group rhythm. Bumped margin 16px → 20px and label
   font-size .85rem → .9rem (~14.4px) for legibility on small screens.
   line-height 1.4 on label keeps a wrapping label from overlapping
   the input below. */
.form-group { margin-bottom:20px; }
.form-group label {
  display:block;
  font-size:.9rem;
  line-height:1.4;
  color:var(--hint);
  margin-bottom:8px;
  font-weight:600;
}
.currency-row { display:flex; gap:8px; }
.currency-row input {
  flex:1; background:var(--surface); border:1px solid rgba(255,255,255,.1);
  border-radius:var(--radius); padding:14px;
  /* v7.5.10 — explicit 17px is above the 16px iOS-no-zoom threshold
     while still slightly larger than body text to draw the eye to the
     primary input on the swap form. */
  font-size:17px;
  color:var(--text); outline:none;
  /* v7.5.10 — explicit min-height matches every other tap target. */
  min-height:48px;
  transition: border-color .08s ease, box-shadow .08s ease;
}
.currency-row input:focus {
  border-color:var(--gold);
  /* v7.5.10 — visible focus ring (WCAG 2.2 §2.4.7 + §2.4.13). The
     gold-tinted box-shadow is high-contrast against both the surface
     bg and the page bg, satisfies the new "Focus Appearance" success
     criterion, and matches the PIN-lock input style for consistency. */
  box-shadow: 0 0 0 3px rgba(212,175,55,.18);
}
.currency-btn {
  background:var(--surface); border:1px solid rgba(255,255,255,.15);
  border-radius:var(--radius); padding:14px 16px; font-size:1rem;
  color:var(--text); font-weight:600; cursor:pointer; min-width:90px;
  white-space:nowrap; display:inline-flex; align-items:center; gap:6px;
  /* v7.5.10 — explicit min-height meets the union of Apple HIG (44pt),
     Material Design 3 (48dp), and WCAG 2.5.5 (44 CSS px AAA). Unified
     across every interactive element in the app. */
  min-height:48px;
  /* user-select:none stops accidental text selection on long-press. */
  user-select:none; -webkit-user-select:none;
  /* 80ms is the perceptual sweet spot — long enough to be visible,
     short enough to feel instantaneous (Doherty Threshold). */
  transition: background .08s ease, transform .08s ease;
}
.currency-btn:active {
  background:rgba(212,175,55,.2);
  /* v7.5.10 — scale gives a "physical press" feel that matches the
     primary CTA, so all buttons share one tactile language. */
  transform:scale(.97);
}
/* Chain/network badge inline next to ticker code on the swap buttons.
   Sourced from FixedFloat /ccies `network` field — never inferred. */
.btn-net-badge {
  display:inline-block; font-size:.65rem; font-weight:700; line-height:1;
  padding:3px 6px; border-radius:6px; background:rgba(212,175,55,.18);
  color:var(--gold); letter-spacing:.3px; vertical-align:middle;
  border:1px solid rgba(212,175,55,.35); margin:0 2px;
}

.swap-arrow {
  /* Reset native <button> look so only the gold arrow remains —
     we promoted the div to a real button for keyboard + a11y. */
  background: none; border: none; width: 100%;
  text-align:center; font-size:1.6rem; padding:10px 0;
  color:var(--gold); cursor:pointer; user-select:none; -webkit-user-select:none;
  /* v7.5.10 — bumped 44 → 48 to match the rest of the app's tap targets. */
  min-height:48px; display:flex; align-items:center; justify-content:center;
  transition: transform .2s;
}
.swap-arrow:active { transform:rotate(180deg); }
.rate-info {
  text-align:center; font-size:.85rem; line-height:1.5; color:var(--hint);
  padding:14px 14px; min-height:auto;
  background:var(--surface); border-radius:var(--radius);
  border:1px solid rgba(255,255,255,.06);
  /* v7.5.10 — top margin bumped 4px → 12px so the "1 BTC = …" panel
     no longer collides with the swap arrow above it on dense layouts.
     Bottom margin bumped 12px → 20px for clearer visual handoff to
     the next form group. */
  margin:12px 0 20px;
  /* Native backup for any scrollIntoView/anchor jumps: keep a
     comfortable gap above the card so it never lands flush against
     the top of the viewport. The JS scroll helper computes an
     explicit target too — this is defence-in-depth. */
  scroll-margin-top: 80px;
}
/* v7.5.10 — gap 8px → 12px so the two type buttons read as separate
   options, not a single segmented control. margin-bottom 16px → 20px
   for clearer separation from the next form group. */
.rate-type-toggle { display:flex; gap:12px; margin-bottom:20px; }
.type-btn {
  flex:1; padding:12px 10px; border:1px solid rgba(255,255,255,.1);
  border-radius:var(--radius); background:var(--surface);
  color:var(--hint); font-size:.9rem; cursor:pointer; text-align:center;
  /* v7.5.10 — bumped 44px → 48px to match the rest of the app's tap
     targets, plus tap feedback. */
  min-height:48px;
  user-select:none; -webkit-user-select:none;
  transition: border-color .08s ease, background .08s ease, color .08s ease, transform .08s ease;
}
.type-btn:active { transform:scale(.97); }
.type-btn.active {
  border-color:var(--gold); color:var(--gold);
  background:rgba(212,175,55,.1);
}

.primary-btn {
  width:100%; padding:14px 16px; background:var(--btn); color:var(--btn-text);
  border:none; border-radius:var(--radius); font-size:1.05rem;
  font-weight:700; cursor:pointer;
  /* v7.5.10 — top margin 8px → 16px so the CTA is visually anchored
     below the form rather than glued to the last input. */
  margin-top:16px;
  min-height:48px;
  user-select:none; -webkit-user-select:none;
  transition: transform .08s ease, opacity .08s ease;
}
.primary-btn:disabled { opacity:.4; filter:grayscale(1); cursor:not-allowed; }
/* v7.5.10 — slight opacity nudge alongside the existing scale gives
   stronger affordance on press without changing the visual identity. */
.primary-btn:active:not(:disabled) { transform:scale(.97); opacity:.92; }
/* Secondary buttons must also meet the 48pt union touch target —
   used for Copy Address, Back, Cancel, Refund, etc. */
.secondary-btn {
  width:100%; padding:12px 16px; background:transparent;
  border:1px solid rgba(255,255,255,.15); border-radius:var(--radius);
  color:var(--hint); font-size:.9rem; cursor:pointer;
  /* v7.5.10 — top margin 8px → 12px (slightly tighter than primary
     so the visual hierarchy primary > secondary is preserved). */
  margin-top:12px;
  /* v7.5.10 — bumped 44 → 48 + tap feedback to match the rest. */
  min-height:48px;
  user-select:none; -webkit-user-select:none;
  transition: transform .08s ease, opacity .08s ease, border-color .08s ease;
}
.secondary-btn:active { transform:scale(.97); opacity:.92; }
/* v7.5.10 — adjacent button stacking. When the page renders two
   buttons in a row (e.g. Copy + Open Wallet), keep a comfortable
   12px gap rather than relying on the per-button margin-top. */
.secondary-btn + .secondary-btn,
.primary-btn + .secondary-btn { margin-top:12px; }

input[type="text"], input[type="email"] {
  width:100%; background:var(--surface); border:1px solid rgba(255,255,255,.1);
  border-radius:var(--radius); padding:14px;
  /* v7.5.10 — 16px is the iOS Safari "no-auto-zoom-on-focus"
     threshold. Anything below triggers a viewport zoom that breaks
     the layout and frustrates users. Apple has not documented this
     explicitly but it is well-established WebKit behavior since iOS 4. */
  font-size:16px;
  color:var(--text); outline:none;
  /* v7.5.10 — explicit min-height, matches every other tap target. */
  min-height:48px;
  transition: border-color .08s ease, box-shadow .08s ease;
}
input:focus {
  border-color:var(--gold);
  /* v7.5.10 — focus ring (WCAG 2.2 §2.4.7 + §2.4.13). See same rule
     on .currency-row input:focus for full rationale. */
  box-shadow: 0 0 0 3px rgba(212,175,55,.18);
}

/* v7.5.10 — card rhythm. padding bumped 14/16 → 18/18 (8pt grid
   alignment) and margin 8px → 16px so consecutive cards have a
   clear visual gap rather than appearing glued. */
.summary-box {
  background:var(--surface); border-radius:var(--radius);
  padding:18px; margin:16px 0;
}

/* PROTECTED: "You will receive" block — see CLAUDE.md "Order Receive
   Block". Mirrors the web .ffe-receive-block visual rhythm so the
   same data lands on the user's eye in the same place across surfaces.
   Must NEVER be removed without project-owner sign-off.

   Visual restyle (matches web PR #983): red palette → muted gold
   #d4af37 (already the Mini App's --gold variable). Receive block now
   reads as confirmation of secondary info, not a competing primary
   action. DOM/IDs/data-protected attribute completely unchanged.
   Refs:
   - https://www.nngroup.com/articles/visual-hierarchy-ux-definitions/
   - https://m3.material.io/styles/color/the-color-system/key-colors-tones */
.receive-block {
  margin: 18px 0 12px;
  padding: 12px 14px;
  border: 1px solid rgba(212, 175, 55, 0.30);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(212, 175, 55, 0.05) 0%, rgba(212, 175, 55, 0.015) 100%);
  text-align: center;
}
.receive-header {
  color: var(--gold);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .8px;
  margin-bottom: 5px;
  opacity: .85;
}
.receive-amount {
  color: #f0d97a;
  font-size: .95rem;
  font-weight: 700;
  margin-bottom: 6px;
  word-break: break-word;
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap;
  justify-content: center;
}
.receive-network-badge {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 5px;
  background: rgba(212, 175, 55, 0.12);
  border: 1px solid rgba(212, 175, 55, 0.35);
  color: var(--gold);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .3px;
}
.receive-label-mini {
  color: rgba(255, 255, 255, 0.55);
  font-size: .68rem;
  font-weight: 600;
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: .5px;
}
.receive-address-box {
  background: rgba(212, 175, 55, 0.04);
  border: 1px dashed rgba(212, 175, 55, 0.25);
  border-radius: 7px;
  padding: 8px 10px;
}
.receive-address {
  color: rgba(255, 255, 255, 0.85);
  font-size: .75rem;
  line-height: 1.5;
  word-break: break-all;
  user-select: all;
  cursor: text;
}

/* Triple chevron pointing DOWN from "To address:" label to the
   deposit address. Mirrors web .ffe-arrows-down (PR #982).
   Decorative — aria-hidden + pointer-events:none. transform+opacity
   animation only (GPU-accelerated, no reflow). Respects
   prefers-reduced-motion per WCAG 2.1 SC 2.3.3. */
.arrows-down {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 4px auto 6px;
  color: #ff4d4d;
  line-height: 0;
  pointer-events: none;
}
.arrows-down svg {
  width: 22px;
  height: 22px;
  margin-top: -8px;
  opacity: .45;
  animation: arrows-down-pulse 1.4s ease-in-out infinite;
  will-change: opacity, transform;
}
.arrows-down svg:first-child  { margin-top: 0; }
.arrows-down svg:nth-child(2) { animation-delay: 0.2s; }
.arrows-down svg:nth-child(3) { animation-delay: 0.4s; }
@keyframes arrows-down-pulse {
  0%, 100% { opacity: 0.4; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(2px); }
}
@media (prefers-reduced-motion: reduce) {
  .arrows-down svg { animation: none; opacity: .7; }
}
.summary-row {
  display:flex; justify-content:space-between; padding:8px 0;
  border-bottom:1px solid rgba(255,255,255,.05); font-size:.95rem;
}
.summary-row:last-child { border-bottom:none; }
.summary-row span { color:var(--hint); }
.summary-row strong { color:var(--text); }
.summary-row code {
  color: var(--gold);
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: .9rem;
  letter-spacing: .5px;
}
.mono { font-family:'SF Mono',Menlo,Consolas,monospace; font-size:.8rem; word-break:break-all; }

/* v7.5.10 — same rhythm as .summary-box for visual consistency. */
.deposit-box {
  background:var(--surface); border-radius:var(--radius);
  padding:18px; margin:16px 0; text-align:center;
}
.deposit-label { font-size:.85rem; color:var(--hint); margin-bottom:4px; }
.deposit-amount { font-size:1.25rem; font-weight:700; color:var(--gold); margin-bottom:10px; }
.deposit-address { font-size:1rem; color:var(--text); padding:12px 12px; background:rgba(0,0,0,.3); border-radius:8px; margin-bottom:8px; word-break:break-all; line-height:1.4; }
.deposit-qr {
  /* Bulletproof centering — text-align alone fails inside flex parents
     that override default block-level alignment. display:flex centers
     the QR image regardless of ancestor layout. */
  text-align:center; padding:10px; margin:8px auto;
  background:var(--surface); border-radius:var(--radius);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
}
/* QR size clamped to fit all phones without scrolling — still
   well above the 120px minimum for reliable camera scanning. */
.qr-image {
  width:clamp(140px, 38vw, 168px);
  height:clamp(140px, 38vw, 168px);
  border-radius:10px;
  background:#fff; padding:6px;
  display:block; margin:0 auto;
}
.track-badge {
  text-align:center; padding:12px; border-radius:var(--radius);
  font-weight:700; font-size:1rem; margin-bottom:12px;
  letter-spacing:.5px;
}
.track-badge.status-new       { background:rgba(52,152,219,.15); color:#3498db; }
.track-badge.status-pending   { background:rgba(241,196,15,.15); color:#f1c40f; }
.track-badge.status-exchange  { background:rgba(155,89,182,.15); color:#9b59b6; }
.track-badge.status-withdraw  { background:rgba(52,152,219,.15); color:#3498db; }
.track-badge.status-done      { background:rgba(39,174,96,.15);  color:#27ae60; }
.track-badge.status-expired   { background:rgba(149,165,166,.15);color:#95a5a6; }
.track-badge.status-emergency { background:rgba(231,76,60,.15);  color:#e74c3c; }
.track-badge.status-refund    { background:rgba(241,196,15,.15); color:#f1c40f; }
.deposit-tag { text-align:center; margin:6px 0; }
.timer { text-align:center; color:var(--danger); font-weight:600; margin:6px 0; font-size:.95rem; }

/* v7.5.10 — heading rhythm. line-height 1.35 prevents tall ascenders
   from clipping when a heading wraps to two lines on narrow screens.
   margin-bottom bumped 12px → 16px for clearer visual separation
   between section title and first content row. */
h2 { font-size:1.15rem; line-height:1.35; text-align:center; margin-bottom:16px; }
/* v7.5.10 — paragraph rhythm. Without this, .help-step p (margin
   4px 0 0) carries through to every <p>, producing visually crammed
   text blocks. Universal default of 0 0 12px ensures readable spacing
   everywhere, while local overrides (e.g. .help-step) still win
   thanks to specificity. */
p { margin: 0 0 12px; }

/* Currency modal — full-screen overlay. Padding-top + sticky header
   top BOTH respect env(safe-area-inset-top) so the search input and
   close × never render behind the iOS status bar / Dynamic Island on
   installed PWA (standalone mode). Apple HIG "Layout" + W3C CSS Env
   Variables L1 — interactive controls must clear the safe-area inset.
     https://developer.apple.com/design/human-interface-guidelines/layout
     https://www.w3.org/TR/css-env-1/ */
.modal {
  position:fixed; inset:0; background:var(--bg); z-index:100;
  overflow-y:auto; overflow-x:hidden;
  padding:calc(12px + env(safe-area-inset-top, 0px)) 16px env(safe-area-inset-bottom, 20px);
  width:100%; max-width:100vw;
}
.modal-header {
  display:flex; gap:8px; margin-bottom:14px;
  /* position:sticky with top:0 sticks to the inside of the .modal's
     padding edge (per CSS Positioned Layout Module Level 3). Because
     .modal already adds env(safe-area-inset-top) to its padding-top,
     "top:0" on the header naturally clears the status bar — no extra
     offset needed. The 8px bottom padding gives the search input
     visual breathing room before the option grid starts. */
  position:sticky; top:0;
  background:var(--bg);
  padding:8px 0; z-index:1;
}
.modal-header input {
  flex:1; background:var(--surface); border:1px solid rgba(255,255,255,.15);
  border-radius:var(--radius); padding:14px 12px; font-size:1rem;
  color:var(--text); outline:none;
}
.modal-header input:focus { border-color:var(--gold); }
.modal-header input::placeholder { color:var(--hint); }
.modal-close {
  /* v7.5.64 — bumped to meet Apple HIG 44pt + Material 48dp touch
     target minimum (was 10×14 padding + 1.1rem font ≈ 38px tall).
     Phones consistently mis-tap below 44pt; the picker close X is
     in a corner where the user is already aiming carefully. */
  background:var(--surface); border:1px solid rgba(255,255,255,.1); color:var(--text); font-size:1.1rem;
  cursor:pointer; padding:12px 16px; border-radius:var(--radius); font-weight:700;
  min-width:44px; min-height:44px;
  display:inline-flex; align-items:center; justify-content:center;
}
.currency-list {
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:8px; padding-bottom:20px; max-width:100%; overflow:hidden;
}
/* v7.5.64 — narrow phones (iPhone SE 1st-gen, older Android <380px)
   render 3-col with overflow because each cell needs ≥110px to show
   coin icon + symbol + name. 2-col fallback keeps the picker usable. */
@media (max-width: 380px) {
  .currency-list { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
.coin-item {
  background:var(--surface); border:1px solid rgba(255,255,255,.08);
  border-radius:var(--radius); padding:12px 4px; text-align:center;
  cursor:pointer; font-weight:700;
  transition: border-color .15s, background .15s;
  display:flex; flex-direction:column; align-items:center; gap:3px;
  overflow:hidden; min-width:0; word-break:break-all;
}
.coin-item:active { background:rgba(212,175,55,.2); border-color:var(--gold); }
.coin-item .coin-icon { width:32px; height:32px; flex-shrink:0; }
.coin-item > div:nth-child(2) { font-size:.85rem; }
.coin-item .coin-name {
  /* v7.5.11 — chain/network readability fix.
     Was 0.6rem (~9.6px) hint-grey 400-weight — under iOS minimum
     readability threshold, users couldn't tell USDT had its chain
     "ETH" right under it (perceived as "USDT without chain").
     Bumped to 0.78rem (~12.5px) gold-tinted 600-weight pill so the
     chain identification is unmissable. Critical because sending
     crypto to wrong network = unrecoverable loss (extends the
     CLAUDE.md "Order Receive Block" rationale to the picker — the
     user's first decision point on every swap). */
  font-size: .78rem;
  color: var(--gold);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: .3px;
  margin-top: 4px;
  background: rgba(212,175,55,.08);
  padding: 2px 6px;
  border-radius: 4px;
  max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* Coin icons */
.coin-icon {
  vertical-align: middle;
  border-radius: 50%;
  object-fit: contain;
  flex-shrink: 0;
}
.coin-item .coin-icon {
  display: block;
  margin: 0 auto 4px;
}
.summary-row strong .coin-icon,
.deposit-amount .coin-icon {
  vertical-align: -3px;
  margin-right: 2px;
}

/* Tab buttons — used inside the hamburger panel only (the legacy
   horizontal .tab-nav and .tab-nav-secondary wrappers were removed
   when the hamburger menu replaced them). No `flex: 1` here on
   purpose — that would make items in the column-flex .ham-panel
   stretch vertically to fill the entire panel height; we want a
   compact list with min-height: 48px from .ham-item. */
.tab-btn {
  padding:14px 12px; border:none; border-radius:10px;
  background:transparent; color:rgba(255,255,255,.5); font-size:.95rem;
  font-weight:600; cursor:pointer; text-align:center;
  transition: background .2s, color .2s;
  min-height:48px;
}
.tab-btn:active { transform:scale(.97); }
.tab-content { animation:fadeIn .25s ease; }

/* Help steps */
.help-steps { display:flex; flex-direction:column; gap:12px; }
.help-step {
  display:flex; gap:12px; align-items:flex-start;
  background:var(--surface); border-radius:var(--radius); padding:14px;
}
.help-num {
  min-width:28px; height:28px; border-radius:50%;
  background:var(--gold); color:#000; font-weight:700;
  display:flex; align-items:center; justify-content:center;
  font-size:.85rem; flex-shrink:0;
}
.help-step p { font-size:.9rem; color:var(--text); margin:4px 0 0; }
.help-step strong { color:var(--gold); font-size:.95rem; }

.loading {
  position:fixed; inset:0; background:rgba(0,0,0,.7);
  display:flex; flex-direction:column; align-items:center;
  justify-content:center; z-index:200; gap:12px; color:var(--hint);
}
.spinner {
  width:36px; height:36px; border:3px solid rgba(255,255,255,.15);
  border-top-color:var(--gold); border-radius:50%;
  animation:spin .8s linear infinite;
}
@keyframes spin { to{transform:rotate(360deg)} }

/* Saved wallets picker (Mini App mirror of bot's /wallets flow) */
.saved-wallets-btn {
  margin-top: 10px; width: 100%;
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px;
  background: rgba(212,175,55,.08);
  border: 1px solid rgba(212,175,55,.35);
  border-radius: var(--radius);
  color: var(--gold); font-weight: 600; font-size: .95rem;
  cursor: pointer; min-height: 48px;
  transition: background .15s ease, border-color .15s ease;
}
.saved-wallets-btn:active { background: rgba(212,175,55,.18); }
.saved-wallets-btn .saved-wallets-btn-icon { font-size: 1.1rem; }
.saved-wallets-btn .saved-wallets-btn-text { flex: 1; text-align: left; }
.saved-wallets-btn .saved-wallets-btn-caret { transition: transform .2s ease; font-size: .9rem; }
.saved-wallets-btn.open .saved-wallets-btn-caret { transform: rotate(180deg); }

.saved-wallets-picker {
  margin-top: 8px;
  background: var(--surface);
  border: 1px solid rgba(212,175,55,.2);
  border-radius: var(--radius);
  padding: 8px;
  max-height: 340px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
  animation: fadeIn .18s ease;
}
.saved-wallets-header {
  font-size: .8rem; color: var(--hint); font-weight: 600;
  padding: 4px 8px 6px; text-transform: uppercase; letter-spacing: .5px;
}
.saved-wallet-item {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 12px; min-height: 56px;
  background: rgba(255,255,255,.03);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 10px;
  color: var(--text); font-family: inherit; font-size: 1rem;
  text-align: left; cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .1s ease;
}
.saved-wallet-item:active { transform: scale(.985); background: rgba(212,175,55,.12); }
.saved-wallet-item.matching {
  border-color: rgba(212,175,55,.55);
  background: rgba(212,175,55,.08);
}
.saved-wallet-icon { flex-shrink: 0; display: inline-flex; align-items: center; }
.saved-wallet-body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.saved-wallet-label {
  font-weight: 600; font-size: .95rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.saved-wallet-addr {
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: .75rem; color: var(--hint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.saved-wallet-badge {
  flex-shrink: 0;
  padding: 4px 8px;
  font-size: .7rem; font-weight: 700; letter-spacing: .3px;
  border-radius: 999px;
  background: rgba(255,255,255,.08); color: var(--hint);
  text-transform: uppercase; white-space: nowrap;
}
.saved-wallet-badge.matching {
  background: rgba(212,175,55,.18); color: var(--gold);
}

/* Saved-wallet delete button + row layout */
.saved-wallet-row {
  display: flex; align-items: stretch; gap: 6px;
}
.saved-wallet-row .saved-wallet-item { flex: 1; }
.saved-wallet-delete {
  flex-shrink: 0; width: 44px; min-height: 56px;
  background: transparent; border: 1px solid rgba(255,255,255,.08);
  border-radius: 10px; color: rgba(255,255,255,.5);
  font-size: 1.1rem; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.saved-wallet-delete:active {
  background: rgba(231,76,60,.15); color: var(--danger);
  border-color: rgba(231,76,60,.35);
}

/* "Add new wallet" CTA + empty state inside the picker */
.saved-wallets-add-btn {
  margin-top: 4px; padding: 12px; min-height: 48px;
  background: transparent;
  border: 1px dashed rgba(212,175,55,.4);
  border-radius: 10px;
  color: var(--gold); font-weight: 600; font-size: .95rem;
  cursor: pointer; text-align: center;
  transition: background .15s ease, border-color .15s ease;
}
.saved-wallets-add-btn:active {
  background: rgba(212,175,55,.1); border-color: var(--gold);
}
.saved-wallets-empty {
  padding: 16px 8px; text-align: center; color: var(--hint);
  font-size: .9rem;
}

/* Add-wallet form — same dark card feel as the picker */
.saved-wallets-form {
  margin-top: 10px; padding: 14px;
  background: var(--surface);
  border: 1px solid rgba(212,175,55,.25);
  border-radius: var(--radius);
  animation: fadeIn .2s ease;
}
.saved-wallets-form-row { margin-bottom: 10px; }
.saved-wallets-form-row label {
  display: block; font-size: .8rem; color: var(--hint);
  font-weight: 600; margin-bottom: 4px; text-transform: uppercase;
  letter-spacing: .5px;
}
.saved-wallets-form-row input[type="text"] {
  width: 100%; background: rgba(0,0,0,.3);
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--radius); padding: 12px;
  color: var(--text); font-size: 1rem; outline: none;
}
.saved-wallets-form-row input:focus { border-color: var(--gold); }
.saved-wallets-form-row .currency-btn {
  min-width: 110px; padding: 11px 14px;
}
.saved-wallets-form-error {
  color: var(--danger); font-size: .85rem; margin: 4px 0 10px;
  padding: 8px 10px; background: rgba(231,76,60,.1);
  border-radius: 8px; border: 1px solid rgba(231,76,60,.25);
}
.saved-wallets-form-actions {
  display: flex; flex-direction: column; gap: 6px; margin-top: 10px;
}

/* Toast — lightweight feedback after add/delete */
.toast {
  position: fixed; left: 16px; right: 16px; top: 16px;
  padding: 12px 16px; border-radius: 10px;
  background: #2a2a3e; color: var(--text);
  font-size: .95rem; font-weight: 600; text-align: center;
  z-index: 300; box-shadow: 0 6px 20px rgba(0,0,0,.35);
  border: 1px solid rgba(255,255,255,.08);
  animation: fadeIn .2s ease;
}
.toast.toast-success {
  background: rgba(39,174,96,.95); color: #fff;
  border-color: rgba(39,174,96,.6);
}
.toast.toast-error {
  background: rgba(231,76,60,.95); color: #fff;
  border-color: rgba(231,76,60,.6);
}

/* The legacy .tab-nav-secondary horizontal row (Alerts / Wallets /
   History) was removed when the hamburger menu took over all tab
   navigation — every selector that targeted it has been deleted to
   avoid confusing future readers. The same items now live inside
   .ham-panel and use .ham-item for layout + active state. */

/* Alerts tab */
.alerts-list { display: flex; flex-direction: column; gap: 8px; }
.alerts-empty {
  text-align: center; color: var(--hint);
  padding: 24px 16px; font-size: .92rem;
  background: var(--surface); border-radius: var(--radius);
}
.alert-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px; background: var(--surface);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 12px; min-height: 56px;
}
.alert-icon { flex-shrink: 0; display: inline-flex; align-items: center; }
.alert-body { flex: 1; min-width: 0; }
.alert-title {
  font-weight: 700; font-size: 1rem; color: var(--gold);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.alert-sub {
  font-size: .8rem; color: var(--hint); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.alert-delete {
  flex-shrink: 0; width: 44px; height: 44px;
  background: transparent; border: 1px solid rgba(255,255,255,.08);
  border-radius: 10px; color: rgba(255,255,255,.5);
  font-size: 1.05rem; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.alert-delete:active {
  background: rgba(231,76,60,.15); color: var(--danger);
  border-color: rgba(231,76,60,.35);
}
.alerts-form {
  margin-top: 14px; padding: 16px;
  background: var(--surface);
  border: 1px solid rgba(212,175,55,.25);
  border-radius: var(--radius);
  animation: fadeIn .2s ease;
}
.alerts-form-row { margin-bottom: 12px; }
.alerts-form-row label {
  display: block; font-size: .8rem; color: var(--hint);
  font-weight: 600; margin-bottom: 6px;
  text-transform: uppercase; letter-spacing: .5px;
}
.alerts-form-row input[type="text"] {
  width: 100%; background: rgba(0,0,0,.3);
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--radius); padding: 12px;
  color: var(--text); font-size: 1rem; outline: none;
}
.alerts-form-row input:focus { border-color: var(--gold); }
.alerts-form-row .currency-btn { min-width: 110px; padding: 11px 14px; }
.alerts-current {
  padding: 8px 10px; background: rgba(212,175,55,.08);
  border: 1px solid rgba(212,175,55,.25); border-radius: 8px;
  color: var(--gold); font-size: .85rem; margin-bottom: 10px;
}
.alerts-error {
  color: var(--danger); font-size: .85rem;
  padding: 8px 10px; background: rgba(231,76,60,.1);
  border-radius: 8px; border: 1px solid rgba(231,76,60,.25);
  margin: 4px 0 10px;
}
.alerts-form-actions {
  display: flex; flex-direction: column; gap: 6px; margin-top: 10px;
}

/* History tab */
.history-list { display: flex; flex-direction: column; gap: 8px; }
.history-empty, .history-loading {
  text-align: center; color: var(--hint);
  padding: 24px 16px; font-size: .92rem;
  background: var(--surface); border-radius: var(--radius);
}
.history-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 12px; min-height: 64px;
  background: var(--surface);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 12px;
  color: var(--text); font-family: inherit;
  text-align: left; cursor: pointer;
  transition: background .15s ease, transform .1s ease;
}
.history-row:active { transform: scale(.99); background: rgba(212,175,55,.08); }
.history-badge {
  flex-shrink: 0; padding: 6px 10px;
  border-radius: 8px; font-size: .72rem; font-weight: 700;
  letter-spacing: .3px; white-space: nowrap;
  background: rgba(255,255,255,.08); color: var(--hint);
}
.history-badge.status-new       { background: rgba(52,152,219,.18);  color: #3498db; }
.history-badge.status-pending   { background: rgba(241,196,15,.18);  color: #f1c40f; }
.history-badge.status-exchange  { background: rgba(155,89,182,.18);  color: #9b59b6; }
.history-badge.status-withdraw  { background: rgba(52,152,219,.18);  color: #3498db; }
.history-badge.status-done      { background: rgba(39,174,96,.18);   color: #27ae60; }
.history-badge.status-expired   { background: rgba(149,165,166,.18); color: #95a5a6; }
.history-badge.status-emergency { background: rgba(231,76,60,.18);   color: #e74c3c; }
.history-badge.status-refund    { background: rgba(241,196,15,.18);  color: #f1c40f; }
.history-body { flex: 1; min-width: 0; }
.history-main {
  font-weight: 600; font-size: .95rem; color: var(--text);
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  overflow: hidden; text-overflow: ellipsis;
}
.history-sub {
  font-size: .78rem; color: var(--hint); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Chip row shows Order ID (mono, gold) + network + rate type
   so the user can identify each swap at a glance. Chips wrap on
   narrow screens and stay left-aligned on wide ones. */
.history-chips {
  display: flex; flex-wrap: wrap; gap: 4px 6px;
  margin-top: 4px; align-items: center;
}
.history-chip {
  padding: 1px 7px; border-radius: 6px;
  font-size: .72rem; font-weight: 600;
  line-height: 1.5;
  letter-spacing: .2px;
  white-space: nowrap;
}
.history-chip-id {
  background: rgba(212,175,55,.12);
  color: var(--gold);
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  letter-spacing: .5px;
}
.history-chip-net {
  background: rgba(52,152,219,.12);
  color: #8bc7f0;
}
.history-chip-rate {
  background: rgba(155,89,182,.14);
  color: #c28ce0;
  text-transform: uppercase;
}
.history-chip-rate.rate-fixed {
  background: rgba(52,152,219,.14);
  color: #8bc7f0;
}
.history-chev {
  flex-shrink: 0; color: var(--hint); font-size: 1.4rem;
}

/* Help — status reference + detailed steps */
.help-status-list { display: flex; flex-direction: column; gap: 10px; }
.help-status-item {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--surface); border-radius: var(--radius); padding: 12px;
}
.help-status-badge {
  flex-shrink: 0; padding: 6px 10px; border-radius: 8px;
  font-size: .75rem; font-weight: 700; letter-spacing: .3px;
  white-space: nowrap; align-self: flex-start;
  background: rgba(255,255,255,.08); color: var(--hint);
}
.help-status-badge.status-new       { background: rgba(52,152,219,.18);  color: #3498db; }
.help-status-badge.status-pending   { background: rgba(241,196,15,.18);  color: #f1c40f; }
.help-status-badge.status-exchange  { background: rgba(155,89,182,.18);  color: #9b59b6; }
.help-status-badge.status-withdraw  { background: rgba(52,152,219,.18);  color: #3498db; }
.help-status-badge.status-done      { background: rgba(39,174,96,.18);   color: #27ae60; }
.help-status-badge.status-expired   { background: rgba(149,165,166,.18); color: #95a5a6; }
.help-status-badge.status-emergency { background: rgba(231,76,60,.18);   color: #e74c3c; }
.help-status-badge.status-refund    { background: rgba(241,196,15,.18);  color: #f1c40f; }
.help-status-item p {
  font-size: .88rem; color: var(--text); margin: 0; line-height: 1.55;
}

/* Hide HTML buttons that duplicate the native MainButton / BackButton.
   #btn-next-confirm (Review Swap) and #btn-create-order (Confirm Swap)
   stay VISIBLE in the thumb-reach zone — see rule above. */
.tg-app #btn-next-address,
.tg-app #btn-back-currencies,
.tg-app #btn-back-address,
.tg-app #btn-new-swap {
  display:none !important;
}

/* ─── Preview mode (Mini App opened in a plain browser) ────────── */
/* When there is no Telegram context, /ff-price still works (public
   path with IP rate limiting + 15s cache) so users can check rates,
   but per-user tabs and order mutations need the Telegram bot. The
   banner directs them there; the auth-only tabs are hidden to avoid
   confusing dead-ends. */
/* The legacy "preview banner" (Open in Telegram / Swap on acechange.io)
   was removed once the PWA became the primary, fully-functional app.
   In-browser users no longer see a takeover banner — they just use
   the swap form directly. The maintenance takeover (.pwa-maintenance)
   below remains for admin-controlled upgrade windows. */

/* ─── Phase D: Install app button + iOS install hint ─────────── */
/* beforeinstallprompt surfaces on Chrome/Edge/Samsung Internet.
   Sits at the very top of #app (above the preview banner). Gold
   filled primary action — one tap triggers the browser prompt. */
.pwa-install-btn {
  display: block; width: 100%;
  background: var(--gold); color: #000;
  border: none; border-radius: 10px;
  padding: 12px 16px; margin: 0 0 12px;
  font-size: .95rem; font-weight: 700;
  cursor: pointer; min-height: 44px;
  box-shadow: 0 2px 8px rgba(212,175,55,.35);
  transition: transform .1s ease, box-shadow .15s ease;
}
.pwa-install-btn:active { transform: scale(.98); }
.pwa-install-btn:hover  { box-shadow: 0 3px 12px rgba(212,175,55,.5); }

/* iOS Safari has no beforeinstallprompt — we instead show a compact
   tip explaining the Share ▸ Add to Home Screen gesture. Dismissible
   and persisted so we don't nag. */
.ios-install-hint {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; margin: 0 0 12px;
  background: rgba(52,152,219,.14);
  border: 1px solid rgba(52,152,219,.35);
  border-radius: 10px;
  font-size: .82rem; color: var(--text); line-height: 1.35;
}
.ios-install-hint-icon { font-size: 1.1rem; flex-shrink: 0; }
.ios-install-hint-text { flex: 1; min-width: 0; }
.ios-install-hint-text strong { color: var(--gold); }
.ios-install-hint-dismiss {
  flex-shrink: 0; background: transparent; color: var(--hint);
  border: none; padding: 10px 12px; cursor: pointer;
  font-size: 1rem; line-height: 1;
  min-height: 44px; min-width: 44px;
  display: flex; align-items: center; justify-content: center;
}
.ios-install-hint-dismiss:active { color: var(--text); }

/* ─── PWA admin-triggered maintenance takeover ──────────────────
   Shown when /ff-config returns pwa_maintenance:true. Fully
   replaces #app content — no nav, no form, no distractions. */
.pwa-maintenance {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  min-height: 75vh; padding: 40px 20px;
  text-align: center; color: var(--text);
}
.pwa-maintenance-icon { font-size: 3.2rem; margin-bottom: 18px; }
.pwa-maintenance h1 {
  font-size: 1.4rem; margin: 0 0 12px;
  color: var(--gold); font-weight: 700;
}
.pwa-maintenance p {
  font-size: 1rem; margin: 0 0 28px;
  max-width: 420px; line-height: 1.5; color: var(--text);
}
.pwa-maintenance-cta {
  background: var(--gold); color: #000;
  font-weight: 700; padding: 12px 24px;
  border-radius: 10px; text-decoration: none;
  min-height: 44px; display: inline-flex; align-items: center;
}
.pwa-maintenance-cta:active { transform: scale(.97); }
body.pwa-maintenance-active #ham-btn,
body.pwa-maintenance-active #ham-panel,
body.pwa-maintenance-active #ham-overlay,
body.pwa-maintenance-active #pwa-install-btn,
body.pwa-maintenance-active #ios-install-hint { display: none !important; }

/* ─── Settings tab + PIN UI ─── */
.settings-card {
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 14px;
}
.settings-card h3 { margin: 0 0 8px; font-size: 1rem; color: var(--gold); }
.settings-hint    { color: var(--hint); font-size: .88rem; margin: 0 0 14px; line-height: 1.5; }
.pin-feature-disabled {
  background: rgba(231,76,60,.1);
  border: 1px solid rgba(231,76,60,.4);
  color: #ffaca6; padding: 10px 12px; border-radius: 8px;
  font-size: .9rem;
}
.pin-block { margin-top: 8px; }
.pin-block label {
  display: block; margin: 12px 0 6px;
  color: #fff; font-size: .9rem; font-weight: 600;
}
.pin-block input[type="password"] {
  width: 100%; padding: 12px 14px;
  background: rgba(0,0,0,.3); color: #fff;
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 8px;
  font-size: 1.4rem; letter-spacing: .4em; text-align: center;
  font-family: ui-monospace, Menlo, monospace;
}
.pin-block input[type="password"]:focus {
  outline: none; border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(212,175,55,.18);
}
.pin-status-on { color: #6eea93; margin-bottom: 12px; font-weight: 600; }
.pin-form-error {
  background: rgba(231,76,60,.12);
  border: 1px solid rgba(231,76,60,.4);
  color: #ffaca6; padding: 10px 12px; border-radius: 8px;
  font-size: .9rem; margin-top: 10px;
}
.pin-block .secondary-btn { margin-top: 8px; }

/* ─── PIN lock screen ─── */
.pin-lock {
  position: fixed; inset: 0;
  background: linear-gradient(180deg, #0d0f1d 0%, #1a1a2e 100%);
  z-index: 100000;
  display: flex; align-items: center; justify-content: center;
  /* Padding respects iOS Dynamic Island / notch + home-indicator so
     the lock UI never collides with the status bar even on large
     content (e.g. error messages that push the form lower).
     Apple HIG "Layout" — clear safe-area inset for all interactive
     surfaces in standalone PWA mode. */
  padding: calc(40px + env(safe-area-inset-top, 0px)) 20px calc(40px + env(safe-area-inset-bottom, 0px));
}
.pin-lock-inner {
  width: 100%; max-width: 360px; text-align: center;
}
.pin-lock-logo { font-size: 3.6rem; margin-bottom: 10px; }
.pin-lock-title {
  font-size: 1.6rem; font-weight: 700; color: var(--gold);
  margin: 0 0 4px;
}
.pin-lock-sub  { color: var(--hint); font-size: .95rem; margin: 0 0 22px; }
.pin-lock input[type="password"] {
  width: 100%; max-width: 280px;
  padding: 16px 14px;
  background: rgba(255,255,255,.05); color: #fff;
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 10px;
  font-size: 1.6rem; letter-spacing: .5em; text-align: center;
  font-family: ui-monospace, Menlo, monospace;
}
.pin-lock input[type="password"]:focus {
  outline: none; border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(212,175,55,.18);
}
.pin-lock-error {
  background: rgba(231,76,60,.15);
  border: 1px solid rgba(231,76,60,.4);
  color: #ffaca6; padding: 10px 12px; border-radius: 8px;
  font-size: .9rem; margin: 14px 0 4px;
}
.pin-lock .primary-btn { margin-top: 18px; width: 100%; max-width: 280px; }

/* "Forgot PIN?" recovery link — small + subtle so it doesn't
   compete visually with the primary "Unlock" button (Apple HIG
   "Buttons" guidance: secondary destructive paths must be visibly
   secondary). Becomes more prominent on hover. */
.pin-forgot-link {
  display: inline-block; margin-top: 14px;
  background: none; border: 0; padding: 8px 14px;
  color: var(--hint); font-size: .9rem;
  cursor: pointer; text-decoration: underline;
  font-family: inherit;
}
.pin-forgot-link:hover, .pin-forgot-link:focus-visible {
  color: var(--gold); outline: none;
}

/* PIN-reset confirmation modal — sheet-style overlay above the
   pin-lock screen. z-index 100001 = pin-lock (100000) + 1, so the
   reset modal paints on top of the lock without visual fight. */
.pin-reset-modal {
  position: fixed; inset: 0; z-index: 100001;
  display: flex; align-items: center; justify-content: center;
  padding: calc(20px + env(safe-area-inset-top, 0px)) 20px
           calc(20px + env(safe-area-inset-bottom, 0px));
  background: rgba(0, 0, 0, .72);
}
.pin-reset-card {
  background: #1a1a2e; border: 1px solid rgba(255, 215, 0, .25);
  border-radius: 14px; padding: 22px 22px 18px;
  width: 100%; max-width: 380px; text-align: center;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .5);
}
.pin-reset-icon { font-size: 2.4rem; margin-bottom: 8px; }
.pin-reset-title {
  margin: 0 0 10px; font-size: 1.05rem; font-weight: 700;
  color: #ff4d4d; letter-spacing: .2px;
}
.pin-reset-msg {
  margin: 0 0 12px; color: var(--text); font-size: .95rem;
}
.pin-reset-list {
  list-style: none; padding: 12px 14px; margin: 0 0 14px;
  background: rgba(0, 0, 0, .35);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 10px; text-align: left;
}
.pin-reset-list li {
  padding: 5px 0; color: var(--text); font-size: .92rem;
  border-bottom: 1px solid rgba(255, 255, 255, .04);
}
.pin-reset-list li:last-child { border-bottom: none; }
.pin-reset-note {
  font-size: .82rem; color: var(--hint); margin: 0 0 16px;
}
.pin-reset-actions {
  display: flex; gap: 10px;
}
.pin-reset-actions > button {
  flex: 1; padding: 12px 14px; font-size: .95rem;
  border-radius: 10px; cursor: pointer; font-weight: 600;
  font-family: inherit;
}
/* Reuse .secondary-btn / .primary-btn styles already defined above
   for Cancel; "Erase & reset" gets a danger style — red background,
   white text — to make the destructive action unambiguous. */
.danger-btn {
  background: #ff4d4d; color: #fff; border: 0;
}
.danger-btn:hover, .danger-btn:focus-visible {
  background: #e83737; outline: none;
}
.danger-btn:active { background: #c92929; }
/* While the PIN lock screen is up the hamburger button + its panel
   must be inert — the lock overlay (z-index 100000) already paints
   over them, but hiding their backing nodes prevents tab-key focus
   from landing on hidden controls and blocks any rogue programmatic
   open until the user unlocks. */
body.pin-locked { overflow: hidden; }
body.pin-locked #ham-btn,
body.pin-locked #ham-panel,
body.pin-locked #ham-overlay { display: none !important; }
/* v7.5.14 — Privacy Chat (BETA) styles. Scoped under .chat-root and
   chat-* classes so they don't leak into the swap UI. Reuses the
   shared color tokens (--bg, --surface, --gold, --text, --hint)
   from the top of style.css. */

/* BETA pill in the hamburger menu tab label. */
.beta-badge {
  display: inline-block;
  background: rgba(212,175,55,.18);
  color: var(--gold);
  border: 1px solid rgba(212,175,55,.45);
  border-radius: 6px;
  padding: 1px 6px;
  font-size: .65rem;
  font-weight: 700;
  letter-spacing: .4px;
  margin-left: 6px;
  vertical-align: middle;
}

.chat-root { display: flex; flex-direction: column; }

.chat-card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 18px;
  margin: 16px 0;
}

.chat-card h2 {
  margin: 0 0 12px;
  font-size: 1.1rem;
  text-align: left;
  line-height: 1.35;
}

.chat-card p { line-height: 1.5; margin: 0 0 10px; }

.chat-disclosure {
  color: var(--hint);
  font-size: .9rem;
}
.chat-disclosure-warn {
  background: rgba(255,77,77,.08);
  border: 1px solid rgba(255,77,77,.35);
  border-radius: 8px;
  padding: 10px 12px;
  color: #ffb0b0;
  font-size: .9rem;
}

.chat-card-actions {
  display: flex; flex-direction: column; gap: 12px; margin: 16px 0;
}

/* Inline notices. */
.chat-notice {
  padding: 10px 12px; border-radius: 8px;
  margin: 12px 0; font-size: .92rem; line-height: 1.45;
}
.chat-notice-info  { background: rgba(212,175,55,.08); color: var(--text); border: 1px solid rgba(212,175,55,.25); }
.chat-notice-error { background: rgba(255,77,77,.10);  color: #ffb0b0;     border: 1px solid rgba(255,77,77,.35); }

/* Toast top-of-screen. */
.chat-toast {
  position: fixed; top: max(20px, env(safe-area-inset-top, 20px));
  left: 50%; transform: translateX(-50%);
  background: var(--surface); color: var(--text);
  border: 1px solid rgba(255,255,255,.12);
  padding: 10px 16px; border-radius: 999px;
  font-size: .9rem; z-index: 10000;
  box-shadow: 0 4px 16px rgba(0,0,0,.35);
}

/* Recovery phrase grid. */
.chat-phrase-grid {
  list-style: none; padding: 0; margin: 16px 0;
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 8px 12px;
}
.chat-phrase-word {
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px;
  padding: 10px 12px;
  display: flex; align-items: baseline; gap: 8px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
}
.chat-phrase-num { color: var(--hint); font-size: .8rem; min-width: 24px; }
.chat-phrase-text { color: var(--gold); font-weight: 600; font-size: .95rem; }

/* Confirm phrase / restore textarea. */
.chat-confirm-input,
.chat-restore-textarea,
.chat-input {
  width: 100%;
  background: var(--surface);
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--radius);
  padding: 14px;
  color: var(--text);
  font-size: 16px;
  outline: none;
  min-height: 48px;
  font-family: inherit;
  transition: border-color .08s ease, box-shadow .08s ease;
}
.chat-confirm-input:focus,
.chat-restore-textarea:focus,
.chat-input:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(212,175,55,.18);
}
.chat-input-error { border-color: #ff4d4d; }

/* Conversation list. */
.chat-conv-toolbar { flex-direction: row; }
.chat-conv-list { list-style: none; padding: 0; margin: 0; }
.chat-conv-item {
  display: flex; align-items: center; gap: 12px;
  padding: 14px;
  border-bottom: 1px solid rgba(255,255,255,.06);
  cursor: pointer;
  transition: background .08s ease, transform .08s ease;
  user-select: none;
}
.chat-conv-item:active { background: rgba(212,175,55,.08); transform: scale(.99); }
.chat-conv-avatar {
  width: 40px; height: 40px;
  background: rgba(212,175,55,.10);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.1rem;
}
.chat-conv-meta { flex: 1; min-width: 0; }
.chat-conv-label { font-weight: 600; font-size: .95rem; }
.chat-conv-preview { color: var(--hint); font-size: .82rem; margin-top: 2px; }
.chat-conv-unread {
  background: var(--gold); color: #1a1a2e;
  border-radius: 999px;
  min-width: 22px; height: 22px;
  font-size: .75rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  padding: 0 7px;
}
.chat-empty {
  text-align: center; color: var(--hint);
  padding: 32px 16px; font-size: .92rem; line-height: 1.5;
}

/* v7.5.26 — friendly empty-state hero on conversation list. */
.chat-empty-hero {
  text-align: center;
  padding: 28px 16px 36px;
  margin: 12px 0 24px;
  background: linear-gradient(180deg, rgba(212,175,55,.06), rgba(212,175,55,.02));
  border: 1px solid rgba(212,175,55,.18);
  border-radius: 16px;
}
.chat-empty-illustration {
  font-size: 56px; line-height: 1; margin-bottom: 14px;
  filter: drop-shadow(0 2px 8px rgba(212,175,55,.25));
}
.chat-empty-title {
  margin: 0 0 6px; font-size: 1.25rem; color: var(--text);
}
.chat-empty-sub {
  margin: 0 auto 20px; max-width: 320px;
  color: var(--hint); font-size: .9rem; line-height: 1.5;
}
.chat-empty-steps {
  text-align: left; max-width: 360px; margin: 0 auto;
}
.chat-empty-hint {
  margin: 18px auto 0; max-width: 320px;
  color: var(--hint); font-size: .82rem; opacity: .85;
}

/* v7.5.26 — Settings hero card (My chat ID). Distinguished from
   regular cards with a subtle gold accent + elevation so the
   primary share-invite action is the obvious entry point. */
.chat-card-hero {
  background: linear-gradient(180deg, rgba(212,175,55,.08), var(--surface) 60%);
  border: 1px solid rgba(212,175,55,.28);
  box-shadow: 0 4px 18px rgba(0,0,0,.18);
}
.chat-userid-display {
  background: rgba(0,0,0,.32);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 10px;
  padding: 14px;
  margin: 12px 0 4px;
}
.chat-userid-short {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1.08rem;
  letter-spacing: .04em;
  color: var(--gold);
  text-align: center;
  word-break: break-all;
}
.chat-userid-full {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .68rem;
  color: var(--hint);
  word-break: break-all;
  margin-top: 8px;
  opacity: .7;
  text-align: center;
}

/* v7.5.26 — How-it-works disclosure inside the hero card. */
.chat-howto-details {
  margin-top: 14px;
  border-top: 1px solid rgba(255,255,255,.06);
  padding-top: 12px;
}
.chat-howto-details > summary {
  cursor: pointer;
  list-style: none;
  padding: 8px 0;
  color: var(--gold);
  font-weight: 600;
  font-size: .92rem;
}
.chat-howto-details > summary::-webkit-details-marker { display: none; }
.chat-howto-details[open] > summary { margin-bottom: 8px; }
.chat-howto-body h3 {
  margin: 14px 0 6px; font-size: .95rem; color: var(--text);
}
.chat-howto-steps {
  margin: 0 0 4px 0;
  padding-left: 22px;
  color: var(--text);
  font-size: .9rem;
  line-height: 1.55;
}
.chat-howto-steps li {
  margin-bottom: 8px;
}
.chat-howto-steps li::marker {
  color: var(--gold);
  font-weight: 700;
}

/* Conversation screen. */
.chat-conv-header {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-bottom: 1px solid rgba(255,255,255,.06);
  background: var(--bg);
  flex: 0 0 auto;
}
.chat-back-btn {
  background: transparent; border: 0; color: var(--gold);
  font-size: 1.6rem; line-height: 1; padding: 6px 10px;
  cursor: pointer; min-width: 44px; min-height: 44px;
}
.chat-conv-title { font-weight: 600; }
.chat-conv-title-text { vertical-align: middle; }

/* v7.5.50 / v7.5.53 — viewport-locked conversation screen.
   Pre-fix the conversation lived inside a normal tab with
   `.chat-messages { max-height: 60vh }`, which left a visible gap
   between the composer and the soft keyboard on iOS Safari (vh
   doesn't react to keyboard) and broke landscape entirely.

   v7.5.53 — fixes the "input bar jumps to top of screen on focus"
   regression. iOS Safari shifts the LAYOUT viewport upward when
   an input is focused so the input is on screen; a `position:
   fixed; inset: 0` element is anchored to the LAYOUT viewport, so
   it shifts up too — leaving the composer floating somewhere in
   the middle (or at the very top, see screenshot bug report).
   Pattern used by Telegram Web Z / WhatsApp Web: skip `inset` and
   instead set `top/left/width/height` from `visualViewport` props
   in JS so the screen tracks the VISUAL viewport (what the user
   actually sees), not the layout viewport. CSS provides a safe
   100vh fallback for browsers without visualViewport API.
*/
.chat-conv-screen {
  position: fixed;
  top: 0; left: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  z-index: 9000;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  overscroll-behavior: contain;
  contain: layout size;
}

/* Header gets safe-area-inset-top so the back button doesn't sit
   under the iOS notch on standalone PWA / Add-to-Home-Screen. */
.chat-conv-screen .chat-conv-header {
  padding-top: calc(10px + env(safe-area-inset-top, 0));
}

.chat-messages {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 10px 12px 14px;
  display: flex; flex-direction: column;
  gap: 10px;            /* default gap between sender changes */
  overscroll-behavior: contain;
}
.chat-bubble-row { display: flex; }
.chat-bubble-row-out { justify-content: flex-end; }
.chat-bubble-row-in  { justify-content: flex-start; }
/* Tighter spacing inside a same-sender run (WhatsApp-style). */
.chat-bubble-row.is-grouped { margin-top: -6px; }
.chat-bubble {
  max-width: 78%;
  padding: 8px 12px 6px;
  border-radius: 16px;
  word-wrap: break-word; overflow-wrap: anywhere;
  line-height: 1.4;
  font-size: 15px;
  position: relative;
}
.chat-bubble-out { background: rgba(212,175,55,.20); color: var(--text); border-top-right-radius: 4px; }
.chat-bubble-in  { background: rgba(255,255,255,.06); color: var(--text); border-top-left-radius: 4px; }
/* Inside a grouped run, soften the "tail" corner so only the first
   bubble in the run shows the asymmetric corner — looks like a
   continuous thread instead of repeating tails. */
.chat-bubble-row.is-grouped .chat-bubble-out { border-top-right-radius: 16px; }
.chat-bubble-row.is-grouped .chat-bubble-in  { border-top-left-radius: 16px; }
.chat-bubble-text { white-space: pre-wrap; }
.chat-bubble-meta { color: var(--hint); font-size: .68rem; margin-top: 4px; text-align: right; }
.chat-bubble-row-in .chat-bubble-meta { text-align: left; }
/* Hide timestamp + status on every bubble whose successor groups
   with it — only the LAST bubble of a run shows meta. The
   appendMessage helper sets is-grouped-prev when adding a new bubble
   that grouped with the previous one. */
.chat-bubble-row.is-grouped-prev .chat-bubble-meta { display: none; }

/* Composer. */
.chat-composer {
  display: flex; align-items: flex-end; gap: 8px;
  padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0));
  border-top: 1px solid rgba(255,255,255,.06);
  background: var(--bg);
  flex: 0 0 auto;
}
/* v7.5.59 — composer is now a contenteditable <div>, NOT a <textarea>.
   The element is the same .chat-composer-input class so all sizing,
   colour, focus-ring and surrounding flexbox layout are preserved.
   Auto-grow happens naturally via min/max-height + overflow-y:auto
   (no JS height measurement needed). */
.chat-composer-input {
  flex: 1;
  background: var(--surface);
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 18px;
  padding: 10px 14px;
  color: var(--text);
  font-size: 16px;
  font-family: inherit;
  line-height: 1.4;
  outline: none;
  min-height: 44px;
  max-height: 120px;
  overflow-y: auto;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  -webkit-user-select: text;
  user-select: text;
  /* Bound the contenteditable to its box so a paste of a very long
     unbroken token doesn't blow out the layout. */
  max-width: 100%;
  transition: border-color .08s ease;
}
/* Placeholder for contenteditable — :empty matches when there are
   no child nodes AND no text. Carries the placeholder string from
   the data-placeholder attribute set in chat-ui.js. */
.chat-composer-input:empty::before {
  content: attr(data-placeholder);
  color: var(--hint);
  pointer-events: none;
  /* Don't let the placeholder pseudo-element accept caret clicks —
     the caret should always land in the contenteditable text node. */
  display: inline-block;
}
.chat-composer-input:focus { border-color: var(--gold); }
.chat-composer-send {
  background: var(--gold); color: var(--btn-text);
  border: 0; border-radius: 50%;
  min-width: 44px; min-height: 44px;
  font-size: 1.2rem; font-weight: 700;
  cursor: pointer;
  user-select: none;
  transition: transform .08s ease, opacity .08s ease;
}
.chat-composer-send:active { transform: scale(.94); opacity: .9; }

/* Invite share. */
.chat-invite-url-box {
  background: rgba(0,0,0,.30);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px;
  padding: 12px;
  margin: 12px 0;
  word-break: break-all;
}
.chat-invite-url {
  color: var(--gold); font-size: .8rem;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
}


/* v7.5.17 — chat QR generator + scanner. */
.chat-qr-box {
  display: flex; justify-content: center;
  margin: 16px 0;
  padding: 12px;
  background: rgba(255,255,255,.04);
  border-radius: 8px;
}
.chat-qr-scanner-slot {
  margin-top: 16px;
  padding: 12px;
  background: rgba(0,0,0,.30);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px;
}
.chat-qr-video {
  display: block;
  width: 100%;
  max-width: 320px;
  margin: 8px auto;
  border-radius: 8px;
  background: #000;
}

/* v7.5.17 — chat conversation kebab + bottom sheet for manage actions. */
.chat-conv-kebab {
  background: transparent;
  border: 0;
  color: var(--hint);
  font-size: 1.4rem;
  line-height: 1;
  padding: 8px 6px;
  margin-left: 4px;
  min-width: 44px;
  min-height: 44px;
  cursor: pointer;
  user-select: none;
  border-radius: 6px;
  transition: background .08s ease, color .08s ease;
}
.chat-conv-kebab:hover,
.chat-conv-kebab:focus-visible {
  background: rgba(255,255,255,.06);
  color: var(--text);
}

.chat-modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.55);
  z-index: 9998;
  display: flex; align-items: flex-end; justify-content: center;
  animation: chatFadeIn .15s ease;
}
@keyframes chatFadeIn { from { opacity: 0; } to { opacity: 1; } }
.chat-bottom-sheet {
  width: 100%; max-width: 520px;
  background: var(--surface);
  border-radius: 16px 16px 0 0;
  padding: 16px 16px max(20px, env(safe-area-inset-bottom, 20px));
  border: 1px solid rgba(255,255,255,.08);
  border-bottom: 0;
  box-shadow: 0 -8px 24px rgba(0,0,0,.45);
}
.chat-bottom-sheet-inner {
  display: flex; flex-direction: column; gap: 10px;
}
.chat-bottom-sheet-title {
  font-weight: 600; text-align: center;
  color: var(--text); margin: 4px 0 12px;
  font-size: .95rem;
}

/* v7.5.18 — recovery phrase blur reveal + advanced toggle. */
.chat-phrase-wrap { position: relative; margin: 16px 0; }
.chat-phrase-blurred { filter: blur(8px); pointer-events: none; user-select: none; }
.chat-phrase-reveal-overlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  cursor: pointer;
  background: rgba(26,26,46,.4);
  border-radius: var(--radius);
  user-select: none;
  transition: background .12s ease;
}
.chat-phrase-reveal-overlay:hover { background: rgba(26,26,46,.55); }
.chat-phrase-reveal-icon { font-size: 2rem; }
.chat-phrase-reveal-text {
  color: var(--gold); font-weight: 700;
  margin-top: 6px; font-size: .9rem;
}

.chat-advanced-toggle summary {
  cursor: pointer; font-weight: 600; color: var(--hint);
  padding: 8px 0; user-select: none;
}
.chat-advanced-toggle summary:hover { color: var(--text); }
.chat-advanced-body { padding: 8px 0; }
.chat-radio-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 0; cursor: pointer; line-height: 1.4;
}
.chat-radio-row input { margin: 0; transform: scale(1.2); accent-color: var(--gold); }

/* v7.5.19 — Phase 2 chat media (image attach + bubble). */
.chat-composer-attach {
  background: transparent; border: 0;
  color: var(--gold);
  font-size: 1.25rem; line-height: 1;
  padding: 0;
  min-width: 44px; min-height: 44px;
  cursor: pointer; user-select: none;
  border-radius: 50%;
  transition: background .08s ease, transform .08s ease;
}
.chat-composer-attach:hover  { background: rgba(212,175,55,.08); }
.chat-composer-attach:active { transform: scale(.94); }

.chat-bubble-media {
  margin: 0 0 4px;
  border-radius: 8px;
  overflow: hidden;
  min-width: 180px;
}
.chat-bubble-media-locked {
  background: rgba(0,0,0,.35);
  border: 1px dashed rgba(212,175,55,.45);
  padding: 28px 16px;
  text-align: center;
  cursor: pointer;
  user-select: none;
  transition: background .08s ease;
}
.chat-bubble-media-locked:hover { background: rgba(0,0,0,.45); }
.chat-bubble-media-locked:active { transform: scale(.99); }
.chat-media-icon { font-size: 1.6rem; margin-bottom: 6px; }
.chat-media-hint { color: var(--hint); font-size: .82rem; line-height: 1.4; }

/* v7.5.22 — multi-mailbox custom config display in chat Settings. */
.chat-mailbox-info {
  background: rgba(0,0,0,.30);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: 6px;
}
.chat-mailbox-label {
  font-weight: 600;
  font-size: .92rem;
  color: var(--text);
  margin-bottom: 4px;
}
.chat-mailbox-url {
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: .78rem;
  color: var(--gold);
  word-break: break-all;
  line-height: 1.35;
}
.chat-mailbox-fingerprint {
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: .72rem;
  color: var(--hint);
  margin-top: 6px;
  letter-spacing: .3px;
}

/* v7.5.34 — Emergency mode (SOS) panel styles.
   Goal: large, branded "Add contact" CTA so the action looks
   intentional and matches the rest of the AceChange visual identity
   (gold #d4af37 + black on gold + rounded radius + 48 px touch). */
.panic-add-cta {
  /* Inherits .primary-btn (gold bg + black text). Override for a
     larger, more prominent CTA — this is the user's first
     interaction with emergency mode setup, so visual weight matters. */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px 18px;
  font-size: 1.08rem;
  letter-spacing: .02em;
  margin-top: 14px;
  box-shadow: 0 4px 14px rgba(212, 175, 55, .25);
}
.panic-add-cta:hover:not(:disabled) {
  box-shadow: 0 6px 18px rgba(212, 175, 55, .35);
}
.panic-add-cta-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .12);
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1;
}
.panic-add-cta-label {
  font-weight: 700;
}

/* Inline add-contact form — visible below the contacts list while
   the CTA is in flight. */
.panic-add-form {
  background: rgba(0, 0, 0, .25);
  border: 1px solid rgba(212, 175, 55, .22);
  border-radius: var(--radius);
  padding: 14px;
  margin: 14px 0 4px;
}
.panic-add-form input[type="text"],
.panic-add-form input[type="email"] {
  background: rgba(0, 0, 0, .3) !important;
  border: 1px solid rgba(255, 255, 255, .12) !important;
  color: var(--text) !important;
  border-radius: 8px !important;
  padding: 12px !important;
  font-size: .95rem !important;
}
.panic-add-form input:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}
.panic-add-form button {
  font-weight: 600 !important;
}
.panic-add-form button[type="button"]:nth-of-type(1) {
  background: var(--gold) !important;
  color: #000 !important;
}

/* Active SOS state — high-contrast urgent box. */
.panic-status-box.active {
  background: linear-gradient(180deg, rgba(204, 0, 0, .12), var(--surface) 70%);
  border: 1px solid rgba(204, 0, 0, .35);
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 14px;
}

.panic-btn-cancel {
  width: 100%;
  margin-top: 12px;
  padding: 14px 16px;
  background: #c00;
  color: #fff;
  border: none;
  border-radius: var(--radius);
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  min-height: 48px;
  transition: transform .08s ease, opacity .08s ease;
}
.panic-btn-cancel:active { transform: scale(.97); opacity: .92; }

/* ============================================
   ATTESTATION (v7.8.25) — OFAC + GDPR consent
   ============================================ */
.mini-attestation {
  background: rgba(212, 175, 55, 0.06);
  border: 1px solid rgba(212, 175, 55, 0.3);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 14px 0;
}
.mini-attest-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 8px 0;
  cursor: pointer;
  color: #ddd;
  font-size: .82rem;
  line-height: 1.45;
}
.mini-attest-check {
  appearance: auto;
  -webkit-appearance: auto;
  width: 20px;
  height: 20px;
  min-width: 20px;
  margin-top: 2px;
  accent-color: #d4af37;
  cursor: pointer;
  flex-shrink: 0;
}
.mini-attest-text { flex: 1; }
.mini-attest-text a {
  color: #d4af37;
  text-decoration: underline;
  font-weight: 600;
}
.mini-attest-text a:active { opacity: .8; }
.mini-attest-required {
  color: #e74c3c;
  font-weight: 700;
  margin-left: 2px;
}
.mini-attest-note {
  animation: mini-attest-shake .4s ease-in-out;
}
@keyframes mini-attest-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}
#btn-create-order[disabled],
#btn-create-order[aria-disabled="true"] {
  opacity: 0.5;
  filter: grayscale(0.4);
  cursor: not-allowed;
}
