/* ═══════════════════════════════════════════════════════════════════════════
   OTT Downloader — shared design system  ·  "Aurora Glass"

   One stylesheet for the verify page, the user Mini App and the admin console.

   Design decisions, so the next person does not have to guess:

   · Dark-first. Telegram's webview is dark for most users and a media tool
     reads better on a dark ground. Light mode is fully supported, not an
     afterthought - every token is redefined, not just inverted.
   · Depth comes from LAYERS, not bevels: a live aurora field behind the page
     (fx.js), translucent glass surfaces above it, and stacked shadows plus a
     top-edge highlight on top of that. That is the "3D" here - it survives
     resizing, theming and reduced-motion, which a skeuomorphic bevel does not.
   · Motion budget: one or two moving things per view. Everything transitions
     on shared tokens (--dur/--ease), and every animation stops dead under
     prefers-reduced-motion.
   · Contrast is checked: body text and muted text both clear 4.5:1 on their
     own surface in both themes. Focus rings are 2px + 2px offset (WCAG 2.2
     focus appearance), never removed.
   · Icons are SVG (.ico), never emoji - emoji render differently on every
     platform and carry no accessible name.

   Class names are load-bearing: the Mini App's JS builds markup as strings and
   toggles .on/.active/.hide/.show. Restyle freely, rename nothing.
   ═══════════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');

/* ── tokens ─────────────────────────────────────────────────────────────── */
:root{
  color-scheme: light dark;

  /* text */
  --ink:#0b1020;
  --ink-2:#39415c;
  --ink-3:#5c6483;          /* 4.6:1 on --surface, so "muted" stays readable */

  /* ground + surfaces */
  --page:#eaeefb;
  --page-2:#dfe5f7;
  --surface:#ffffff;
  --surface-2:#f2f5fc;
  --glass:rgba(255,255,255,.80);
  --glass-2:rgba(255,255,255,.64);
  --blur:18px;

  /* brand */
  --brand:#4f46e5;
  --brand-2:#7c3aed;
  --brand-3:#a855f7;
  --accent:#06b6d4;
  --brand-soft:rgba(79,70,229,.11);
  --brand-line:rgba(79,70,229,.30);

  /* status */
  --ok:#047857;  --ok-soft:rgba(4,120,87,.12);
  --bad:#be123c; --bad-soft:rgba(190,18,60,.12);
  --warn:#b45309; --warn-soft:rgba(180,83,9,.14);

  --line:rgba(11,16,32,.12);
  --line-2:rgba(11,16,32,.07);

  /* elevation: hairline highlight on top, diffuse shadow below */
  --e1:0 1px 1px rgba(11,16,32,.04), 0 2px 6px rgba(11,16,32,.05);
  --e2:0 1px 2px rgba(11,16,32,.05), 0 8px 20px rgba(11,16,32,.08),
       inset 0 1px 0 rgba(255,255,255,.85);
  --e3:0 2px 4px rgba(11,16,32,.06), 0 18px 42px rgba(11,16,32,.13),
       inset 0 1px 0 rgba(255,255,255,.9);
  --press:inset 0 2px 6px rgba(11,16,32,.12);
  --glow:0 10px 30px rgba(79,70,229,.28);

  --r-sm:12px; --r:16px; --r-lg:22px; --r-xl:28px;

  --sans:'Plus Jakarta Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  /* motion tokens - deceleration on arrival, acceleration on exit */
  --dur:.22s;
  --dur-slow:.42s;
  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-spring:cubic-bezier(.2,.9,.3,1.15);
}

@media (prefers-color-scheme: dark){
  :root{
    --ink:#f2f5ff; --ink-2:#c3cade; --ink-3:#98a1bd;   /* 4.7:1 on --surface */

    --page:#070a16; --page-2:#04060f;
    --surface:#141a2e; --surface-2:#1b2238;
    --glass:rgba(23,30,52,.74);
    --glass-2:rgba(23,30,52,.58);

    --brand:#818cf8; --brand-2:#a78bfa; --brand-3:#c084fc; --accent:#22d3ee;
    --brand-soft:rgba(129,140,248,.16);
    --brand-line:rgba(129,140,248,.38);

    --ok:#34d399;  --ok-soft:rgba(52,211,153,.14);
    --bad:#fb7185; --bad-soft:rgba(251,113,133,.14);
    --warn:#fbbf24; --warn-soft:rgba(251,191,36,.15);

    --line:rgba(255,255,255,.13);
    --line-2:rgba(255,255,255,.07);

    --e1:0 1px 2px rgba(0,0,0,.45);
    --e2:0 2px 10px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.06);
    --e3:0 14px 38px rgba(0,0,0,.58), inset 0 1px 0 rgba(255,255,255,.08);
    --press:inset 0 2px 8px rgba(0,0,0,.55);
    --glow:0 12px 36px rgba(129,140,248,.34);
  }
}

