/* ============================================================================
   ARV Coin — Sterling
   ----------------------------------------------------------------------------
   Silver on black. The feel comes from space, weight and material rather than
   motion: brushed-metal gradients, hairline rules, generous whitespace, one
   serif for display and one sans for everything else.

   There is no 3D scene. Removing it took 1.3 MB off the critical path, which a
   phone on a slow connection feels immediately — and a rotating object behind a
   balance was never helping anyone read it.

   Colour discipline: silver is the brand, green and red mean market direction and
   nothing else. Nothing decorative is ever green or red, so when a number is
   coloured it means something.
   ============================================================================ */

:root {
  /* Black, warmed very slightly so it reads as ink rather than a dead screen */
  --k-0: #07070a;
  --k-1: #0c0c10;
  --k-2: #121218;
  --k-3: #1a1a22;
  --k-4: #24242e;
  --k-5: #2f2f3b;

  /* Silver */
  --s-0: #f6f7fa;
  --s-1: #dfe2e9;
  --s-2: #b9bec9;
  --s-3: #8f95a3;
  --s-4: #676d7c;
  --s-5: #454b58;

  /* Brushed metal. Used on the wordmark, primary buttons and hairline edges. */
  --brushed: linear-gradient(135deg, #ffffff 0%, #d8dbe3 22%, #9aa0ae 48%, #eef0f4 68%, #b0b6c2 100%);
  --brushed-dim: linear-gradient(135deg, #c8ccd6 0%, #8f95a3 45%, #dfe2e9 70%, #7c8290 100%);
  --edge: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.02) 40%, rgba(255,255,255,0));

  /* Glass */
  --glass: rgba(18, 18, 24, 0.66);
  --glass-2: rgba(26, 26, 34, 0.82);
  --line: rgba(255, 255, 255, 0.07);
  --line-2: rgba(255, 255, 255, 0.12);
  --line-3: rgba(255, 255, 255, 0.2);

  /* Text */
  --tx-0: #f4f5f8;
  --tx-1: #c3c8d2;
  --tx-2: #8b91a0;
  --tx-3: #5d636f;

  /* Market direction — reserved. Nothing decorative is ever green or red, so a
     coloured number always means something. */
  --up: #3ecf8e;
  --up-dim: rgba(62, 207, 142, 0.12);
  --down: #f0616d;
  --down-dim: rgba(240, 97, 109, 0.12);
  --flat: var(--tx-2);

  /* Asset identity. Each is the coin's own colour, desaturated enough to sit on
     a silver-and-black plate without turning the page into a rainbow — Bitcoin
     amber especially, which at full strength fights everything near it. */
  --btc: #f7931a;
  --btc-soft: #c9822a;
  --btc-dim: rgba(247, 147, 26, 0.13);
  --eth: #8f9ad4;
  --eth-dim: rgba(143, 154, 212, 0.13);
  --sol: #4fd6b0;
  --sol-dim: rgba(79, 214, 176, 0.13);

  /* Semantic */
  --warn: #e0b055;
  --warn-dim: rgba(224, 176, 85, 0.11);
  --info: #7fa8d8;
  --info-dim: rgba(127, 168, 216, 0.11);

  /* Type */
  --serif: 'Cormorant Garamond', 'Iowan Old Style', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, monospace;

  /* Rhythm */
  --r-xs: 6px; --r-sm: 10px; --r: 14px; --r-lg: 20px; --r-xl: 28px;
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 72px; --sp-9: 112px;

  --sh-1: 0 1px 2px rgba(0,0,0,.5);
  --sh-2: 0 10px 30px -8px rgba(0,0,0,.7);
  --sh-3: 0 30px 70px -20px rgba(0,0,0,.85);
  --glow: 0 0 40px -10px rgba(223, 226, 233, 0.22);

  --nav-h: 66px;
  --wrap: 1280px;
  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

/* ------------------------------------------------------------------ reset -- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--k-0);
  color: var(--tx-0);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  min-height: 100vh;
}

/* A single fixed wash instead of per-section gradients — one paint, no scroll
   cost, and it stops the page reading as flat black. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 80% 50% at 50% -12%, rgba(223,226,233,.075), transparent 68%),
    radial-gradient(ellipse 60% 45% at 100% 8%, rgba(150,158,175,.05), transparent 70%),
    radial-gradient(ellipse 70% 40% at 0% 92%, rgba(120,128,145,.04), transparent 70%);
}
.page, .nav, .foot { position: relative; z-index: 1; }

/* Tabular figures on every number that changes. Without this a live price
   shifts the layout sideways each time a digit changes width, which is the
   difference between a trading screen and a broken one. */
.num, .price, td.num, th.num, .mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1, 'zero' 1;
  letter-spacing: -.012em;
}

h1, h2, h3, h4, h5 { margin: 0 0 var(--sp-3); line-height: 1.14; }
h1, h2 { font-family: var(--serif); font-weight: 500; letter-spacing: -.015em; }
h1 { font-size: clamp(2.4rem, 6vw, 4.4rem); }
h2 { font-size: clamp(1.7rem, 3.4vw, 2.6rem); }
h3 { font-size: 1.15rem; font-weight: 600; letter-spacing: -.02em; }
h4 { font-size: .98rem; font-weight: 620; letter-spacing: -.01em; }
h5 {
  font-size: .72rem; font-weight: 650; text-transform: uppercase;
  letter-spacing: .1em; color: var(--tx-3);
}

