/* ══════════════════════════════════════════════════════════════════════════
   glass.css — MarketsMill ™ Liquid-Glass design system (shared)

   The dashboard (localchain-dashboard-cards.html) grew a Liquid-Glass card
   language inside its own inline <style id="acct-redesign">, so every other
   member page kept layout.css / settings-common.css's flat opaque cards and
   the site read as two different products. This file is that same language,
   lifted out so any page can opt in with one <link>.

   HOW TO ADOPT ON A PAGE (both steps, in this order):
     1. <link rel="stylesheet" href="/glass.css?v=1">  AFTER layout.css
        (and after settings-common.css) so its rules win the cascade.
     2. <div class="glass-bg" aria-hidden="true"></div> as the first child of
        <body>, before appShellOpen(). Without it the translucent fills have
        nothing to refract and cards look muddy.

   RULES THIS FILE FOLLOWS (breaking them broke pages before):
   - It NEVER sets `display` on a card/row. Several pages ship cards as
     style="display:none" and reveal them with el.style.display = '', which
     falls back to the stylesheet — a `display:flex` here would silently
     change the revealed layout.
   - It NEVER adds `padding` to a container whose children already inset
     themselves (.section-card is padding-less by contract; .section-header,
     .info-row, .sp-item, .wpr-body all supply their own 24px).
   - Text inputs stay OPAQUE. Typed text over a blurred backdrop loses
     contrast; only radius/focus are unified.
   - It never repaints a surface whose colour ENCODES MEANING (a warning
     banner, a semantic chip, a destructive button).
   - Selectors are prefixed `body.has-sidebar` (specificity 0,2,1) so they
     beat settings-common.css's bare `.section-card` and each page's own
     inline <style>, which on several pages parses BEFORE these links.

   THE TOKEN TRAP THAT BIT THIS FILE ONCE — read before adding a rule.
   --glass-fill / --glass-fill-2 / --glass-stroke are CARD tokens: in light
   theme they are near-opaque WHITE (.74 / .60 / .85), which reads correctly
   only for a card floating over the tinted page canvas. Reuse them for
   anything that must read AGAINST a white card — an inset panel, a ghost
   button's border, a row hover — and you paint white-on-white and the
   element silently disappears. Use --glass-recess / --glass-ctl-bd /
   --glass-hover / --glass-divider below, which invert per theme.
   ══════════════════════════════════════════════════════════════════════════ */


/* ── 1. Tokens ───────────────────────────────────────────────────────────
   The card tokens are byte-identical to the dashboard's #acct-redesign
   block; keep them in sync. The four "inside a card" tokens are additions
   (the dashboard never needed them because it has no forms). */
:root {
  --gbg-base: var(--color-BasicBg);
  --gbg-1: rgba(56,189,248,.10);
  --gbg-2: rgba(168,85,247,.10);
  --gbg-3: rgba(46,189,133,.06);
  --glass-fill:        rgba(255,255,255,.045);
  --glass-fill-2:      rgba(255,255,255,.07);
  --glass-stroke:      rgba(255,255,255,.10);
  --glass-stroke-2:    rgba(255,255,255,.16);
  --glass-blur:        blur(18px) saturate(140%);
  --glass-inset:       inset 0 1px 0 rgba(255,255,255,.07);
  --glass-shadow:      0 1px 2px rgba(0,0,0,.30), 0 14px 34px -16px rgba(0,0,0,.55);
  --glass-shadow-lift: 0 2px 6px rgba(0,0,0,.34), 0 26px 52px -18px rgba(0,0,0,.6);
  --stat-ic-bg: linear-gradient(170deg, rgba(255,255,255,.16), rgba(255,255,255,.04));
  --stat-ic-fg: var(--color-PrimaryText);
  --chip-bg: rgba(255,255,255,.08);

  /* ── Inside-a-card tokens. These INVERT between themes (a light wash on
     dark, a dark wash on light) so they always read against the card. ── */
  --glass-divider: rgba(255,255,255,.10);   /* rules between rows/sections */
  --glass-recess:  rgba(255,255,255,.07);   /* inset panel / callout / thead */
  --glass-ctl-bd:  rgba(255,255,255,.18);   /* ghost button + control hairline */
  --glass-hover:   rgba(255,255,255,.06);   /* row + control hover wash */

  /* Shared geometry — one radius scale for the whole app. */
  --glass-r-card:  18px;   /* outer cards / panels */
  --glass-r-stat:  20px;   /* stat tiles (dashboard .acct-stat) */
  --glass-r-inner: 14px;   /* recessed surfaces inside a card */
  --glass-r-ctl:   12px;   /* inputs + buttons */
  --glass-r-chip:   7px;   /* status chips / badges */
}