/* ── base ───────────────────────────────────────────────────────────────── */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{max-width:100%;overflow-x:hidden}

body{
  margin:0;padding:14px 14px 104px;
  color:var(--ink);
  font:600 14.5px/1.5 var(--sans);
  letter-spacing:-.006em;
  -webkit-font-smoothing:antialiased;
  /* The aurora canvas (fx.js) paints on top of this; the gradients below are
     the still fallback for reduced-motion, no-JS and old webviews. */
  background:
    radial-gradient(120vw 60vh at 8% -12%, var(--brand-soft), transparent 60%),
    radial-gradient(90vw 50vh at 104% 2%, rgba(6,182,212,.12), transparent 58%),
    linear-gradient(180deg, var(--page) 0%, var(--page-2) 100%);
  /* NOT background-attachment:fixed - it forces a full-page repaint on every
     scroll frame, and with gradients that size it is the single most expensive
     thing a phone webview can be asked to do. The aurora canvas is already
     position:fixed, which gives the same parallax for free. */
  background-repeat:no-repeat;
  min-height:100vh;
}

/* the animated field lives behind everything and never eats a tap */
#fxbg{
  position:fixed;inset:0;width:100%;height:100%;
  z-index:-1;pointer-events:none;display:block;
  opacity:0;transition:opacity .8s var(--ease);
}
#fxbg.on{opacity:1}

h1{font-size:22px;font-weight:800;letter-spacing:-.032em;margin:0 0 2px;line-height:1.14}
h2{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.13em;
   color:var(--ink-3);margin:24px 0 10px;display:flex;align-items:center;gap:8px}
h2:after{content:'';flex:1;height:1px;background:linear-gradient(90deg,var(--line),transparent)}
.display{font-size:27px;font-weight:800;letter-spacing:-.035em;line-height:1.1}

a{color:var(--brand)}

/* ── surfaces ───────────────────────────────────────────────────────────── */
.card{
  position:relative;
  background:var(--glass);
  border:1px solid var(--line-2);
  border-radius:var(--r-lg);
  padding:16px;margin-bottom:12px;
  box-shadow:var(--e2);
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.card.flat{box-shadow:var(--e1);background:var(--glass-2)}
.card.raise{box-shadow:var(--e3)}

/* a lit top edge sells the sheet-of-glass read far better than a border does */
.card:before{
  content:'';position:absolute;inset:0 0 auto;height:1px;border-radius:inherit;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
  opacity:.6;pointer-events:none;
}
@media (prefers-color-scheme: dark){
  .card:before{background:linear-gradient(90deg,transparent,rgba(255,255,255,.22),transparent)}
}

/* press feedback on anything interactive that is a card */
.card.tap:active{transform:translateY(1px) scale(.995)}

.hero{
  position:relative;overflow:hidden;color:#fff;border:0;
  background:linear-gradient(135deg,var(--brand) 0%,var(--brand-2) 52%,var(--brand-3) 88%);
  box-shadow:var(--glow), inset 0 1px 0 rgba(255,255,255,.3);
  backdrop-filter:none;-webkit-backdrop-filter:none;
}
/* two slow-drifting light pools - the only always-on motion in the hero */
.hero:before{
  content:'';position:absolute;inset:-60% -30% auto auto;width:260px;height:260px;
  border-radius:50%;background:rgba(255,255,255,.20);filter:blur(24px);
  animation:drift 14s ease-in-out infinite;will-change:transform;
}
.hero:after{
  content:'';position:absolute;inset:auto auto -70% -20%;width:220px;height:220px;
  border-radius:50%;background:rgba(34,211,238,.28);filter:blur(28px);
  animation:drift 18s ease-in-out infinite reverse;will-change:transform;
}
@keyframes drift{
  0%,100%{transform:translate3d(0,0,0)}
  50%{transform:translate3d(-30px,24px,0)}
}
.hero *{position:relative;z-index:1}
.hero .muted,.hero h1,.hero b{color:#fff}
.hero .muted{opacity:.88}

.head{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.avatar{
  width:48px;height:48px;border-radius:16px;flex:0 0 auto;overflow:hidden;
  display:grid;place-items:center;font-size:19px;font-weight:800;color:#fff;
  background:linear-gradient(140deg,var(--brand),var(--brand-2));
  box-shadow:0 8px 20px rgba(79,70,229,.42), inset 0 1px 0 rgba(255,255,255,.4);
}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}

/* ── stats ──────────────────────────────────────────────────────────────── */
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(92px,1fr));gap:10px}
.stat{
  position:relative;overflow:hidden;
  background:var(--glass);border:1px solid var(--line-2);border-radius:var(--r);
  padding:14px 9px;text-align:center;box-shadow:var(--e2);
  transition:transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease);
}
.stat:active{transform:translateY(-2px);box-shadow:var(--e3)}
.stat:after{
  content:'';position:absolute;inset:auto 0 0;height:2px;
  background:linear-gradient(90deg,var(--brand),var(--accent));
  opacity:.85;
}
.stat b{display:block;font-size:22px;font-weight:800;letter-spacing:-.03em;line-height:1.15;
        background:linear-gradient(180deg,var(--ink),var(--ink-2));
        -webkit-background-clip:text;background-clip:text;color:transparent}