p { margin: 0 0 var(--sp-4); color: var(--tx-1); }
a { color: var(--s-1); text-decoration: none; transition: color .15s var(--ease); }
a:hover { color: var(--s-0); }
::selection { background: rgba(223,226,233,.22); color: #fff; }
:focus-visible { outline: 1px solid var(--s-2); outline-offset: 3px; border-radius: 3px; }
hr { border: 0; border-top: 1px solid var(--line); margin: var(--sp-5) 0; }

/* The wordmark and any display text that should look milled rather than printed */
.metal {
  background: var(--brushed);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ---------------------------------------------------------------- helpers -- */

.up { color: var(--up); } .down { color: var(--down); } .flat { color: var(--flat); }
.muted { color: var(--tx-2); } .dim { color: var(--tx-3); }

/* The USD companion beside a ₹ figure. A muted secondary: smaller, dimmer and
   lighter so it reads as context and never competes with the rupee price. */
.price-usd {
  color: var(--tx-3);
  font-weight: 400;
  font-size: .82em;
  letter-spacing: -.01em;
  margin-left: .12em;
}
.small { font-size: .85rem; } .tiny { font-size: .76rem; }
.right { text-align: right; } .center { text-align: center; }
.nowrap { white-space: nowrap; } .hidden { display: none !important; }
.strong { font-weight: 620; } .serif { font-family: var(--serif); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--sp-5); }
.wrap-narrow { max-width: 760px; } .wrap-mid { max-width: 1020px; } .wrap-wide { max-width: 1560px; }

.stack > * + * { margin-top: var(--sp-4); }
.stack-lg > * + * { margin-top: var(--sp-5); }
.row { display: flex; align-items: center; gap: var(--sp-3); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.row-wrap { flex-wrap: wrap; }
.spacer { flex: 1; }

/* Tracks are minmax(0, 1fr), never a bare 1fr.
   `1fr` is shorthand for `minmax(auto, 1fr)`, and that `auto` floor is the
   min-content width of whatever is inside. One nowrap formula or one wide table
   in a cell therefore inflates the whole track past its container and the page
   scrolls sideways on a phone — with the overflow appearing on innocent siblings,
   which makes it maddening to trace. The explicit 0 floor removes the whole
   class of bug, and `min-width: 0` on the children does the same for flex and
   grid items that scroll internally. */
.grid { display: grid; gap: var(--sp-4); }
.grid > * { min-width: 0; }
.g-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g-auto { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

/* Page-level splits: a wide main column and a narrower rail.
   Declared here rather than as an inline style on each page, because an inline
   `grid-template-columns` beats every media query — which is exactly how a phone
   ends up scrolling sideways with no obvious cause. */
.split {
  display: grid; gap: var(--sp-4); align-items: start;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
}
.split-hero {
  display: grid; gap: var(--sp-7); align-items: center;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
}
.split > *, .split-hero > * { min-width: 0; }

/* A row of figures that sizes to its content on a wide screen. The column count
   follows the number of figures rather than being fixed at four — a hardcoded
   count leaves a visibly empty column the moment a figure is added or removed. */
.stat-strip { display: grid; grid-auto-flow: column; grid-auto-columns: auto; gap: var(--sp-5); }
.stat-strip > * { min-width: 0; }

@media (max-width: 980px) {
  .split, .split-hero { grid-template-columns: minmax(0, 1fr); }
  .split-hero { align-items: start; gap: var(--sp-5); }
}
@media (max-width: 560px) {
  /* Back to rows on a phone, two per line. grid-auto-flow has to be reset or the
     figures stay in one sideways-scrolling strip. */
  .stat-strip {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-4);
  }
}

/* ------------------------------------------------------------------- nav --- */

.nav {
  position: sticky; top: 0; z-index: 100; height: var(--nav-h);
  display: flex; align-items: center;
  background: rgba(7,7,10,.8);
  backdrop-filter: blur(22px) saturate(140%);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
  border-bottom: 1px solid var(--line);
}
.nav .wrap { display: flex; align-items: center; gap: var(--sp-5); }

.brand {
  display: flex; align-items: center; gap: var(--sp-3);
  font-family: var(--serif); font-size: 1.3rem; font-weight: 600;
  letter-spacing: .02em; flex-shrink: 0; color: var(--tx-0);
}
.brand:hover { color: var(--tx-0); }
.brand-mark {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 8px;
  background: var(--brushed);
  display: grid; place-items: center;
  font-family: var(--sans); font-size: .78rem; font-weight: 800;
  color: #0a0a0d;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 2px 10px -2px rgba(0,0,0,.7);
}

.nav-links { display: flex; gap: 2px; flex: 1; }
.nav-links a {
  padding: 7px 13px; border-radius: var(--r-sm);
  color: var(--tx-2); font-size: .88rem; font-weight: 500;
  transition: all .15s var(--ease); white-space: nowrap;
}
.nav-links a:hover { background: var(--k-3); color: var(--tx-0); }
.nav-links a.on { background: var(--k-3); color: var(--s-0); box-shadow: inset 0 0 0 1px var(--line-2); }

.nav-toggle {
  display: none; width: 38px; height: 38px; cursor: pointer;
  background: none; border: 1px solid var(--line-2); border-radius: var(--r-sm);
  color: var(--tx-1); font-size: 1.05rem;
}

.nav-ticker {
  display: flex; align-items: baseline; gap: var(--sp-2);
  padding: 5px 12px; border-radius: var(--r-sm);
  background: var(--k-2); border: 1px solid var(--line);
  font-size: .85rem;
}
/* An author `display` beats the UA stylesheet's rule for [hidden], so the ticker
   would sit there showing two em-dashes until a price arrived. It stays out of
   the layout until it has something to say. */
.nav-ticker[hidden] { display: none; }
.nav-ticker .k {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .09em; color: var(--tx-3);
}

/* Help sits inline in the desktop links row (so support is visible in the web
   view, not only in the footer) and also appears in the mobile "More" overflow
   once the links row collapses (see the 880px block). */
.nav-help { display: inline; }

/* ------------------------------------------------------ bottom tab bar ----- */

/* A fixed bottom navigation in the style of a trading app, shown on BOTH mobile
   and desktop (the top .nav stays as well). Icons inherit currentColor so they
   keep the silver-on-black palette, and the active tab lights up like the top
   nav's .on state. */
.tabbar {
  display: flex; position: fixed; z-index: 200;
  left: 0; right: 0; bottom: 0;
  background: rgba(7,7,10,.94);
  backdrop-filter: blur(22px) saturate(140%);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.tabbar .tab {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 8px 4px; min-height: 52px;
  color: var(--tx-3); text-align: center;
  transition: color .15s var(--ease);
}
.tabbar .tab:hover { color: var(--tx-1); }
.tabbar .tab.on { color: var(--s-0); }
.tabbar .tab.on .tab-ic { filter: drop-shadow(0 0 8px rgba(223,226,233,.28)); }
.tabbar .tab-ic { display: grid; place-items: center; height: 22px; }
.tabbar .tab-ic svg { display: block; }
.tabbar .tab-l {
  font-size: .66rem; font-weight: 600; letter-spacing: .02em;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Keep the fixed bar from covering the last of the page or the footer. */
body { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }

/* On desktop, centre the bar and cap its width so it reads as a control rather
   than a full-width mobile bar; the top nav remains the primary desktop nav. */
@media (min-width: 881px) {
  .tabbar {
    left: 50%; right: auto; transform: translateX(-50%);
    width: auto; max-width: 620px;
    border: 1px solid var(--line-2); border-bottom: 0;
    border-radius: 16px 16px 0 0;
    padding: 0 8px;
  }
  .tabbar .tab { flex: 0 0 auto; padding: 10px 20px; min-height: 56px; }
  .tabbar .tab-l { font-size: .72rem; }
}

/* On mobile the bottom bar is the primary navigation, so the hamburger becomes
   a secondary "More" overflow for Deposit/Withdraw/Refer/Profile/Help. Surface
   the Help entry that is inline on desktop. */
@media (max-width: 880px) {
  .nav-help { display: block; }
}

/* --------------------------------------------------------------- surfaces -- */

.card {
  position: relative;
  background: var(--glass);
  backdrop-filter: blur(18px) saturate(125%);
  -webkit-backdrop-filter: blur(18px) saturate(125%);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  box-shadow: var(--sh-2);
}
/* A lit top edge. This is what makes a flat rectangle read as a machined
   surface rather than a div. */
.card::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 1px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--edge);
  pointer-events: none;
}
.card-solid { background: var(--k-1); backdrop-filter: none; }
.card-tight { padding: var(--sp-4); }
.card-flush { padding: 0; overflow: hidden; }
.card-lift { transition: transform .45s var(--ease-out), border-color .3s var(--ease), box-shadow .45s var(--ease-out); }
.card-lift:hover { transform: translateY(-3px); border-color: var(--line-2); box-shadow: var(--sh-3); }

.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding-bottom: var(--sp-4); margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.card-head h3, .card-head h4 { margin: 0; }

/* ------------------------------------------------------------------ hero --- */

/* ============================================================================
   Hero — machined metal, in four layers
   ----------------------------------------------------------------------------
   No video, no images, no canvas. A background video costs a megabyte or two
   before a single word is readable, and on a phone it is the fastest way to make
   a site feel cheap. Everything below is a gradient, so the hero paints on the
   first frame and adds nothing to the page weight.

   Layer order matters:
     .hero-plate   deep charcoal, lit from above
     .hero-engine  fine concentric engine-turning, as on a milled plate
     .hero-sweep   a specular highlight drifting across, like light on steel
     .hero-grain   faint noise, so large flat areas do not read as plastic

   Only .hero-sweep animates, and only on transform and opacity, so it stays on
   the compositor and never triggers layout.
   ============================================================================ */

.hero { position: relative; overflow: hidden; padding: var(--sp-9) 0 var(--sp-8); }
.hero-media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }

/* The plate. Two overlapping radials give a surface with a light source rather
   than a flat fill, and the bottom fade hands off to the page background so the
   hero has no visible seam. */
.hero-plate {
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 90% 60% at 50% -20%, rgba(233,236,242,.15), transparent 62%),
    radial-gradient(ellipse 50% 40% at 82% 10%, rgba(176,184,200,.09), transparent 68%),
    linear-gradient(180deg, #14141b 0%, #0d0d12 46%, var(--k-0) 100%);
}

/* Engine-turning. Two sets of very fine lines at opposing angles, plus a slow
   concentric ring — the same idea as the guilloché on a watch dial or a share
   certificate. Kept under 4% opacity: it should be felt rather than seen, and
   anything stronger fights the type on top of it. */
.hero-engine {
  position: absolute; inset: 0;
  opacity: .55;
  background-image:
    repeating-linear-gradient(115deg,
      rgba(255,255,255,.030) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(65deg,
      rgba(255,255,255,.016) 0 1px, transparent 1px 7px),
    repeating-radial-gradient(circle at 50% -10%,
      rgba(255,255,255,.022) 0 1px, transparent 1px 22px);
  /* Fade out towards the bottom so the texture does not run under body copy. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.5) 55%, transparent 92%);
  mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.5) 55%, transparent 92%);
}

/* The specular sweep. A wide, soft, off-axis highlight that drifts across the
   plate. This is the one thing that makes the surface read as metal rather than
   paint — real metal has a moving hotspot. */
.hero-sweep {
  position: absolute; inset: -40%;
  background: conic-gradient(from 200deg at 50% 50%,
    transparent 0deg,
    rgba(255,255,255,.05) 40deg,
    rgba(214,217,224,.13) 78deg,
    rgba(255,255,255,.03) 120deg,
    transparent 180deg,
    rgba(150,158,175,.07) 260deg,
    transparent 340deg);
  filter: blur(70px);
  animation: sweep var(--sweep, 18s) linear infinite;
  will-change: transform;
  pointer-events: none;
}
@keyframes sweep { to { transform: rotate(360deg); } }

/* Grain. An inline SVG turbulence — about 200 bytes, no request, and it stops
   the large dark areas looking like flat vector fill. */
.hero-grain {
  position: absolute; inset: 0;
  opacity: .05;
  mix-blend-mode: overlay;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* A hairline at the very bottom of the hero, brightest in the middle — the
   machined edge of the plate. */
.hero::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; z-index: 1;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.14) 30%,
              rgba(255,255,255,.22) 50%, rgba(255,255,255,.14) 70%, transparent);
}

.hero-inner { position: relative; z-index: 2; }
.hero-eyebrow {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .22em;
  color: var(--tx-3); margin-bottom: var(--sp-4);
}
/* The eyebrow as a live status pill: a pulsing dot + label, so the page reads as
   a live market at first glance. */
.hero-eyebrow.live {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 13px; margin-bottom: var(--sp-5);
  border: 1px solid var(--line-2); border-radius: 999px;
  background: rgba(255, 255, 255, 0.03); color: var(--tx-2);
  letter-spacing: .16em;
}
.hero-eyebrow.live .live-dot { width: 7px; height: 7px; }
/* A soft aura behind the display headline, for depth against the plate. */
.hero h1::before {
  content: ''; position: absolute; z-index: -1;
  left: -4%; top: -10%; width: 74%; height: 120%;
  background: radial-gradient(56% 56% at 32% 42%, rgba(152, 164, 190, 0.16), transparent 70%);
  filter: blur(36px); pointer-events: none;
}

/* Display type with a light source travelling through it, so the wordmark reads
   as engraved rather than filled. Paused under reduced-motion below. */
.hero h1 { position: relative; }
.metal-lit {
  background: linear-gradient(100deg,
    #8f95a3 0%, #d8dbe3 18%, #ffffff 30%, #eef0f4 38%,
    #a8aeba 55%, #d8dbe3 76%, #7c8290 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: lit 9s ease-in-out infinite;
}
@keyframes lit {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

/* -------------------------------------------------------------- stat tile -- */

.stat { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.stat-k {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .1em;
  color: var(--tx-3); font-weight: 600;
}
.stat-v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.5rem; font-weight: 600; letter-spacing: -.03em; line-height: 1.1;
}
.stat-v-lg { font-size: 2.2rem; }
.stat-sub { font-size: .8rem; color: var(--tx-2); }

/* ------------------------------------------------------------------ price -- */

.price-hero { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.price-hero .v {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(2.2rem, 6.5vw, 3.8rem);
  font-weight: 620; letter-spacing: -.04em; line-height: 1;
}

/* A tick flash is the single most useful affordance on a live price — it tells
   you the number is alive. Kept brief so a fast tape does not strobe. */
@keyframes flash-up   { from { background: var(--up-dim); }   to { background: transparent; } }
@keyframes flash-down { from { background: var(--down-dim); } to { background: transparent; } }
.tick-up   { animation: flash-up .5s var(--ease) 1; border-radius: 4px; }
.tick-down { animation: flash-down .5s var(--ease) 1; border-radius: 4px; }

.chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 100px;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: .78rem; font-weight: 600;
  background: var(--k-3); color: var(--tx-1);
}
.chip.up { background: var(--up-dim); color: var(--up); }
.chip.down { background: var(--down-dim); color: var(--down); }
.chip.flat { background: var(--k-3); color: var(--flat); }

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: var(--r-xs);
  font-size: .68rem; font-weight: 640; text-transform: uppercase; letter-spacing: .07em;
  background: var(--k-3); color: var(--tx-2); border: 1px solid var(--line);
}
.badge.ok { background: var(--up-dim); color: var(--up); border-color: transparent; }
.badge.bad { background: var(--down-dim); color: var(--down); border-color: transparent; }
.badge.warn { background: var(--warn-dim); color: var(--warn); border-color: transparent; }
.badge.info { background: var(--info-dim); color: var(--info); border-color: transparent; }
.badge.metal { background: var(--brushed-dim); color: #0c0c10; border-color: transparent; font-weight: 700; }

.live-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: var(--up); box-shadow: 0 0 0 0 rgba(62,207,142,.55);
  animation: pulse 2.4s infinite;
}
.live-dot.stale { background: var(--warn); animation: none; }
.live-dot.off { background: var(--tx-3); animation: none; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(62,207,142,.5); }
  70% { box-shadow: 0 0 0 7px rgba(62,207,142,0); }
  100% { box-shadow: 0 0 0 0 rgba(62,207,142,0); }
}

/* --------------------------------------------------------------- buttons --- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 11px 20px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: var(--k-3); color: var(--tx-0);
  font-family: var(--sans); font-size: .9rem; font-weight: 600;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: all .16s var(--ease);
}
.btn:hover { background: var(--k-4); color: var(--tx-0); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:disabled, .btn[aria-disabled='true'] { opacity: .38; cursor: not-allowed; transform: none; }

.btn-primary {
  background: var(--brushed); color: #0a0a0d; font-weight: 700;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.65), 0 4px 18px -6px rgba(223,226,233,.35);
}
.btn-primary:hover {
  color: #0a0a0d; filter: brightness(1.06);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.75), 0 8px 26px -8px rgba(223,226,233,.5);
}
.btn-ghost { background: transparent; border-color: var(--line-2); color: var(--tx-1); }
.btn-ghost:hover { background: var(--k-2); border-color: var(--line-3); color: var(--tx-0); }
.btn-buy { background: var(--up-dim); color: var(--up); border-color: rgba(62,207,142,.3); }
.btn-buy:hover { background: rgba(62,207,142,.2); color: var(--up); }
.btn-sell { background: var(--down-dim); color: var(--down); border-color: rgba(240,97,109,.3); }
.btn-sell:hover { background: rgba(240,97,109,.2); color: var(--down); }
.btn-danger { background: var(--down-dim); color: var(--down); border-color: rgba(240,97,109,.28); }
.btn-sm { padding: 7px 13px; font-size: .82rem; }
.btn-lg { padding: 15px 30px; font-size: .98rem; }
.btn-block { width: 100%; }

/* ---------------------------------------------------------------- inputs --- */

.field { display: flex; flex-direction: column; gap: 7px; }
.field label { font-size: .8rem; font-weight: 620; color: var(--tx-1); }
.field .hint { font-size: .76rem; color: var(--tx-3); line-height: 1.45; }
.field .err { font-size: .78rem; color: var(--down); }

input, select, textarea {
  width: 100%; padding: 11px 13px;
  background: var(--k-1); border: 1px solid var(--line);
  border-radius: var(--r-sm); color: var(--tx-0);
  font-family: var(--sans); font-size: .95rem;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--s-3);
  box-shadow: 0 0 0 3px rgba(223,226,233,.09);
}
input::placeholder { color: var(--tx-3); }
input[aria-invalid='true'] { border-color: var(--down); }
input:disabled { opacity: .5; cursor: not-allowed; }