[data-theme="light"] {
  /* Flat page canvas, no ambient tint — matches the reference card grey. */
  --gbg-base: #F8F8F8;
  --gbg-1: transparent;
  --gbg-2: transparent;
  --gbg-3: transparent;
  --glass-fill:        rgba(255,255,255,.74);
  --glass-fill-2:      rgba(255,255,255,.6);
  --glass-stroke:      rgba(255,255,255,.85);
  --glass-stroke-2:    rgba(255,255,255,.92);
  --glass-blur:        blur(20px) saturate(150%);
  --glass-inset:       inset 0 1px 0 rgba(255,255,255,.7);
  --glass-shadow:      0 1px 2px rgba(16,20,30,.04), 0 10px 30px -12px rgba(16,20,30,.16);
  --glass-shadow-lift: 0 2px 6px rgba(16,20,30,.06), 0 24px 46px -14px rgba(16,20,30,.26);
  --stat-ic-bg: linear-gradient(170deg, rgba(255,255,255,.9), rgba(236,238,241,.95));
  --stat-ic-fg: #15171E;
  --chip-bg: rgba(21,23,30,.06);

  --glass-divider: rgba(16,20,30,.10);
  --glass-recess:  rgba(16,20,30,.045);
  --glass-ctl-bd:  rgba(16,20,30,.16);
  --glass-hover:   rgba(16,20,30,.04);
}


/* ── 1b. Dark mapping for the legacy --lq-* palette ──────────────────────
   deposit / withdraw / voucher-request / withdraw-verify each carry a
   "Liquid Glass v2" palette (--lq-text, --lq-line, --lq-bg, --lq-green)
   hard-coded to LIGHT values, from when each painted its own permanent
   light canvas via body::before and ignored the theme entirely. Once
   glass.css makes their canvas and cards theme-adaptive, those frozen
   near-black text values land on a dark card and the page goes blank —
   voucher-request measured 1.03:1 on its own <h1>.

   This lives here, not in the four pages, so the mapping exists once.
   The selector must be `:root[data-theme="dark"]` (0,2,0) and NOT the bare
   attribute (0,1,0): each page declares --lq-* in its own `:root` (0,1,0)
   that parses AFTER this file, so an equal-specificity rule would lose on
   source order. */
:root[data-theme="dark"] {
  --lq-text:   var(--color-PrimaryText);
  --lq-text-2: var(--color-SecondaryText);
  --lq-text-3: var(--color-TertiaryText);
  --lq-line:   var(--glass-divider);
  --lq-bg:     var(--color-BasicBg);
  --lq-green:  var(--color-Buy);
  --lq-green-bg: rgba(46,189,133,.14);
  --lq-shadow-card: var(--glass-shadow);
  --lq-shadow-lift: var(--glass-shadow-lift);
}


/* ── 2. Ambient backdrop ─────────────────────────────────────────────────
   position:fixed is load-bearing: `body.has-sidebar` is display:flex
   (layout.css), so a static div here would become a phantom flex column. */