.stat span{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.09em;
           color:var(--ink-3)}

/* ── layout helpers ─────────────────────────────────────────────────────── */
.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.row+.row{margin-top:10px}

/* ── form controls ──────────────────────────────────────────────────────── */
input,select,textarea{
  font:600 14px/1.4 var(--sans);width:100%;padding:13px 14px;color:var(--ink);
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);
  box-shadow:var(--press);
  transition:border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
             background var(--dur) var(--ease);
}
input:hover,textarea:hover,select:hover{border-color:var(--brand-line)}
input:focus,textarea:focus,select:focus{
  outline:0;border-color:var(--brand);
  box-shadow:0 0 0 3px var(--brand-soft), var(--press);
  background:var(--surface);
}
input::placeholder,textarea::placeholder{color:var(--ink-3);font-weight:500}
textarea{min-height:86px;resize:vertical;line-height:1.5}

/* WCAG 2.2 focus appearance: 2px ring, 2px offset, never suppressed */
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:6px}

/* ── buttons ────────────────────────────────────────────────────────────── */
button{
  position:relative;overflow:hidden;
  font:700 14px/1 var(--sans);letter-spacing:-.01em;padding:13px 16px;border:0;
  border-radius:var(--r-sm);cursor:pointer;color:#fff;
  background:linear-gradient(180deg,var(--brand),var(--brand-2));
  box-shadow:0 6px 18px rgba(79,70,229,.34), inset 0 1px 0 rgba(255,255,255,.3);
  transition:transform .09s var(--ease), box-shadow var(--dur) var(--ease),
             filter var(--dur) var(--ease);
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
}
button:hover{filter:brightness(1.07)}
button:active{transform:translateY(2px) scale(.985);
              box-shadow:0 2px 6px rgba(79,70,229,.3), var(--press)}
/* a light sweeps across the primary action on press - one frame of delight,
   no layout cost, and it is skipped entirely under reduced-motion */
button:after{
  content:'';position:absolute;inset:0;transform:translateX(-120%) skewX(-18deg);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.32),transparent);
  pointer-events:none;
}
button:active:after{animation:sweep .55s var(--ease-out)}
@keyframes sweep{to{transform:translateX(120%) skewX(-18deg)}}