input.num-input {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 1.3rem; font-weight: 600; letter-spacing: -.02em;
}
.amount-input { position: relative; }
.amount-input .cur {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  color: var(--tx-2); font-family: var(--mono); font-size: 1.15rem; pointer-events: none;
}
.amount-input input { padding-left: 34px; }
.quick { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.check {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3); cursor: pointer;
  background: var(--k-1); border: 1px solid var(--line); border-radius: var(--r-sm);
  font-size: .86rem; color: var(--tx-1);
  transition: border-color .15s var(--ease);
}
.check:hover { border-color: var(--line-2); }
.check input { width: auto; flex-shrink: 0; margin-top: 3px; accent-color: var(--s-2); }

/* OTP entry — six characters, spaced so they read as separate digits */
.otp-input {
  font-family: var(--mono); font-size: 1.7rem; font-weight: 600;
  letter-spacing: .5em; text-align: center; padding: 14px 13px 14px 26px;
}

/* ------------------------------------------------------------------ table -- */

/* `min-width: 0` is what actually makes this scroll instead of stretching its
   parent. Without it the wrapper's min-content is the table's, and a nine-column
   tax table drags the whole page wider than the phone. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; min-width: 0; }
table.data { width: 100%; border-collapse: collapse; font-size: .87rem; }
table.data th {
  position: sticky; top: 0; z-index: 1;
  text-align: left; padding: 10px var(--sp-4);
  font-size: .68rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--tx-3); font-weight: 650; white-space: nowrap;
  background: var(--k-1); border-bottom: 1px solid var(--line);
}
table.data td {
  padding: 11px var(--sp-4); color: var(--tx-1);
  border-bottom: 1px solid rgba(255,255,255,.03);
}
table.data tbody tr { transition: background .12s var(--ease); }
table.data tbody tr:hover { background: rgba(255,255,255,.018); }
table.data td.num, table.data th.num { text-align: right; }
table.data tfoot td {
  font-weight: 650; color: var(--tx-0); background: var(--k-1);
  border-top: 1px solid var(--line-2); border-bottom: none;
}

/* --------------------------------------------------------------- ledger ---- */

/* The itemised fee and tax list. Its job is to make every deduction impossible
   to miss, so nothing here is collapsed, greyed out or behind a tooltip. */
.ledger-list { display: flex; flex-direction: column; gap: 1px; }
.ledger-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-4); padding: 10px var(--sp-4);
  background: var(--k-1); font-size: .89rem; flex-wrap: wrap;
}
.ledger-row:first-child { border-radius: var(--r-sm) var(--r-sm) 0 0; }
.ledger-row:last-child { border-radius: 0 0 var(--r-sm) var(--r-sm); }
.ledger-row .l { color: var(--tx-1); }
.ledger-row .a {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-weight: 600; white-space: nowrap; margin-left: auto;
}
.ledger-row .note {
  flex-basis: 100%; font-size: .75rem; color: var(--tx-3);
  margin-top: 3px; line-height: 1.45;
}
.ledger-row.k-gross { background: var(--k-2); }
.ledger-row.k-gross .a { font-size: 1.02rem; }
.ledger-row.k-charge .a, .ledger-row.k-tds .a { color: var(--warn); }
.ledger-row.k-net { background: var(--up-dim); border-left: 2px solid var(--up); }
.ledger-row.k-net .l { color: var(--tx-0); font-weight: 640; }
.ledger-row.k-net .a { color: var(--up); font-size: 1.1rem; font-weight: 700; }
.ledger-row.k-pnl .a { font-weight: 700; }
.ledger-row.k-liability { background: rgba(224,176,85,.05); }
.ledger-row.k-liability .a { color: var(--warn); }
.ledger-row.k-liability-total { background: var(--warn-dim); border-left: 2px solid var(--warn); }
.ledger-row.k-liability-total .l { color: var(--tx-0); font-weight: 640; }
.ledger-row.k-liability-total .a { color: var(--warn); font-size: 1.02rem; font-weight: 700; }
.ledger-row.k-warning { background: var(--down-dim); border-left: 2px solid var(--down); }
.ledger-row.k-warning .note { color: var(--tx-1); }
.ledger-divider { height: var(--sp-4); }

/* ------------------------------------------------------------------ notes -- */

.note-box {
  padding: var(--sp-4); border-radius: var(--r-sm);
  border-left: 2px solid var(--info); background: var(--info-dim);
  font-size: .86rem; color: var(--tx-1);
}
.note-box.warn { border-color: var(--warn); background: var(--warn-dim); }
.note-box.bad { border-color: var(--down); background: var(--down-dim); }
.note-box.ok { border-color: var(--up); background: var(--up-dim); }
.note-box strong { color: var(--tx-0); }
.note-box p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- toasts --- */

.toast-host {
  position: fixed; bottom: var(--sp-5); right: var(--sp-5); z-index: 900;
  display: flex; flex-direction: column; gap: var(--sp-2);
  max-width: min(400px, calc(100vw - 32px));
}
.toast {
  display: flex; gap: var(--sp-3); padding: var(--sp-4);
  background: var(--glass-2);
  backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
  border: 1px solid var(--line-2); border-left: 2px solid var(--info);
  border-radius: var(--r-sm); box-shadow: var(--sh-3);
  font-size: .87rem; animation: toast-in .3s var(--ease-out);
}
.toast.ok { border-left-color: var(--up); }
.toast.bad { border-left-color: var(--down); }
.toast.warn { border-left-color: var(--warn); }
.toast.out { animation: toast-out .24s var(--ease) forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateX(22px); } }
@keyframes toast-out { to { opacity: 0; transform: translateX(22px); } }

/* --------------------------------------------------------------- loading --- */

.skeleton {
  background: linear-gradient(90deg, var(--k-2) 25%, var(--k-3) 50%, var(--k-2) 75%);
  background-size: 200% 100%; animation: shimmer 1.4s infinite;
  border-radius: var(--r-sm); color: transparent !important;
}
@keyframes shimmer { to { background-position: -200% 0; } }