.glass-bg {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(48% 40% at 20% 6%,   var(--gbg-1), transparent 70%),
    radial-gradient(46% 42% at 86% 2%,   var(--gbg-2), transparent 72%),
    radial-gradient(52% 50% at 98% 100%, var(--gbg-3), transparent 70%),
    var(--gbg-base);
  animation: glassDrift 30s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes glassDrift { to { transform: scale(1.12) translate(-1.5%, -1%); } }
@media (prefers-reduced-motion: reduce) { .glass-bg { animation: none; } }
/* In light the three gradient stops are `transparent`, so the drift animates
   nothing — pure compositor cost. Only run it where it is visible. */
[data-theme="light"] .glass-bg { animation: none; will-change: auto; }

/* Keep the overscroll / rubber-band area on the same canvas as .glass-bg,
   otherwise the bounce reveals the old white body background. */
[data-theme="light"] body { background-color: var(--gbg-base); }


/* ── 3. Outer cards ──────────────────────────────────────────────────────
   Background / border / radius / shadow only — no display, no padding.

   NOTE ON backdrop-filter: a filtered element becomes the containing block
   for any position:fixed descendant, which mis-anchors JS-positioned menus
   that measure with getBoundingClientRect(). investment-plan.html hit this
   with its fixed .row-menu inside a .section-card. So `.section-card` — the
   one container that wraps arbitrary page content — gets the glass fill but
   NO blur. Over the light canvas a .74-alpha white wash reads the same; the
   blur only matters on the tighter, known-content cards below.

   DELIBERATELY NOT IN THIS GROUP:
   - .pending-banner — its amber fill/rim encodes "warning", not "surface".
   - .ds-summary     — it is the sole child of a .section-card on
                       leader-direct-sell, so glassing it nests a card in an
                       identical card and paints a double rim. */
body.has-sidebar .section-card {
  background: var(--glass-fill);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--glass-r-card);
  box-shadow: var(--glass-inset), var(--glass-shadow);
}

body.has-sidebar .inbox-card,
body.has-sidebar .form-card,
body.has-sidebar .method-card,
body.has-sidebar .wh-card,
body.has-sidebar .plan-card,
/* withdraw-verify's two panels: both hard-code rgba(255,255,255,.78), which
   in dark left a white card under light body text (its <h2> measured 1.35:1). */
body.has-sidebar .summary-card,
body.has-sidebar .expired-card {
  background: var(--glass-fill);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--glass-r-card);
  box-shadow: var(--glass-inset), var(--glass-shadow);
}

/* .profile-hero is a bare `display:flex` row in settings-common.css with no
   padding of its own, so it needs an inset to become a card at all. Its
   children (.hero-avatar, .hero-info) do not self-inset, so adding padding
   here is correct rather than double-padding. */
body.has-sidebar .profile-hero {
  background: var(--glass-fill);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--glass-r-card);
  box-shadow: var(--glass-inset), var(--glass-shadow);
  padding: 20px 24px;
}

/* Stat tiles get the dashboard's slightly rounder .acct-stat geometry. */
body.has-sidebar .sp-tile {
  background: var(--glass-fill);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--glass-r-stat);
  box-shadow: var(--glass-inset), var(--glass-shadow);
  transition: transform .16s ease, box-shadow .16s ease;
}

/* Lift on hover — only for cards that are actually interactive. */
body.has-sidebar .method-card:hover,
body.has-sidebar .sp-tile:hover,
body.has-sidebar .plan-card:hover {
  transform: translateY(-3px);
  /* The fill must brighten too. `body.has-sidebar .method-card` is (0,2,1)
     and outranks the page's own `.method-card:hover` (0,2,0), so without
     this the page's hover brighten is dead and only the lift survives. */
  background: var(--glass-fill-2);
  border-color: var(--glass-stroke-2);
  box-shadow: var(--glass-inset), var(--glass-shadow-lift);
}
/* "Coming soon" method rows are non-interactive: fainter fill, no lift. */
body.has-sidebar .method-card.coming-soon,
body.has-sidebar .method-card.coming-soon:hover {
  background: color-mix(in srgb, var(--glass-fill) 60%, transparent);
  transform: none;
  box-shadow: var(--glass-inset), 0 1px 2px rgba(16,20,30,.03);
  cursor: not-allowed;
}
/* .active is NOT a heavier state. The Unified Wallet card ships with
   class="method-card active" from when cards held a persistent selection;
   they are tap-to-go now, so `active` must match a resting card or that one
   row reads as permanently selected. */