button.sec{
  background:var(--glass);color:var(--ink);border:1px solid var(--line);
  box-shadow:var(--e1);
}
button.sec:active{box-shadow:var(--press)}
button.danger{background:linear-gradient(180deg,#f43f5e,#be123c);
              box-shadow:0 6px 18px rgba(225,29,72,.34), inset 0 1px 0 rgba(255,255,255,.24)}
button.warn{background:linear-gradient(180deg,#f59e0b,#d97706);
            box-shadow:0 6px 18px rgba(217,119,6,.32), inset 0 1px 0 rgba(255,255,255,.26)}
button.ok{background:linear-gradient(180deg,#10b981,#047857);
          box-shadow:0 6px 18px rgba(5,150,105,.32), inset 0 1px 0 rgba(255,255,255,.24)}
button.ghost{background:transparent;color:var(--brand);box-shadow:none;
             border:1px dashed var(--brand-line)}
button.sm{padding:9px 12px;font-size:12.5px;border-radius:10px}
button:disabled{opacity:.45;box-shadow:none;cursor:not-allowed;filter:none}
button:disabled:active{transform:none}
button.block{width:100%}
button.busy{pointer-events:none}
button.busy:before{
  content:'';width:14px;height:14px;border-radius:50%;flex:0 0 auto;
  border:2px solid rgba(255,255,255,.35);border-top-color:#fff;
  animation:r .7s linear infinite;
}

/* inline SVG icons inside buttons / nav */
.ico{width:18px;height:18px;flex:0 0 auto;display:block;
     fill:none;stroke:currentColor;stroke-width:1.9;
     stroke-linecap:round;stroke-linejoin:round}

/* ── pills ──────────────────────────────────────────────────────────────── */
.pill{display:inline-flex;align-items:center;gap:5px;padding:4px 11px;border-radius:999px;
      font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;
      border:1px solid transparent}
.pill.on{background:var(--ok-soft);color:var(--ok);border-color:var(--ok-soft)}
.pill.off{background:var(--bad-soft);color:var(--bad);border-color:var(--bad-soft)}
.pill.w{background:var(--warn-soft);color:var(--warn);border-color:var(--warn-soft)}
.pill.b{background:var(--brand-soft);color:var(--brand);border-color:var(--brand-line)}
/* a live pill breathes so "downloading" reads as ongoing, not stuck */
.pill.live:before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;
                  animation:pulse 1.6s var(--ease) infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.7)}}

/* ── key/value rows ─────────────────────────────────────────────────────── */
.kv{display:flex;justify-content:space-between;align-items:center;gap:11px;
    padding:10px 0;border-bottom:1px solid var(--line-2);font-size:13.5px;min-width:0}
.kv:last-child{border-bottom:0}
/* Both sides may shrink: a WebGL renderer string opposite a timestamp used to
   force the whole page into horizontal scroll. */
.kv>span:first-child{color:var(--ink-3);font-weight:600;flex:1 1 auto;
                     min-width:0;overflow-wrap:anywhere}
.kv>span:last-child{text-align:right;font-weight:700;flex:0 1 auto;
                    min-width:0;overflow-wrap:anywhere}

.devrow{padding:11px 0;border-bottom:1px solid var(--line-2);font-size:13px;min-width:0}
.devrow:last-child{border-bottom:0}
.devrow b{display:block;font-weight:650;line-height:1.35;overflow-wrap:anywhere}
.devrow .when{display:block;margin-top:3px;font-size:11.5px;color:var(--ink-3);white-space:nowrap}

/* ── chips (multi-select: platforms, audio, quality) ───────────────────── */
.chips{display:grid;grid-template-columns:repeat(auto-fit,minmax(126px,1fr));gap:9px}
.chip{
  position:relative;
  border:1px solid var(--line);border-radius:var(--r-sm);padding:12px 10px;
  font-size:12.5px;font-weight:700;text-align:center;cursor:pointer;user-select:none;
  background:var(--glass);box-shadow:var(--e1);
  transition:transform .1s var(--ease-spring), border-color var(--dur) var(--ease),
             box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
  /* 44px minimum touch target */
  min-height:44px;display:flex;align-items:center;justify-content:center;
}
.chip:hover{border-color:var(--brand-line)}
.chip:active{transform:scale(.97)}
.chip.on{border-color:var(--brand);background:var(--brand-soft);color:var(--brand);
         box-shadow:0 6px 18px var(--brand-soft), inset 0 1px 0 rgba(255,255,255,.14);
         transform:translateY(-1px)}
.chip.ok{border-color:var(--ok);background:var(--ok-soft);color:var(--ok)}
.chip.lock{opacity:.5;cursor:not-allowed}

/* ── progress ───────────────────────────────────────────────────────────── */
.bar{height:9px;border-radius:99px;background:var(--surface-2);overflow:hidden;
     margin-top:8px;box-shadow:var(--press);position:relative}
.bar i{display:block;height:100%;border-radius:99px;
       background:linear-gradient(90deg,var(--brand),var(--brand-2),var(--accent));
       transition:width .4s var(--ease-out)}
/* indeterminate: a shuttle, linear easing because the rate really is constant */
.bar.live i{width:34%;animation:sl 1.15s linear infinite;will-change:margin-left}
@keyframes sl{0%{margin-left:-36%}100%{margin-left:102%}}