.spinner {
  width: 15px; height: 15px; flex-shrink: 0;
  border: 2px solid var(--line-2); border-top-color: var(--s-2);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.empty { padding: var(--sp-7) var(--sp-4); text-align: center; color: var(--tx-3); }
.empty .icon { font-size: 1.8rem; opacity: .35; margin-bottom: var(--sp-3); }

/* A section whose last refresh failed keeps the rows it already had — they are
   still the best information available — and says so by fading rather than by
   going blank. Deliberately subtle: the numbers must stay readable, because an
   operator acting on slightly old data is far better off than one staring at an
   error where the table used to be. */
[data-stale] { opacity: .62; transition: opacity .2s var(--ease); }

/* ------------------------------------------------------------------- tabs -- */

.tabs {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--k-1); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.tab {
  padding: 6px 12px; border: none; background: none; cursor: pointer;
  color: var(--tx-2); font-family: var(--mono); font-size: .8rem; font-weight: 600;
  border-radius: var(--r-xs); transition: all .15s var(--ease);
}
.tab:hover { color: var(--tx-0); }
.tab.on { background: var(--k-3); color: var(--s-0); box-shadow: inset 0 0 0 1px var(--line-2); }

/* Buy/sell segmented control */
.side-toggle { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; padding: 3px;
  background: var(--k-1); border: 1px solid var(--line); border-radius: var(--r-sm); }
.side-toggle button {
  padding: 10px; border: 0; background: none; cursor: pointer;
  color: var(--tx-2); font-weight: 650; font-size: .9rem;
  border-radius: var(--r-xs); transition: all .15s var(--ease);
}
.side-toggle button.on[data-side='buy'] { background: var(--up-dim); color: var(--up); }
.side-toggle button.on[data-side='sell'] { background: var(--down-dim); color: var(--down); }

/* ------------------------------------------------------------------ chart -- */

.chart-shell {
  position: relative; background: var(--k-1);
  border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden;
}
.chart-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap; padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.chart-canvas { width: 100%; height: 430px; position: relative; }
.chart-canvas.tall { height: 560px; }
.chart-canvas.short { height: 250px; }
.chart-legend {
  display: flex; gap: var(--sp-4); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--line); font-size: .78rem;
}
.legend-item { display: flex; align-items: center; gap: 6px; color: var(--tx-2); }
.legend-swatch { width: 10px; height: 2px; border-radius: 2px; flex-shrink: 0; }

.ohlc-readout {
  display: flex; gap: var(--sp-4); flex-wrap: wrap;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: .78rem; color: var(--tx-2);
}
.ohlc-readout b { color: var(--tx-0); font-weight: 600; }

.chart-overlay-msg {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(12,12,16,.72); backdrop-filter: blur(3px);
  font-size: .88rem; color: var(--tx-2); text-align: center;
  padding: var(--sp-5); z-index: 3;
}

/* ------------------------------------------------------------------- tape -- */

/* Recent trades. Monospaced and dense — a tape is meant to be glanced at, not
   read, and any padding here costs a row of information. */
.tape { display: flex; flex-direction: column; max-height: 320px; overflow-y: auto; }
.tape-row {
  display: grid; grid-template-columns: 1fr auto auto;
  gap: var(--sp-3); padding: 5px var(--sp-4);
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: .78rem;
  border-bottom: 1px solid rgba(255,255,255,.025);
}
.tape-row.new { animation: tape-in .4s var(--ease-out); }
@keyframes tape-in { from { opacity: 0; transform: translateY(-6px); background: rgba(255,255,255,.05); } }
.tape-row .t { color: var(--tx-3); }
.tape-head {
  display: grid; grid-template-columns: 1fr auto auto; gap: var(--sp-3);
  padding: 8px var(--sp-4);
  font-size: .66rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--tx-3); border-bottom: 1px solid var(--line);
}

/* ------------------------------------------------------------------ depth -- */

/* There is no bid/ask ladder because there is no spread — every fill settles at
   the index price. What matters instead is how much wants in and out, so depth
   is drawn as two opposing bars. */
.depth { display: flex; flex-direction: column; gap: var(--sp-3); }
.depth-bar { height: 8px; border-radius: 4px; background: var(--k-3); overflow: hidden; }
.depth-bar span { display: block; height: 100%; }
.depth-bar.buy span { background: linear-gradient(90deg, var(--up), rgba(62,207,142,.4)); }
.depth-bar.sell span { background: linear-gradient(90deg, var(--down), rgba(240,97,109,.4)); }

/* -------------------------------------------------------------------- QR --- */

.qr-panel {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-4);
  padding: var(--sp-5); background: var(--k-1);
  border: 1px solid var(--line); border-radius: var(--r-lg);
}
.qr-frame { padding: var(--sp-4); background: #fff; border-radius: var(--r); line-height: 0; box-shadow: var(--sh-2); }
.qr-frame svg, .qr-frame canvas, .qr-frame img { display: block; width: 216px; height: 216px; }
.qr-unconfigured {
  width: 216px; height: 216px; display: grid; place-items: center; text-align: center;
  padding: var(--sp-4); background: var(--k-2);
  border: 1px dashed var(--line-2); border-radius: var(--r);
  color: var(--tx-3); font-size: .78rem; line-height: 1.5;
}
.qr-vpa {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 9px 14px; background: var(--k-2);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  font-family: var(--mono); font-size: .92rem; color: var(--tx-0);
}

/* ------------------------------------------------------------------ steps -- */

.steps { display: flex; gap: 0; margin-bottom: var(--sp-5); }
.step {
  flex: 1; display: flex; flex-direction: column; gap: 5px;
  padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--k-4);
  color: var(--tx-3); font-size: .8rem;
}
.step.on { border-top-color: var(--s-2); color: var(--s-0); }
.step.done { border-top-color: var(--up); color: var(--up); }
.step .n { font-family: var(--mono); font-size: .68rem; font-weight: 700; letter-spacing: .06em; }
.step .t { font-weight: 620; }

/* ------------------------------------------------------------ order cards -- */

/* Live orders and trades on the wallet page. Cards rather than table rows because
   each one is a thing that needs a decision, and the whole card is the tap target
   through to the order — a small "view" link in a row is a worse phone control. */
.order-cards {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  padding: 0 var(--sp-4) var(--sp-4);
}
.order-cards > .empty { grid-column: 1 / -1; }

.order-card {
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--sp-4);
  background: var(--k-1); border: 1px solid var(--line);
  border-radius: var(--r-sm); text-decoration: none; color: inherit;
  transition: border-color .14s var(--ease), background .14s var(--ease),
              transform .14s var(--ease);
}
.order-card:hover {
  border-color: var(--s-3); background: var(--k-2); transform: translateY(-1px);
}
.order-card-top { display: flex; align-items: center; gap: 6px; }
.order-card-figure {
  font-family: var(--mono); font-size: 1.15rem; font-weight: 680; color: var(--tx-0);
  letter-spacing: -.01em;
}
/* The instruction. Deliberately the most readable line after the amount: it is
   what the holder has to do, and burying it would defeat the point of the card. */
.order-card-next {
  font-size: .84rem; color: var(--tx-1); line-height: 1.45; margin-top: 2px;
}