body.has-sidebar .method-card.active {
  border-color: var(--glass-stroke);
  box-shadow: var(--glass-inset), var(--glass-shadow);
}


/* ── 4. Recessed surfaces inside a card ──────────────────────────────────
   A callout/panel sitting ON a card. Uses --glass-recess (a dark wash in
   light theme), NOT --glass-fill-2, or it vanishes on a white card.

   .pay-info-box / .form-summary are deposit+withdraw panels hard-coded to
   rgba(255,255,255,.55) — fine when those pages painted their own permanent
   light canvas, but once their card became theme-adaptive that fixed white
   panel put near-white text on near-white in dark. Mapping them here makes
   them follow the theme. */
body.has-sidebar .ldd-addr-box,
body.has-sidebar .ldd-recipient,
body.has-sidebar .ds-investor,
body.has-sidebar .crypto-summary,
body.has-sidebar .addr-card,
body.has-sidebar .balance-row,
body.has-sidebar .amount-input-wrap,
body.has-sidebar .pay-info-box,
body.has-sidebar .form-summary,
/* voucher-request panels + request rows, same hard-coded-white problem. */
body.has-sidebar .vr-recipient,
body.has-sidebar .vr-list-row {
  background: var(--glass-recess);
  border: 1px solid var(--glass-divider);
  border-radius: var(--glass-r-inner);
}
body.has-sidebar .vr-list-row:hover { background: var(--glass-hover); }
body.has-sidebar .addr-card.selected {
  border-color: var(--lc-accent);
}
/* The border shorthand above also resets border-color, which outranks the
   page's `.amount-input-wrap:focus-within` (0,2,0) from (0,2,1). Re-assert
   the focus ring so the Amount field still shows focus. */
body.has-sidebar .amount-input-wrap:focus-within {
  border-color: var(--lc-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lc-accent) 18%, transparent);
}


/* ── 5. Hairlines ────────────────────────────────────────────────────────
   Opaque --color-Line reads as a hard rule on a translucent card; --glass-
   stroke is a card RIM (near-white in light) and would vanish here. */
body.has-sidebar .section-header,
body.has-sidebar .modal-header {
  border-bottom-color: var(--glass-divider);
}
body.has-sidebar .modal-footer {
  border-top-color: var(--glass-divider);
}
body.has-sidebar .info-row,
body.has-sidebar .wpr-item,
body.has-sidebar .inbox-row,
body.has-sidebar .ds-row {
  border-bottom-color: var(--glass-divider);
}
body.has-sidebar .sp-card-item {
  border-top-color: var(--glass-divider);
}
body.has-sidebar .inbox-tabs,
body.has-sidebar .inbox-head,
body.has-sidebar .inbox-footer {
  border-color: var(--glass-divider);
}

/* Row hover. These rows are the primary click target on their pages, and
   the tint is their only affordance, so it must actually be visible. */
body.has-sidebar .inbox-row:hover,
body.has-sidebar .wpr-item:hover,
body.has-sidebar .sp-item:hover,
body.has-sidebar .ds-row:hover {
  background: var(--glass-hover);
}


/* ── 6. Tables ───────────────────────────────────────────────────────────
   Matches the dashboard's .acct-inv-table: tinted head, translucent rules. */