/* ── text ───────────────────────────────────────────────────────────────── */
.mono{font-family:var(--mono);font-size:11.5px;font-weight:500;word-break:break-all}
.muted{color:var(--ink-3);font-size:12.5px;font-weight:600}
.step{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;
      margin-bottom:10px;display:flex;align-items:center;gap:7px;
      background:linear-gradient(90deg,var(--brand),var(--brand-3));
      -webkit-background-clip:text;background-clip:text;color:transparent}
.item{border:1px solid var(--line-2);border-radius:var(--r);padding:13px;margin-top:10px;
      background:var(--surface-2);
      transition:transform var(--dur) var(--ease), border-color var(--dur) var(--ease)}
.item:active{transform:translateY(1px)}
.err{border-left:4px solid var(--bad)}

/* ── toast ──────────────────────────────────────────────────────────────── */
.toast{
  position:fixed;left:14px;right:14px;bottom:88px;padding:14px 17px;border-radius:var(--r);
  background:color-mix(in srgb,var(--ink) 94%,transparent);color:var(--page);
  font-size:13.5px;font-weight:700;text-align:center;
  opacity:0;transform:translateY(10px) scale(.97);
  transition:opacity var(--dur) var(--ease), transform var(--dur) var(--ease-spring);
  pointer-events:none;z-index:99;box-shadow:var(--e3);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
}
.toast.show{opacity:1;transform:translateY(0) scale(1)}

/* ── bottom navigation ──────────────────────────────────────────────────── */
.nav{
  position:fixed;left:0;right:0;bottom:0;display:flex;gap:2px;padding:10px 8px;
  padding-bottom:calc(10px + env(safe-area-inset-bottom));
  background:var(--glass);
  backdrop-filter:blur(22px) saturate(160%);-webkit-backdrop-filter:blur(22px) saturate(160%);
  border-top:1px solid var(--line-2);z-index:60;
  box-shadow:0 -10px 30px rgba(11,16,32,.10);
}
.nav button{
  flex:1;background:transparent;color:var(--ink-3);box-shadow:none;padding:7px 0;
  font-size:10.5px;font-weight:700;flex-direction:column;gap:5px;min-height:48px;
  border-radius:12px;
}
.nav button:after{display:none}          /* no sweep on tabs */
.nav button:hover{filter:none;color:var(--ink-2)}
.nav button:active{transform:none}
.nav button .ico{width:21px;height:21px;transition:transform var(--dur) var(--ease-spring)}
.nav button b{font-size:17px;font-weight:500;line-height:1}   /* legacy glyph tabs */
.nav button.active{color:var(--brand)}
.nav button.active .ico{transform:translateY(-2px) scale(1.08)}
.nav button.active b{transform:translateY(-1px)}
/* the active tab sits on a lit pad rather than just changing colour */
.nav button.active:before{
  content:'';position:absolute;inset:2px 8px;border-radius:12px;
  background:var(--brand-soft);z-index:-1;
  animation:padin .25s var(--ease-spring);
}
@keyframes padin{from{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}

/* ── utility ────────────────────────────────────────────────────────────── */
.hide{display:none!important}
.spin{width:26px;height:26px;margin:30px auto;border:3px solid var(--line);
      border-top-color:var(--brand);border-radius:50%;animation:r .75s linear infinite}
@keyframes r{to{transform:rotate(360deg)}}

/* content that fades up as it is inserted - applied by fx.js, one per section */
.reveal{animation:rise .5s var(--ease-out) both}
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* ── motion & transparency preferences ──────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *,*:before,*:after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  /* progress indicators still need to read as "working" */
  .spin,.bar.live i,button.busy:before{animation-duration:1.4s!important;
                                       animation-iteration-count:infinite!important}
  #fxbg{display:none}
}
/* Some Android webviews fake backdrop-filter support and paint the blur as a
   flat grey. Where it is genuinely unsupported, fall back to solid surfaces so
   text never lands on a half-transparent ground. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  /* Only the fixed overlays still ask for a blur; where it is unsupported they
     need an opaque ground or the content behind shows through the nav. */
  .nav,.toast{background:var(--surface)}
}

/* Blur is confined to these two: they are small, fixed, and composited once -
   see the note on .card above for why it is not used on scrolling content. */
.nav,.toast{backdrop-filter:blur(20px) saturate(160%);
            -webkit-backdrop-filter:blur(20px) saturate(160%)}