@media (max-width: 560px) {
  .order-cards { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------------ tiers -- */

.tier-row {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--k-1);
}
.tier-row.earned { border-color: var(--line-3); background: var(--k-2); }
.tier-row.earned .tier-name { background: var(--brushed); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tier-name { font-family: var(--serif); font-size: 1.05rem; font-weight: 600; min-width: 92px; }
.progress { height: 4px; border-radius: 2px; background: var(--k-3); overflow: hidden; }
.progress span { display: block; height: 100%; background: var(--brushed-dim); }

/* ------------------------------------------------------------------ legal -- */

/* Two columns on a desktop, one on a phone. The contents list stops being
   sticky when it stacks — a sticky block above the content it indexes just eats
   the screen. */
.legal-layout {
  display: grid; grid-template-columns: 200px minmax(0, 1fr);
  gap: var(--sp-6); align-items: start;
}
.legal-layout > * { min-width: 0; }

.toc { position: sticky; top: 80px; }
.toc ul { list-style: none; margin: 0; padding: 0; line-height: 2; }
.toc a { color: var(--tx-2); text-decoration: none; display: block;
  padding-left: 9px; border-left: 1px solid transparent; transition: all .15s var(--ease); }
.toc a:hover { color: var(--tx-0); }
.toc a.on { color: var(--s-0); border-left-color: var(--s-2); }

@media (max-width: 860px) {
  .legal-layout { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
  .toc { position: static; }
  .toc ul { columns: 2; column-gap: var(--sp-4); line-height: 1.9; }
}

/* ----------------------------------------------------------------- footer -- */

.foot {
  margin-top: var(--sp-8); padding: var(--sp-6) 0 var(--sp-5);
  border-top: 1px solid var(--line); background: rgba(7,7,10,.6);
  font-size: .84rem; color: var(--tx-2);
}
.foot-grid { display: grid; gap: var(--sp-5); grid-template-columns: 1.6fr repeat(4, 1fr); margin-bottom: var(--sp-5); }
.foot ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.foot a { color: var(--tx-2); }
.foot a:hover { color: var(--s-1); }
.foot-bottom {
  padding-top: var(--sp-4); border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap;
  font-size: .78rem; color: var(--tx-3);
}
.risk-line { font-size: .78rem; color: var(--tx-3); line-height: 1.55; max-width: 72ch; }
.feed-status {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: .74rem; color: var(--tx-3);
}

/* ------------------------------------------------------------- responsive -- */

@media (max-width: 1080px) {
  .g-4 { grid-template-columns: repeat(2, 1fr); }
  .foot-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 880px) {
  .nav-links {
    position: fixed; inset: var(--nav-h) 0 auto 0; display: none;
    flex-direction: column; gap: 2px; padding: var(--sp-4);
    background: rgba(7,7,10,.97);
    backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
    border-bottom: 1px solid var(--line);
  }
  .nav-links.open { display: flex; }
  .nav-links a { padding: 12px 14px; }
  .nav-toggle { display: grid; place-items: center; }
  .nav .wrap { gap: var(--sp-3); }
  .nav-ticker { display: none; }
}

@media (max-width: 660px) {
  :root { --sp-5: 16px; --sp-6: 24px; --sp-7: 32px; --sp-8: 48px; --sp-9: 64px; }
  body { font-size: 14.5px; }
  .wrap { padding: 0 var(--sp-4); }
  .g-2, .g-3, .g-4, .g-auto { grid-template-columns: minmax(0, 1fr); }
  .wallet-split { grid-template-columns: minmax(0, 1fr); }
  .wallet-split .divider { height: 1px; }

  /* Segmented controls hold more labels than a 390px screen has room for, so they
     scroll rather than push the page sideways. */
  .tabs, .side-toggle { max-width: 100%; overflow-x: auto; }
  .tabs { scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }

  /* Flex items default to min-width: auto, which is min-content — so a row
     holding a scrollable tab strip or a long label still refuses to shrink and
     pushes past the screen edge. Same fix as the grid tracks, applied where the
     layout is flex. */
  .row > *, .row-between > *, .chart-bar > *, .card-head > * { min-width: 0; }
  .card { padding: var(--sp-4); border-radius: var(--r); }
  .stat-v { font-size: 1.3rem; }
  .stat-v-lg { font-size: 1.85rem; }
  .chart-canvas { height: 310px; }
  .chart-canvas.tall { height: 370px; }
  .foot-grid { grid-template-columns: 1fr; }
  .toast-host { left: var(--sp-4); right: var(--sp-4); bottom: var(--sp-4); max-width: none; }
  .steps { flex-direction: column; gap: 2px; }
  .step { border-top: none; border-left: 1px solid var(--k-4); }
  .step.on { border-left-color: var(--s-2); }
  .step.done { border-left-color: var(--up); }

  /* A 70px blur animating behind the fold is the most expensive thing on the
     page and the least noticed. The plate, engine-turning and grain all stay —
     those are static and free — so the hero still looks machined, it just stops
     moving. */
  .hero-sweep { animation: none; filter: blur(46px); opacity: .7; }
  .metal-lit { animation: none; background-position: 30% 50%; }
  .hero-engine { opacity: .4; }
}

/* --------------------------------------------------------- accessibility -- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  /* Motion off, material intact. Someone who has asked their system to stop
     animations still deserves the finished surface, not a bare rectangle. */
  .hero-sweep { animation: none; }
  .metal-lit { animation: none; background-position: 30% 50%; }
  .card-lift:hover { transform: none; }
  .live-dot { animation: none; }
  .tape-row.new { animation: none; }
}

@media print {
  body::before, .nav, .tabbar, .foot, .toast-host, .btn, .hero-media { display: none !important; }
  body { background: #fff; color: #000; }
  .card { border: 1px solid #ccc; background: #fff; box-shadow: none; }
  * { color: #000 !important; }

  /* Anything still waiting to be revealed would print as a blank block, so the
     animation's starting state is overridden rather than relied upon. */
  [data-reveal] { opacity: 1 !important; transform: none !important; filter: none !important; }

  /* The tax statement is the page people actually print, and it is mostly
     tables. Without borders and a repeated header a multi-page table is
     unreadable on paper. */
  table.data { border: 1px solid #999; }
  table.data thead { display: table-header-group; }
  table.data th, table.data td { border-bottom: 1px solid #ccc; background: #fff !important; }
  table.data tr, .card, .ledger-row { break-inside: avoid; }
  .ledger-row { border-bottom: 1px solid #eee; }
  .badge, .chip { border: 1px solid #999 !important; background: #fff !important; }
  .progress { border: 1px solid #999; }
  .progress span { background: #999 !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .7em; }
}


/* ============================================================================
   Scroll reveal
   ----------------------------------------------------------------------------
   Content arrives as you reach it, one element at a time. The grammar is
   deliberately narrow — a long ease-out, a short rise, a little defocus
   resolving — because that reads as considered, whereas varied directions and
   bounces read as a template.

   Three rules keep it feeling expensive rather than busy:

     Slow out, never in. 900ms on a cubic-bezier(.16,1,.3,1) decelerates almost
     to a stop, which is what makes movement feel weighted instead of springy.

     One direction only. Everything rises. Nothing slides in from the side, and
     nothing scales up from nothing.

     Reveal once. Elements do not re-animate when scrolled back past — an element
     that keeps replaying is a distraction, not a delight.

   Only opacity, transform and filter are animated, so this stays on the
   compositor and never triggers layout.
   ============================================================================ */

[data-reveal] {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  filter: blur(5px);
  transition:
    opacity .9s var(--ease-out),
    transform .9s var(--ease-out),
    filter .9s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
[data-reveal].shown {
  opacity: 1;
  transform: none;
  filter: blur(0);
}
/* Released after the transition so hundreds of revealed nodes are not all
   holding a compositor layer for the rest of the session. */
[data-reveal].settled { will-change: auto; transition: none; }

/* Quieter variant for dense areas — table rows, tape lines, list items — where
   a 20px rise on every row would look like the page is loading badly. */
[data-reveal='soft'] { transform: translate3d(0, 10px, 0); filter: blur(3px); }

/* For a figure that should feel like it lands. Slightly further, slightly
   slower. Used on the price and the headline numbers. */
[data-reveal='weighty'] {
  transform: translate3d(0, 30px, 0);
  filter: blur(8px);
  transition-duration: 1.15s;
}

/* Stagger. A parent sets data-reveal-group and each child gets its index, so a
   row of cards resolves left to right rather than all at once. */
[data-reveal-group] > [data-reveal] {
  --reveal-delay: calc(var(--i, 0) * 80ms);
}
[data-reveal-group='tight'] > [data-reveal] {
  --reveal-delay: calc(var(--i, 0) * 45ms);
}

/* A hairline that draws itself. Section rules and card underlines use this —
   it is the single most "engraved" gesture available for the cost of a scaleX. */
.rule {
  height: 1px; border: 0; margin: var(--sp-5) 0;
  background: linear-gradient(90deg, rgba(255,255,255,.16), rgba(255,255,255,.05) 55%, transparent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1.2s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.rule.shown { transform: scaleX(1); }

/* A silver underline that grows beneath a heading as it arrives. */
.underline-draw { position: relative; display: inline-block; padding-bottom: 10px; }
.underline-draw::after {
  content: ''; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--brushed-dim);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 1.1s var(--ease-out) .18s;
}
.underline-draw.shown::after { transform: scaleX(1); }

/* Section spacing. Generous, and the reason the reveals have room to read as
   separate moments rather than one wave. */
.section { padding: var(--sp-8) 0; position: relative; }
.section-lg { padding: var(--sp-9) 0; }
.section-head { max-width: 68ch; margin-bottom: var(--sp-6); }
.section-num {
  font-family: var(--mono); font-size: .7rem; letter-spacing: .18em;
  color: var(--tx-3); margin-bottom: var(--sp-3);
}

/* A number that counts up to its value on reveal. The digits are tabular already,
   so the width does not jump while it runs. */
.count-up { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  /* Everything visible immediately, no movement. Not "animated faster" —
     genuinely off, because the point is the absence of motion. */
  [data-reveal] {
    opacity: 1 !important; transform: none !important; filter: none !important;
    transition: none !important;
  }
  .rule { transform: scaleX(1) !important; transition: none !important; }
  .underline-draw::after { transform: scaleX(1) !important; transition: none !important; }
}


/* ============================================================================
   Crypto furniture
   ----------------------------------------------------------------------------
   The market motifs: candles, asset rows, sparklines, the tracking identity.
   Asset colour is used as a thin accent — a rail, a swatch, a glyph — never as a
   fill, so the page stays silver and black with the coins as highlights.
   ============================================================================ */

/* -------------------------------------------------------------- asset rows -- */

.asset-row {
  display: grid;
  grid-template-columns: 34px 1fr auto auto;
  align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid rgba(255,255,255,.035);
  transition: background .15s var(--ease);
}
.asset-row:last-child { border-bottom: 0; }
.asset-row:hover { background: rgba(255,255,255,.02); }

/* The coin glyph. A ring in the asset's colour with its ticker inside — reads as
   a coin without needing an image request per asset. */
.coin {
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--mono); font-size: .6rem; font-weight: 700; letter-spacing: -.02em;
  border: 1px solid currentColor;
  position: relative;
}
.coin::after {
  content: ''; position: absolute; inset: -1px; border-radius: 50%;
  background: currentColor; opacity: .09;
}
.coin span { position: relative; z-index: 1; color: var(--tx-0); }
.coin.btc { color: var(--btc); }
.coin.eth { color: var(--eth); }
.coin.sol { color: var(--sol); }
.coin.arv { color: var(--s-1); }
.coin.arv::after { opacity: .14; }

.asset-name { min-width: 0; }
.asset-name .t { font-weight: 620; font-size: .92rem; }
.asset-name .s { font-size: .72rem; color: var(--tx-3); text-transform: uppercase; letter-spacing: .06em; }

/* A left rail in the asset colour, so a row is identifiable at a glance. */
.asset-row.railed { border-left: 2px solid transparent; padding-left: calc(var(--sp-4) - 2px); }
.asset-row.railed.btc { border-left-color: var(--btc); }
.asset-row.railed.eth { border-left-color: var(--eth); }
.asset-row.railed.sol { border-left-color: var(--sol); }
.asset-row.railed.arv { border-left-color: var(--s-2); }

/* ---------------------------------------------------------------- candles --- */

/* A decorative candlestick run, drawn in CSS. Used in the hero and as section
   punctuation — it says "market" without loading a chart library above the fold. */
.candles {
  display: flex; align-items: flex-end; gap: 3px; height: 64px;
}
/* Full height so the wick spans the range and the body is a percentage of it.
   Without an explicit height the flex item collapses to its content — and since
   the body starts at zero height for the reveal, the whole run would be
   invisible. */
.candle {
  position: relative; width: 6px; height: 100%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
/* The wick */
.candle::before {
  content: ''; position: absolute; width: 1px; top: 0; bottom: 0;
  background: currentColor; opacity: .45;
}
/* The body */
.candle::after {
  content: ''; position: relative; width: 100%;
  height: var(--body, 50%);
  background: currentColor;
  border-radius: 1px;
  opacity: .85;
}
.candle.up { color: var(--up); }
.candle.down { color: var(--down); }
.candle.neutral { color: var(--s-4); }

/* Hero candles: taller, dimmer, and they grow on reveal so the hero has one
   piece of market motion that is not the price itself. */
.candles-hero { height: 96px; gap: 5px; opacity: .55; }
.candles-hero .candle { width: 7px; }
.candles-hero .candle::after {
  height: 0;
  transition: height 1.1s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.candles-hero.shown .candle::after { height: var(--body, 50%); }

/* -------------------------------------------------------------- sparkline -- */

.spark { width: 84px; height: 26px; display: block; flex-shrink: 0; }
.spark path { fill: none; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.spark.up path { stroke: var(--up); }
.spark.down path { stroke: var(--down); }
.spark .fill { stroke: none; opacity: .12; }
.spark.up .fill { fill: var(--up); }
.spark.down .fill { fill: var(--down); }

/* --------------------------------------------------------------- identity -- */

/* ------------------------------------------------------------- formula ----- */

.formula {
  font-family: var(--mono); font-size: 1rem; line-height: 2.1;
  white-space: nowrap; overflow-x: auto;
  padding: var(--sp-4) var(--sp-5);
  background: var(--k-1); border: 1px solid var(--line); border-radius: var(--r);
  color: var(--tx-1);
}
.formula .arv { color: var(--s-0); }
.formula .btc { color: var(--btc); }
.formula .op { color: var(--tx-3); }

/* ------------------------------------------------------------- wallet card - */

/* Two balances, one card. Rupees and ARV are different kinds of thing and the
   split is load-bearing — a user needs to see instantly which one they can spend
   and which one is exposure. */
/* One holding, full width — what wallet-split became once the rupee side of the
   wallet stopped existing. Kept as its own class rather than a modifier so the
   two-column layout is still available if a second balance ever returns. */
.wallet-single { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; }

.wallet-split {
  display: grid; grid-template-columns: 1fr 1px 1fr; gap: var(--sp-5);
  align-items: stretch;
}
.wallet-split .divider { background: var(--line); }
.wallet-locked {
  font-size: .74rem; color: var(--warn);
  display: inline-flex; align-items: center; gap: 4px;
}

@media (max-width: 660px) {
  .wallet-split { grid-template-columns: 1fr; }
  .wallet-split .divider { height: 1px; }
  .asset-row { grid-template-columns: 30px 1fr auto; }
  .asset-row .spark { display: none; }
  .candles-hero { height: 68px; gap: 4px; }
}


/* ---------------------------------------------------------------- chevrons -- */

/* Drawn with borders rather than typed as an arrow character.
   Google Fonts serves the latin subset by default, which has no U+2192, so a
   literal → falls back — and on a device with no font carrying it, that is a
   tofu box. A border chevron always renders, at any size, in any font. */
.arrow::after {
  content: '';
  display: inline-block;
  width: .42em; height: .42em;
  margin-left: .5em;
  border-right: 1.5px solid currentColor;
  border-top: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-.06em);
  transition: transform .2s var(--ease);
}
.arrow:hover::after { transform: rotate(45deg) translate(.1em, -.06em); }

/* Downward, for a scroll cue. */
.arrow-down::after { transform: rotate(135deg) translateX(-.06em); }


/* ============================================================================
   SIGN IN WITH GOOGLE
   ============================================================================

   Google renders its own button inside an iframe and will not accept our CSS, by
   design — it has to look like Google's button or it is not trustworthy. So the
   work here is confining it: giving it a slot the right width, and a divider
   above it that belongs to this palette rather than to Google's.

   `filled_black` is the theme chosen in auth.js. It is the only one that does not
   sit on this page like a white sticker. */

/* A general hint, not only the one inside a .field. The Google block needs a
   caption that lives outside a form field. */
.hint {
  font-size: .76rem;
  color: var(--tx-3);
  line-height: 1.45;
}
.hint.warn { color: var(--warn); }

/* "or", with a hairline through it. */
.or-rule {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: var(--sp-5) 0 var(--sp-4);
  color: var(--tx-3);
  font-size: .7rem;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.or-rule::before,
.or-rule::after {
  content: '';
  flex: 1;
  height: 1px;
  /* Fades out towards the word so the line does not appear to collide with it. */
  background: linear-gradient(90deg, transparent, var(--line-2), transparent);
}

/* The slot Google draws into.
   Centred, and given a minimum height so the card does not jump when the button
   finally appears — the script is third-party and can take a moment. */
.google-slot {
  display: flex;
  justify-content: center;
  min-height: 44px;
}
/* Google sets an inline width on its own iframe; this keeps it from overflowing a
   narrow card on a phone. */
.google-slot > div,
.google-slot iframe {
  max-width: 100% !important;
}


/* ------------------------------------------------------ PWA install banner --

   A visible, dismissible "Install app" prompt shown when the browser reports the
   app is installable (beforeinstallprompt). Fixed near the bottom; on mobile it
   sits above the fixed bottom tab bar so the two never overlap. */
.pwa-install {
  position: fixed;
  z-index: 60;
  left: 50%;
  transform: translateX(-50%);
  /* Sit above the bottom tab bar (now shown on desktop too, ~56px tall). */
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  width: min(440px, calc(100vw - 24px));
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: #14141b;
  border: 1px solid var(--line-2);
  border-radius: 16px;
  box-shadow: 0 14px 44px rgba(0, 0, 0, 0.55);
}
.pwa-install[hidden] { display: none; }
.pwa-install .pwa-ic .brand-mark { width: 34px; height: 34px; }
.pwa-install .pwa-tx { display: flex; flex-direction: column; flex: 1; line-height: 1.28; }
.pwa-install .pwa-tx b { font-size: 13px; color: var(--tx-1); }
.pwa-install .pwa-tx span { font-size: 11px; color: var(--tx-2); }
.pwa-install .pwa-x {
  background: none;
  border: 0;
  color: var(--tx-2);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.pwa-install .pwa-x:hover { color: var(--tx-1); }

/* Clear the mobile bottom tab bar (shown at <=880px). */
@media (max-width: 880px) {
  .pwa-install { bottom: calc(80px + env(safe-area-inset-bottom, 0px)); }
}


/* ---------------------------------------------------------- support assistant --

   A floating chat that answers ARV questions. Sits bottom-right, above the
   bottom tab bar; the panel opens over the page. Silver-on-black to match. */
.asst-fab {
  position: fixed; z-index: 210;
  right: 18px; bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(180deg, #eef0f4, #b9bec9);
  color: #14141b; border: 0;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.asst-fab:hover { transform: translateY(-2px); box-shadow: 0 14px 38px rgba(0, 0, 0, 0.6); }
.asst-fab.on { transform: scale(.96); }

.asst-panel {
  position: fixed; z-index: 210;
  right: 18px; bottom: calc(146px + env(safe-area-inset-bottom, 0px));
  width: min(360px, calc(100vw - 24px));
  max-height: min(70vh, 560px);
  display: flex; flex-direction: column;
  background: #101017; border: 1px solid var(--line-2);
  border-radius: 16px; overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}
.asst-panel[hidden] { display: none; }
.asst-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.02);
}
.asst-title { display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--tx-1); font-size: .92rem; }
.asst-x { background: none; border: 0; color: var(--tx-2); font-size: 20px; line-height: 1; cursor: pointer; }
.asst-x:hover { color: var(--tx-1); }

.asst-log { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.asst-msg {
  max-width: 85%; padding: 9px 12px; border-radius: 13px;
  font-size: .86rem; line-height: 1.45; white-space: normal; word-wrap: break-word;
}
.asst-msg.bot { align-self: flex-start; background: #1b1b24; color: var(--tx-1); border-bottom-left-radius: 4px; }
.asst-msg.me { align-self: flex-end; background: #2a2a36; color: #fff; border-bottom-right-radius: 4px; }
.asst-msg a { color: #dfe2e9; text-decoration: underline; }
.asst-typing { color: var(--tx-3); letter-spacing: .15em; }

.asst-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.asst-chip {
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--line-2);
  color: var(--tx-2); border-radius: 999px; padding: 6px 11px;
  font-size: .78rem; cursor: pointer; transition: color .15s var(--ease), border-color .15s var(--ease);
}
.asst-chip:hover { color: var(--tx-1); border-color: var(--line-3); }

.asst-input { display: flex; gap: 8px; padding: 10px; border-top: 1px solid var(--line); }
.asst-input input {
  flex: 1; min-width: 0; background: #07070a; border: 1px solid var(--line-2);
  border-radius: 10px; color: var(--tx-1); padding: 9px 11px; font-size: .86rem;
}
.asst-input input:focus { outline: none; border-color: var(--line-3); }

/* On phones the panel is roomier and clears the tab bar. */
@media (max-width: 560px) {
  .asst-panel {
    right: 12px; left: 12px; width: auto;
    bottom: calc(140px + env(safe-area-inset-bottom, 0px));
    max-height: 64vh;
  }
}


/* =========================================================== orders page ==
   The P2P order/trade surface (orders.html). Everything here is either a
   colour-coded card or a live countdown; the rest of the page reuses .card,
   .badge, .note-box, .btn and the type helpers.

   BUY is green and SELL is red, using the reserved direction tokens (--up /
   --down) already used by .btn-buy / .btn-sell — nothing decorative on this site
   is ever green or red, so the colour alone tells you the side from across the
   room. The rail on the left edge does the work; the tint is kept very low so a
   stack of cards still reads as silver-on-black. */

.ocard {
  position: relative;
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-3);
  border-radius: var(--r);
  padding: var(--sp-4);
  background: rgba(255, 255, 255, .022);
}
.ocard + .ocard { margin-top: var(--sp-3); }
.ocard-buy  { border-left-color: var(--up);   background: var(--up-dim); }
.ocard-sell { border-left-color: var(--down); background: var(--down-dim); }

/* The side word itself, so BUY/SELL is legible even to someone who cannot tell
   the two rails apart. */
.ocard-side {
  font-size: .72rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--tx-1);
}
.ocard-buy  .ocard-side { color: var(--up); }
.ocard-sell .ocard-side { color: var(--down); }

/* A live countdown. Tabular figures so the text does not jitter every second as
   the digits change width. Amber under 25% of the window, red under 10% or once
   the deadline has passed — the same escalation the copy uses. */
.cd { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--tx-1); }
.cd.cd-warn { color: var(--warn); }
.cd.cd-late { color: var(--down); font-weight: 700; }

/* One copyable payment field: label, value, Copy. A buyer on a phone should
   never have to retype a UPI ID or an amount. */
.copy-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); padding: 8px 0; border-bottom: 1px solid var(--line);
}
.copy-row:last-child { border-bottom: 0; }
.copy-row .k { font-size: .74rem; color: var(--tx-2); flex: 0 0 auto; }
.copy-row .v {
  font-family: var(--mono); font-size: .82rem; color: var(--tx-0);
  text-align: right; overflow-wrap: anywhere; min-width: 0;
}

/* The "needs your action" strip, and the compact history rows. */
.ostrip-item { padding: 8px 0; border-bottom: 1px solid var(--line); }
.ostrip-item:last-child { border-bottom: 0; }
.orow {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); padding: 9px 0; border-bottom: 1px solid var(--line);
}
.orow:last-child { border-bottom: 0; }

/* The unread indicator on the Orders nav item and tab. Amber, not red: it is a
   "you have something to do", not a failure. */
.nav-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--warn); vertical-align: middle;
}
.tabbar .tab-ic { position: relative; }
.tab-dot {
  position: absolute; top: -1px; right: -3px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--warn); box-shadow: 0 0 0 2px rgba(7, 7, 10, .94);
}


/* ============================================================================
   Admin — tabbed operations panel
   ----------------------------------------------------------------------------
   The operator page groups its sections behind tabs instead of one long scroll,
   so every control has a fixed home and is one click away. The bar sticks just
   below the site nav (which is sticky at top:0, height --nav-h) so it stays in
   reach as a table is scrolled.
   ============================================================================ */

.admin-tabs {
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
  padding: var(--sp-2);
  margin-bottom: var(--sp-5);
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh-2);
  backdrop-filter: blur(18px) saturate(125%);
  -webkit-backdrop-filter: blur(18px) saturate(125%);
  position: sticky; top: calc(var(--nav-h) + var(--sp-2)); z-index: 40;
}

.admin-tab {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--tx-2);
  font: inherit; font-size: .9rem; font-weight: 600; white-space: nowrap;
  transition: background .15s var(--ease), color .15s var(--ease), border-color .15s var(--ease);
}
.admin-tab:hover { color: var(--tx-0); background: var(--k-3); }
.admin-tab.is-active {
  color: var(--k-0); background: var(--brushed-dim);
  border-color: transparent; box-shadow: var(--sh-1);
}

.admin-tab-count {
  min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
  font-size: .7rem; font-weight: 700; line-height: 1;
  background: var(--warn-dim); color: var(--warn);
}
.admin-tab.is-active .admin-tab-count { background: rgba(0, 0, 0, .18); color: var(--k-0); }
/* An author-level display beats the UA rule behind the `hidden` attribute, so
   without this the count sits there reading "0" when there is nothing waiting. */
.admin-tab-count[hidden] { display: none; }

.admin-panel { animation: adminPanelIn .2s var(--ease-out); }
.admin-panel[hidden] { display: none; }
@keyframes adminPanelIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

/* Settings, grouped into labelled blocks rather than one flat wall of fields. */
.settings-group-title {
  margin: 0 0 var(--sp-3);
  font-size: .82rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--tx-2);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--line);
}

@media (max-width: 640px) {
  /* On a phone the bar scrolls sideways instead of stacking into a tall block,
     and drops its sticky offset so it does not eat the viewport. */
  .admin-tabs {
    position: static;
    flex-wrap: nowrap; overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .admin-tab { flex: 0 0 auto; }
}



/* ============================================================================
   The ARV coin — struck metal, in transforms
   ----------------------------------------------------------------------------
   Geometry and material for js/coin3d.js. Deliberately not a 3D library: the
   hero scene this replaces in spirit cost ~1.3 MB before a word was readable.
   This is a few dozen divs on the compositor, so it costs nothing measurable.

   Size comes in from JS as --coin-d (diameter) and --coin-t (thickness), so the
   large hero coin and the smaller wallet one share every rule below.

   What makes it read as metal is layering rather than geometry: a brushed base,
   curvature shading, an engraved ring and dentils, a mark embossed with one
   consistent light direction, and a specular band that travels across the face
   as it turns. Metal is defined by how it moves light, so the highlight moves.

   Every animation here touches only transform and opacity, so the whole thing
   stays on the GPU and cannot trigger layout.
   ============================================================================ */

.coin3d-stage {
  --coin-d: 124px;
  --coin-t: 17px;
  --coin-px: 0deg;
  --coin-py: 0deg;
  --coin-scale: 1;
  position: relative;
  display: grid; place-items: center;
  /* The vanishing point sits above centre, which is where a held object is
     actually viewed from. Dead centre looks like a diagram. */
  perspective: 1100px;
  perspective-origin: 50% 40%;
}

.c-parallax {
  position: relative;
  transform-style: preserve-3d;
  transform: scale(var(--coin-scale)) rotateY(var(--coin-px)) rotateX(var(--coin-py));
  transition: transform .55s var(--ease-out);
}

.c-float  { position: relative; transform-style: preserve-3d; animation: cFloat 7s ease-in-out infinite; will-change: transform; }
.c-wobble { position: relative; transform-style: preserve-3d; animation: cWobble 13s ease-in-out infinite; }

@keyframes cFloat  { 0%, 100% { transform: translateY(-10px); } 50% { transform: translateY(10px); } }
@keyframes cWobble { 0%, 100% { transform: rotateX(-19deg); }   50% { transform: rotateX(-6deg); } }

/* The body. Linear, because a coin turning at an eased rate looks broken. */
.c-coin {
  position: relative;
  width: var(--coin-d); height: var(--coin-d);
  transform-style: preserve-3d;
  animation: cSpin 17s linear infinite;
  will-change: transform;
}
@keyframes cSpin { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } }

/* ------------------------------------------------------------------ faces -- */

.c-face {
  position: absolute; inset: 0;
  border-radius: 50%;
  overflow: hidden;
  backface-visibility: hidden;
  /* A horizon-split reflection — the one thing that separates polished metal from
     grey plastic. Metal is a mirror, so it does not have a colour of its own: it
     reflects a bright sky above and a dark floor below, meeting at a hard line
     across the middle. That hard transition is what the eye reads as "chrome".
     Everything else here (brushing, dome, engraving) sits on top of it. */
  background:
    radial-gradient(circle at 26% 18%, rgba(255,255,255,.95) 0%, rgba(255,255,255,0) 38%),
    linear-gradient(177deg,
      #fdfeff  0%,     /* sky, blown out at the top    */
      #e4e9f2 22%,
      #b6becd 44%,
      #8d95a6 49.4%,
      #3f4552 50.6%,   /* horizon — the hard cut       */
      #5b6272 58%,
      #878fa0 74%,
      #c2c9d6 92%,     /* light bouncing off the floor */
      #9aa1b1 100%);
  /* Struck relief: a lit top edge and a hairline all round. Deliberately no broad
     inset glow — a large soft inner shadow inflates the disc into a pillow, and a
     struck coin is flat with a sharp edge, not a cushion. */
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,.75),
    inset 0 -1px 1px rgba(10,10,16,.45),
    inset 0 0 0 1px rgba(255,255,255,.22);
}
.c-front { transform: translateZ(calc(var(--coin-t) / 2)); }
.c-back  { transform: rotateY(180deg) translateZ(calc(var(--coin-t) / 2)); }

/* Anisotropic streaking — the horizontal smear polished metal gets from a broad
   light source. Deliberately NOT a repeating-conic: at these radii the fine
   angular bands beat against the pixel grid and the moiré reads as dirt on the
   coin rather than as brushing. A few soft linear bands do the same job cleanly. */
.c-brush {
  position: absolute; inset: 0; border-radius: 50%;
  background: linear-gradient(180deg,
    rgba(255,255,255,0)   0%,
    rgba(255,255,255,.16) 12%,
    rgba(255,255,255,0)   19%,
    rgba(255,255,255,.1)  31%,
    rgba(255,255,255,0)   38%,
    rgba(10,10,16,.1)     62%,
    rgba(255,255,255,0)   69%,
    rgba(255,255,255,.07) 84%,
    rgba(255,255,255,0)   92%);
  opacity: .7;
}

/* Curvature, plus the bright bevel that catches light right at the perimeter —
   a real coin is slightly domed and its outer edge is the brightest thing on it. */
.c-dome {
  position: absolute; inset: 0; border-radius: 50%;
  background:
    /* Only a whisper of centre lift, and vignetting kept tight to the last few
       percent so it darkens the edge without swelling the middle. */
    radial-gradient(circle at 50% 50%, rgba(255,255,255,.08) 0%, rgba(255,255,255,0) 46%),
    radial-gradient(circle at 50% 50%, rgba(10,10,16,0) 82%, rgba(10,10,16,.42) 100%),
    /* The bright bevel right at the perimeter — on a real coin the outer edge is
       the brightest thing on the face. */
    radial-gradient(circle at 50% 50%, rgba(255,255,255,0) 93%, rgba(255,255,255,.6) 97.5%, rgba(255,255,255,.1) 100%);
}

/* The raised inner ring. Two hairlines, lit above and shadowed below, which is
   all a bevel is. */
.c-ring {
  position: absolute; inset: 8.5%;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.5);
  box-shadow:
    inset 0 1px 2px rgba(14,14,20,.4),
    0 1px 1px rgba(255,255,255,.3);
}

/* Dentils — the ring of fine teeth just inside the edge. A repeating conic gives
   the teeth; the mask trims them to a narrow band. */
.c-dentils {
  position: absolute; inset: 2.5%;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg,
    rgba(16,16,24,.5) 0deg 1.6deg,
    rgba(255,255,255,.42) 1.6deg 3.2deg);
  -webkit-mask: radial-gradient(circle, transparent 0 86%, #000 87% 96%, transparent 97%);
          mask: radial-gradient(circle, transparent 0 86%, #000 87% 96%, transparent 97%);
  opacity: .75;
}

/* The mark, embossed: light from the top-left, shadow to the bottom-right, the
   same direction every other layer is lit from. */
.c-mark {
  position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-56%);
  text-align: center;
  font-family: var(--serif);
  font-size: calc(var(--coin-d) * .27);
  font-weight: 600; letter-spacing: .05em;
  /* The letters carry their own reflection, INVERTED relative to the field: a
     raised face is tilted the other way, so it picks up the dark floor where the
     flat field shows sky and vice versa. That inversion is what makes lettering
     look struck into metal instead of printed on it — and unlike a flat colour it
     stays legible across the horizon line running behind it. */
  background: linear-gradient(180deg,
    #7d8494 0%, #2b303b 44%, #1c2029 49%,
    #eef1f7 52%, #b9c0cd 74%, #8b92a2 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  /* drop-shadow rather than text-shadow: the fill is transparent, so a text
     shadow would draw through it. */
  filter:
    drop-shadow(0 1px 0 rgba(255,255,255,.45))
    drop-shadow(0 -1px 0 rgba(10,10,16,.5));
}
.c-mark-lg { font-size: calc(var(--coin-d) * .34); }

/* Held well inside the disc — at 15% the descenders clipped on the curve. */
.c-sub {
  position: absolute; left: 12%; right: 12%; bottom: 21%;
  text-align: center;
  font-size: calc(var(--coin-d) * .05);
  letter-spacing: .16em; font-weight: 700;
  color: rgba(236,240,248,.78);
  text-shadow: 0 -1px 0 rgba(10,10,16,.55), 0 1px 0 rgba(255,255,255,.18);
}

/* The specular band. It sweeps across the face on the same period as the spin,
   so the hotspot travels while the coin turns instead of being painted on it —
   that single detail is most of what separates metal from a grey disc. */
.c-spec {
  position: absolute; top: -50%; bottom: -50%; left: -60%;
  width: 55%;
  background: linear-gradient(90deg,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.5) 45%,
    rgba(255,255,255,.72) 52%,
    rgba(255,255,255,0) 100%);
  filter: blur(6px);
  transform: rotate(14deg);
  animation: cSpec 17s linear infinite;
  pointer-events: none;
}
@keyframes cSpec {
  0%          { transform: translateX(0) rotate(14deg); opacity: 0; }
  8%          { opacity: .5; }
  42%         { opacity: .95; }
  70%         { opacity: .35; }
  100%        { transform: translateX(320%) rotate(14deg); opacity: 0; }
}

/* ---------------------------------------------------- chamfer and the rim -- */

/* The bevel between face and rim, so the silhouette is not a hard 90 degrees.
   Toned to sit within a shade of the face it meets: as a lighter ring it read as a
   second border floating inside the edge, which muddied the whole perimeter. It
   should be felt as a softening of the corner, not seen as a ring. */
.c-chamfer {
  position: absolute; inset: 0.8%;
  border-radius: 50%;
  background: linear-gradient(178deg,
    #c8ced9 0%, #9ba1b0 44%, #3a3f4b 50%, #565c6a 58%, #6f7584 100%);
  backface-visibility: hidden;
}
.c-chamfer-f { transform: translateZ(calc(var(--coin-t) / 2 - 1px)); }
.c-chamfer-b { transform: rotateY(180deg) translateZ(calc(var(--coin-t) / 2 - 1px)); }

/* The rim: quads laid around the circumference by coin3d.js into a closed wall.
   The vertical gradient is the cylinder's own shading — lit along the top, falling
   into shadow underneath, with its own horizon to match the faces.

   The milling is deliberately a WHISPER of alternation. An obvious light/dark
   alternation at this segment count stops looking like a reeded edge and starts
   looking like a barcode wrapped round a disc, which was the single biggest tell
   that this was drawn rather than machined. Form comes from the gradient; the
   alternation only breaks it up. */
.c-rim { position: absolute; inset: 0; transform-style: preserve-3d; }
.c-rim i {
  position: absolute; top: 50%; left: 50%;
  width: var(--coin-t);
  margin-left: calc(var(--coin-t) / -2);
  background: linear-gradient(180deg,
    #dee2ea 0%, #b6bcc9 14%, #888e9e 42%,
    #3b4653 50%, #525966 57%, #4a5060 78%, #383d49 100%);
}
.c-rim i:nth-child(even) { filter: brightness(1.04); }

/* ----------------------------------------------------- orbits and lighting -- */

.c-rings { position: absolute; inset: 0; transform-style: preserve-3d; pointer-events: none; }
.c-ring-orbit {
  position: absolute; border-radius: 50%;
  border: 1px solid var(--line-3);
  transform-style: preserve-3d;
}
/* Held very faint on purpose. As crisp wireframe circles — worse, a dashed one —
   these stopped reading as orbits and started reading as a CSS demo, which cheapened
   the object they surround. They are ambience: the bead is what shows the motion. */
.c-ring-orbit.o1 { inset: -21%; opacity: .5;  animation: cOrbit1 11s linear infinite; }
.c-ring-orbit.o2 { inset: -37%; opacity: .28; animation: cOrbit2 18s linear infinite; }
@keyframes cOrbit1 { from { transform: rotateX(75deg) rotateZ(0deg); }   to { transform: rotateX(75deg) rotateZ(360deg); } }
@keyframes cOrbit2 { from { transform: rotateX(63deg) rotateZ(360deg); } to { transform: rotateX(63deg) rotateZ(0deg); } }

.c-bead {
  position: absolute; top: -3px; left: 50%;
  width: 6px; height: 6px; margin-left: -3px;
  border-radius: 50%;
  background: var(--s-0);
  box-shadow: 0 0 12px 3px rgba(223, 226, 233, .45);
}

/* Ambient light behind the coin, so it sits in the page rather than on it. */
.c-glow {
  position: absolute; top: 50%; left: 50%;
  width: calc(var(--coin-d) * 2.1); height: calc(var(--coin-d) * 2.1);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(216,220,230,.16) 0%, rgba(216,220,230,.06) 42%, rgba(216,220,230,0) 70%);
  pointer-events: none;
}

/* Two shadows: a tight contact patch and a wide soft one. A single shadow reads
   as a sticker; the pair is what puts the object above a surface. */
.c-shadow {
  position: absolute; left: 50%; bottom: calc(var(--coin-d) * -.18);
  width: calc(var(--coin-d) * .92); height: calc(var(--coin-d) * .12);
  margin-left: calc(var(--coin-d) * -.46);
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.62), rgba(0,0,0,0) 72%);
  filter: blur(5px);
  animation: cShadow 7s ease-in-out infinite;
}
.c-shadow-soft {
  width: calc(var(--coin-d) * 1.5); height: calc(var(--coin-d) * .2);
  margin-left: calc(var(--coin-d) * -.75);
  background: radial-gradient(ellipse at center, rgba(0,0,0,.34), rgba(0,0,0,0) 70%);
  filter: blur(14px);
  animation: cShadowSoft 7s ease-in-out infinite;
}
@keyframes cShadow     { 0%, 100% { transform: scale(.86); opacity: .4; }  50% { transform: scale(1.1); opacity: .72; } }
@keyframes cShadowSoft { 0%, 100% { transform: scale(.9);  opacity: .3; }  50% { transform: scale(1.06); opacity: .5; } }

/* ------------------------------------------------------------- placements -- */

/* Wallet: the coin sits beside the balances. */
.wallet-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 250px;
  gap: var(--sp-5);
  align-items: center;
}
.wallet-hero .coin3d-stage { height: 230px; }

/* Home hero: the showpiece, above the live-price card. */
.hero-coin { height: 300px; margin-bottom: var(--sp-4); }

@media (max-width: 1100px) {
  .wallet-hero { grid-template-columns: minmax(0, 1fr) 210px; }
  .wallet-hero .coin3d-stage { --coin-scale: .86; }
}

@media (max-width: 980px) {
  /* Stacks under the balances rather than above them — the numbers are why the
     page exists, so they stay first. */
  .wallet-hero { grid-template-columns: minmax(0, 1fr); }
  .wallet-hero .coin3d-stage { height: 190px; --coin-scale: .8; order: 2; }
  .hero-coin { height: 250px; --coin-scale: .84; }
}
@media (max-width: 560px) {
  .wallet-hero .coin3d-stage { height: 168px; --coin-scale: .68; }
  .hero-coin { height: 210px; --coin-scale: .72; }
}

@media (prefers-reduced-motion: reduce) {
  /* Genuinely still, and parked at a three-quarter angle so the object still
     reads as dimensional rather than as a flat disc. */
  .c-float, .c-wobble, .c-coin, .c-spec,
  .c-ring-orbit, .c-shadow { animation: none !important; }
  .c-wobble { transform: rotateX(-17deg); }
  .c-coin   { transform: rotateY(-26deg); }
  .c-spec   { opacity: .55; transform: translateX(130%) rotate(14deg); }
  .c-ring-orbit.o1 { transform: rotateX(75deg); }
  .c-ring-orbit.o2 { transform: rotateX(63deg); }
  .c-parallax { transition: none; }
}