body.has-sidebar .inv-table,
body.has-sidebar .wh-table {
  background: var(--glass-fill);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--glass-r-card);
  box-shadow: var(--glass-inset), var(--glass-shadow);
  overflow: hidden;
}
body.has-sidebar .inv-table thead,
body.has-sidebar .wh-table thead { background: var(--glass-recess); }
body.has-sidebar .inv-table thead th,
body.has-sidebar .wh-table thead th { border-bottom: 1px solid var(--glass-divider); }
body.has-sidebar .inv-table td,
body.has-sidebar .wh-table td { border-top: 1px solid var(--glass-divider); }
body.has-sidebar .inv-table tr:hover td,
body.has-sidebar .wh-table tr:hover td { background: var(--glass-hover); }


/* ── 7. Icon squircles ───────────────────────────────────────────────────
   The dashboard's .acct-stat-ic shape, so leading icons read the same on
   every page instead of a flat --color-Vessel circle. */
body.has-sidebar .info-icon {
  border-radius: 15px 15px 6px 6px;
  background: var(--stat-ic-bg);
  border: 1px solid var(--glass-stroke-2);
  box-shadow: var(--glass-inset), 0 2px 5px rgba(16,20,30,.12);
  color: var(--stat-ic-fg);
}
body.has-sidebar .info-icon svg { color: var(--stat-ic-fg); }


/* ── 8. Chips and status badges ──────────────────────────────────────────
   Geometry only. Colour encodes state on these, so it is left to the page —
   .sp-chip-on/.sp-chip-off keep the semantic border that is the sole
   Active/Paused indicator on a split row. */
body.has-sidebar .sp-chip,
body.has-sidebar .wpr-badge,
body.has-sidebar .ds-row-status,
body.has-sidebar .method-badge,
body.has-sidebar .vr-id-plan,
body.has-sidebar .vr-list-code {
  border-radius: var(--glass-r-chip);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .6px;
  padding: 3px 9px;
}
/* Uppercase suits a short status word ("PENDING", "APPROVED"), which is all
   the dashboard's .acct-stat-chip ever holds. Deliberately NOT applied to
   .sp-chip (carries an amount — shouting a number reads as an error) or
   .method-badge (can hold a whole clause, which uppercasing turns into a
   three-line pill at 390px). */
body.has-sidebar .wpr-badge,
body.has-sidebar .ds-row-status {
  text-transform: uppercase;
}
/* Only the NEUTRAL chip loses its border for the shared fill. */
body.has-sidebar .sp-chip:not(.sp-chip-on):not(.sp-chip-off),
body.has-sidebar .vr-id-plan,
body.has-sidebar .vr-list-code {
  background: var(--chip-bg);
  border-color: transparent;
}


/* ── 9. Controls ─────────────────────────────────────────────────────────
   Inputs stay opaque for contrast; radius + focus ring are unified.
   .form-card's inputs on deposit/withdraw are hard-coded white, which put
   near-white text on near-white once the card went theme-adaptive — map
   them onto the theme's input colour. */
body.has-sidebar .form-input,
body.has-sidebar .sp-input,
body.has-sidebar .sp-pct-wrap,
body.has-sidebar .form-card select,
body.has-sidebar .form-card input[type="text"] {
  border-radius: var(--glass-r-ctl);
}
/* Every text field lands on the theme's opaque input colour. settings-common
   .form-input already uses --color-Input, so this is a no-op there; it exists
   because deposit / withdraw / voucher-request / withdraw-verify each
   hard-code a white rgba() fill, which put light dark-theme ink on a white
   field. Scoped to fields, so it cannot touch a card. */
body.has-sidebar .form-input,
body.has-sidebar .form-card select,
body.has-sidebar .form-card input[type="text"],
body.has-sidebar .form-card textarea,
body.has-sidebar .vr-search-input {
  background: var(--color-Input);
  border-color: var(--glass-ctl-bd);
  color: var(--color-PrimaryText);
}
body.has-sidebar .form-input:focus,
body.has-sidebar .sp-input:focus,
body.has-sidebar .form-card select:focus,
body.has-sidebar .form-card input[type="text"]:focus {
  border-color: var(--lc-accent);
  /* Derived from the accent so the ring follows the theme (--lc-accent is
     #0284C7 in light, #38bdf8 in dark) instead of freezing the light value. */
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lc-accent) 18%, transparent);
}

body.has-sidebar .btn-save,
body.has-sidebar .sp-btn,
body.has-sidebar .inbox-btn,
body.has-sidebar .inbox-page-btn,
body.has-sidebar .ldd-btn-ghost,
body.has-sidebar .ldd-btn-accent,
body.has-sidebar .btn-submit {
  border-radius: var(--glass-r-ctl);
}
/* Secondary/ghost buttons. --glass-ctl-bd, not --glass-stroke-2: the latter
   is .92-alpha white in light theme and left these buttons with no visible
   edge at all on a white card. */
body.has-sidebar .sp-btn,
body.has-sidebar .inbox-btn,
body.has-sidebar .inbox-page-btn,
body.has-sidebar .ldd-btn-ghost,
body.has-sidebar .vr-page-btn,
body.has-sidebar .btn-resend {
  background: transparent;
  border: 1px solid var(--glass-ctl-bd);
  box-shadow: none;
}
/* Hover must EXCLUDE the semantic variants. `body.has-sidebar .sp-btn:hover`
   is (0,3,1) and would otherwise outrank the .sp-btn-primary / -danger rules
   below, flipping the primary CTA's label to body ink (1.8:1 on accent) and
   stripping the destructive button's red on the very interaction that
   confirms it. */
body.has-sidebar .sp-btn:not(.sp-btn-primary):not(.sp-btn-danger):hover,
body.has-sidebar .inbox-btn:hover,
body.has-sidebar .inbox-page-btn:hover,
body.has-sidebar .ldd-btn-ghost:hover,
body.has-sidebar .vr-page-btn:hover,
body.has-sidebar .btn-resend:hover {
  background: var(--glass-hover);
  border-color: var(--lc-accent);
  color: var(--color-PrimaryText);
}
body.has-sidebar .sp-btn-primary {
  background: var(--lc-accent);
  border-color: var(--lc-accent);
  color: #fff;
}
body.has-sidebar .sp-btn-primary:hover { background: var(--lc-accent-hover); border-color: var(--lc-accent-hover); }
body.has-sidebar .sp-btn-danger {
  background: transparent;
  border-color: var(--color-Sell);
  color: var(--color-Sell);
}
body.has-sidebar .sp-btn-danger:hover {
  background: color-mix(in srgb, var(--color-Sell) 12%, transparent);
  border-color: var(--color-Sell);
  color: var(--color-Sell);
}

/* Inline feedback banners pick up the card radius (fill stays semantic). */
body.has-sidebar .form-error,
body.has-sidebar .form-success,
body.has-sidebar .ldd-notice {
  border-radius: var(--glass-r-inner);
}


/* ── 10. Section labels ──────────────────────────────────────────────────
   The dashboard labels a group with a small uppercase caption above the
   panel (.acct-section-title). Tracking/size only — NOT colour: in light
   theme --color-SecondaryText is #15181F (near-black by design, for body
   copy), which would turn these muted captions into headings. */
body.has-sidebar .method-section-title,
body.has-sidebar .deposit-section-title {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}


/* ── 11. Responsive ──────────────────────────────────────────────────────
   Cards tighten slightly on phones, matching the dashboard's 760px step. */
@media (max-width: 760px) {
  body.has-sidebar .section-card,
  body.has-sidebar .inbox-card,
  body.has-sidebar .form-card,
  body.has-sidebar .method-card,
  body.has-sidebar .wh-card,
  body.has-sidebar .profile-hero,
  body.has-sidebar .plan-card,
  body.has-sidebar .sp-tile {
    border-radius: var(--glass-r-inner);
  }
  /* Hover lift is a pointer affordance; on touch it leaves cards stuck in
     the lifted state after a tap. */
  body.has-sidebar .method-card:hover,
  body.has-sidebar .sp-tile:hover,
  body.has-sidebar .plan-card:hover {
    transform: none;
  }
}
