
  /* ---- Boot screen ----------------------------------------------------
     Covers the gap between the OS splash (static, not animatable) and the
     first render. Removed as soon as the app paints. */
  #boot{position:fixed; inset:0; z-index:9999; display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:26px;
    background:#F7F3F1; color:#4A1E38;
    transition:opacity .28s ease, visibility .28s ease;}
  #boot.gone{opacity:0; visibility:hidden; pointer-events:none;}html[data-theme="dark"] #boot{color:#F4EDF1;}
  .boot-mark{width:148px; animation:bootIn .5s cubic-bezier(.2,.7,.3,1) both, bootPulse 1.9s 0.5s ease-in-out infinite;}
  .boot-mark svg{width:100%; height:auto; display:block;}
  .boot-bar{width:92px; height:3px; border-radius:2px; background:rgba(74,30,56,.14); overflow:hidden;}
  html[data-theme="dark"] .boot-bar{background:rgba(255,255,255,.14);}
  .boot-bar i{display:block; width:40%; height:100%; border-radius:2px;
    background:linear-gradient(90deg,#B4638F,#4A1E38); animation:bootSlide 1.1s ease-in-out infinite;}
  html[data-theme="dark"] .boot-bar i{background:linear-gradient(90deg,#E9A8CE,#CB86AF);}
  @keyframes bootIn{from{opacity:0; transform:translateY(6px) scale(.96);} to{opacity:1; transform:none;}}
  @keyframes bootPulse{0%,100%{opacity:1;} 50%{opacity:.55;}}
  @keyframes bootSlide{0%{transform:translateX(-110%);} 100%{transform:translateX(260%);}}
  @media (prefers-reduced-motion:reduce){
    .boot-mark{animation:bootIn .2s both;}
    .boot-bar i{animation:none; width:100%; opacity:.5;}
  }
  :root{
    /* ===== BERNQ Design System v1 — foundation tokens (adopted) ===== */
    /* Plum ramp, re-based on #4A1E38 (plum-700 = primary) */
    --plum-950:#210D19; --plum-800:#311425; --plum-700:#4A1E38; --plum-600:#6D2C52;
    --plum-500:#913B6E; --plum-300:#CB86AF; --plum-200:#DAB4CA; --plum-100:#EDDEE7; --plum-050:#F6F1F4;
    /* Ivory surfaces */
    --ivory-000:#FFFDFB; --ivory-050:#FFFAF6; --ivory-100:#FBF5EF; --ivory-200:#F3EAE2;
    /* Readable type scale */
    --fs-display:40px; --fs-h1:22px; --fs-h2:17px; --fs-title:15px;
    --fs-body:14px; --fs-sub:13px; --fs-small:12px; --fs-btn:14px; --fs-kicker:12px;
    --radius-card:16px; --radius-button:12px;

    /* Brand palette — deep aubergine identity (design v2) */
    --plum:#4A1E38;         /* primary: buttons, active nav, headings */
    --plum-deep:#3A1329;    /* darkest — gradient end, balance card */
    --plum-mid:#6B2F4F;     /* mid tone for gradients */
    --plum-accent:#8B4A6B;  /* links and accents */
    --plum-soft:#F0E6EC;    /* soft fill: icon tiles, avatars */
    --plum-mist:#FAF6F8;    /* faintest tint */
    --ink:#1C1416;          /* primary text */
    --ink-soft:#6B5F63;     /* secondary text */
    --muted:#6E5B66;        /* tertiary text, placeholders */
    --line:#EDE7E4;         /* hairlines, borders */
    --surface:#FFFFFF;
    --surface-alt:#FAF7F5;  /* cards nested on cards */
    --bg:#F7F3F1;           /* page background, warm off-white */
    --bg-auth:#FBF0DE;      /* auth screens use a warmer cream */
    /* Status */
    --ok:#3E8E5A;           /* warranty active — green */
    --ok-bg:#EAF5EE;
    --warn:#D4682A;         /* warranty expiring — orange */
    --warn-bg:#FCEFE7;
    --gold:#D9A441;         /* points coin */
    --sage:#3E8E5A;         /* legacy alias → ok */
    --amber:#D4682A;        /* legacy alias → warn */
    --success:#3E8E5A;      /* reskin alias → same green as --sage */
    --warning:#D4682A;      /* reskin alias → same orange as --warn */
    --radius:16px;
    --radius-sm:12px;
    --radius-lg:20px;
    --shadow:0 1px 3px rgba(28,20,22,.04), 0 2px 12px rgba(28,20,22,.06);
    --shadow-lift:0 2px 6px rgba(28,20,22,.06), 0 4px 20px rgba(74,30,56,.10);
  }
  /* Dark theme — deep aubergine-charcoal, keeps the brand warmth */
  html[data-theme="dark"]{
    --plum:#C9A0BC;
    --plum-deep:#DDBCD3;
    --plum-mid:#9E6A87;
    --plum-accent:#D5A8C4;
    --plum-soft:#433041;
    --plum-mist:#352637;
    --ink:#F4EDF1;
    --ink-soft:#DCD2D8;
    --muted:#BCAFB6;
    --line:#4C3948;
    --surface:#352637;
    --surface-alt:#402F41;
    --bg:#271C28;
    --bg-auth:#2E2130;
    --ok:#5FB37C;
    --ok-bg:#1E3327;
    --warn:#E28A4F;
    --warn-bg:#3A251A;
    --gold:#E0B75C;
    --sage:#5FB37C;
    --amber:#E28A4F;
    --success:#5FB37C;      /* reskin alias → dark-mode green */
    --warning:#E28A4F;      /* reskin alias → dark-mode orange */
    --shadow:0 1px 3px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
    --shadow-lift:0 2px 6px rgba(0,0,0,.4), 0 16px 40px rgba(0,0,0,.45);
  }
  *{box-sizing:border-box; -webkit-tap-highlight-color:transparent; margin:0; padding:0;}html{min-height:100%; overscroll-behavior-x:none;}
  /* Landscape lock. iOS ignores the manifest orientation field, so instead of
     preventing rotation we make landscape a dead end rather than a broken layout.
     Only applies to phone-height screens, so desktop and tablets are unaffected. */
  #rotate{display:none;}
  @media (orientation:landscape) and (max-height:520px){
    #rotate{display:flex; position:fixed; inset:0; z-index:10000;
      flex-direction:column; align-items:center; justify-content:center; gap:16px;
      background:#F7F3F1; color:var(--plum);}
    html[data-theme="dark"] #rotate{background:#271C28;}
    body > *:not(#rotate){display:none !important;}
  }
  .rot-logo{position:absolute; top:18px; left:0; right:0; text-align:center;
    font-size:13px; font-weight:800; color:var(--plum); letter-spacing:.06em;}
  .rot-ic{animation:rotTilt 2.4s ease-in-out infinite; transform-origin:50% 50%;}
  @keyframes rotTilt{0%,100%{transform:rotate(0)}45%,55%{transform:rotate(-90deg)}}
  .rot-t{font-size:17px; font-weight:820; color:var(--ink); letter-spacing:-.02em;}
  .rot-s{font-size:13px; color:var(--muted); max-width:280px; text-align:center; line-height:1.5;}
  @media (prefers-reduced-motion:reduce){ .rot-ic{animation:none;} }

  html{background:#F7F3F1;}
  html[data-theme="dark"]{background:#271C28;}
  body{
    font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
    background:var(--bg); color:var(--ink);
    max-width:480px; margin:0 auto; position:relative; min-height:100vh; min-height:100dvh;
    padding-bottom:calc(var(--nav-h, 92px) + 14px);
    -webkit-font-smoothing:antialiased;
    letter-spacing:-0.01em;
    overscroll-behavior-x:none; overflow-x:hidden;
  }
  button{font-family:inherit; cursor:pointer; border:none; background:none; color:inherit;}
  .hidden{display:none !important;}

  /* ---------- Top bar ---------- */
  .topbar{
    position:sticky; top:0; z-index:20;
    background:var(--bg); backdrop-filter:saturate(180%) blur(14px);
    padding:calc(env(safe-area-inset-top) + 12px) 20px 12px;
    display:flex; align-items:center; justify-content:space-between;
    border-bottom:1px solid var(--line);
  }
  body.authing .topbar{background:transparent; backdrop-filter:none; border-bottom:none;}body.authing{overflow:hidden; height:100dvh;}
  .auth-back{display:flex; align-items:center; gap:4px; color:var(--ink-soft); font-size:14px; font-weight:600; padding:6px 0;}

  /* ---------- Layout ---------- */
  .screen{padding:22px 20px 8px; animation:fade .32s ease;}
  /* A14 — input fields with a leading icon */
  
  
  
  @keyframes fade{from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:none;}}
  .section-label{
    font-size:11px; font-weight:700; color:var(--muted);
    letter-spacing:.09em; text-transform:uppercase;
    margin:30px 0 12px; display:flex; align-items:center; gap:7px;
  }
  .section-label svg{width:14px; height:14px; opacity:.7;}
  .greeting{font-size:14.5px; color:var(--ink-soft); margin-bottom:16px; font-weight:500;}

  /* ---------- Cards ---------- */
  .card{
    background:var(--surface); border:1px solid var(--line);
    border-radius:var(--radius); padding:16px; margin-bottom:10px;
  }

  /* Badges */
  .badge{
    display:inline-flex; align-items:center; gap:4px;
    font-size:10.5px; font-weight:700; padding:4px 9px; border-radius:100px;
    letter-spacing:.01em;
  }
  .badge-plum{background:var(--plum-soft); color:var(--plum-deep);}
  .badge-sage{background:var(--ok-bg); color:var(--ok);}

  /* ---------- Buttons ---------- */
  .add-btn{
    width:100%; display:flex; align-items:center; justify-content:center; gap:9px;
    background:var(--ink); color:#fff; border-radius:15px; padding:16px;
    font-size:14.5px; font-weight:700; margin-top:6px; transition:transform .15s ease;
  }
  .add-btn:active{transform:scale(.98);}
  .care-btn.done{background:#E8F1EB; color:var(--sage);}
  .give-btn.done{background:#E8F1EB; color:var(--sage);}
  /* Legacy header card still used by FAQ and Profile subviews */
  .detail-hero{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-card);
    padding:16px; margin-bottom:14px; display:flex; flex-direction:column; box-shadow:0 7px 22px rgba(74,30,56,.06);}
  .detail-name{font-size:var(--fs-h2); font-weight:820; letter-spacing:-.02em;}
  .pd-card-ico.warn{background:var(--warn-bg); color:var(--warn);}
  .pd-card-ico.mut{background:var(--plum-soft); color:var(--muted);}
  .pd-extend{display:block; width:100%; height:50px; border:0; border-radius:var(--radius-button);
    background:linear-gradient(180deg,#6E405D,var(--plum-700) 56%,#3D2935); color:#fff;
    font-size:var(--fs-btn); font-weight:760; box-shadow:0 6px 14px rgba(74,30,56,.22); cursor:pointer;}
  .pd-extend-note{font-size:var(--fs-small); color:var(--muted); text-align:center; line-height:1.45; margin:10px 14px 4px;}

  /* ---- Product detail v2 ---- */
  .pdx-head{display:flex; gap:14px; align-items:center; background:var(--surface);
    border:1px solid var(--line); border-radius:16px; padding:14px; margin-bottom:14px;}
  .pdx-head img{width:92px; height:92px; object-fit:contain; flex:none;}
  .pdx-info{flex:1; min-width:0;}
  .pdx-name{display:block; font-size:18px; font-weight:820; color:var(--ink); line-height:1.2;}
  .pdx-model{display:block; font-size:12px; color:var(--muted); margin-top:2px;}
  .pdx-pill{display:inline-flex; align-items:center; gap:6px; margin-top:8px;
    border-radius:999px; padding:5px 10px; font-size:11px; font-weight:750;}
  .pdx-pill svg{width:13px; height:13px;}
  .pdx-pill.ok{background:var(--ok-bg); color:var(--ok);}
  .pdx-pill.warn{background:var(--warn-bg); color:var(--warn);}
  .pdx-pill.mut{background:var(--surface-alt); color:var(--muted);}
  .pdx-warr{background:linear-gradient(160deg,#6E405D,var(--plum-700)); color:#fff;
    border-radius:16px; padding:15px; margin-bottom:14px;}
  .pdx-warr.expired{background:linear-gradient(160deg,#6B6068,#4A434A);}
  .pdx-warr-k{font-size:11px; opacity:.8; text-transform:uppercase; letter-spacing:.06em;}
  .pdx-warr-v{font-size:22px; font-weight:820; margin-top:4px; letter-spacing:-.02em;}
  .pdx-warr-s{font-size:11.5px; color:#D9B6CB; margin-top:4px;}
  .pdx-warr.expired .pdx-warr-s{color:#CFC7CD;}
  .pdx-sec{font-size:12px; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
    color:var(--muted); margin:18px 0 9px;}
  .pdx-docs{display:grid; grid-template-columns:repeat(3,1fr); gap:9px;}
  .pdx-doc{position:relative; background:var(--surface); border:1px solid var(--line);
    border-radius:14px; padding:12px 10px; text-align:left; opacity:.62; cursor:pointer;}
  .pdx-doc-ic{display:grid; place-items:center; width:34px; height:34px; border-radius:10px;
    background:var(--surface-alt); color:var(--muted); margin-bottom:9px;}
  .pdx-doc-ic svg{width:18px; height:18px;}
  .pdx-doc-lbl{display:block; font-size:11.5px; font-weight:750; color:var(--ink); line-height:1.3;}
  .pdx-doc-badge{position:absolute; top:9px; right:9px; font-size:9px; font-weight:800;
    letter-spacing:.05em; text-transform:uppercase; color:var(--muted);
    background:var(--surface-alt); border:1px solid var(--line); border-radius:6px; padding:2px 6px;}
  

  /* ---------- Rewards ---------- */
  
  
  
  .earn-chev.open{transform:rotate(90deg);}
  
  .earn-drop-body .earn-row{border:none; border-radius:0; border-bottom:1px solid var(--line); margin:0;}
  .earn-drop-body .earn-row:last-child{border-bottom:none;}
  .earn-row{
    display:flex; align-items:center; gap:12px;
    background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-card);
    padding:0 18px; height:54px; margin-bottom:10px;
  }
  
  .earn-title{font-size:var(--fs-body); font-weight:600; letter-spacing:-.1px; color:var(--ink);}
  

  .refer-card{
    background:linear-gradient(145deg, var(--plum) 0%, var(--plum-deep) 100%);
    border-radius:var(--radius-card); padding:20px; color:#fff; margin-bottom:12px; box-shadow:var(--shadow-lift);
  }
  
  .refer-sub{font-size:var(--fs-sub); color:#D9BECB; margin:6px 0 0; line-height:1.4;}
  .refer-code{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    background:rgba(255,255,255,.1); border:1px dashed rgba(255,255,255,.3);
    border-radius:12px; padding:12px 14px; margin-top:15px;
  }
  .refer-code-val{font-size:18px; font-weight:800; letter-spacing:.12em;}
  .refer-copy{display:flex; align-items:center; gap:5px; font-size:var(--fs-small); font-weight:700; color:#fff;
    background:rgba(255,255,255,.16); padding:7px 12px; border-radius:8px;}

  /* ---------- Home cards ---------- */
  /* Single accent hero (AI). Neutral tiles for everything else. */
  .aicard{position:relative; width:100%; text-align:left; cursor:pointer; display:flex; gap:12px; align-items:flex-end;
    border:1px solid var(--line); border-radius:18px; padding:14px; margin-bottom:12px;
    background:var(--surface); box-shadow:0 7px 22px rgba(74,30,56,.06); transition:transform .15s ease;}
  .aicard:active{transform:scale(.985);}
  html[data-theme="dark"] .aicard{background:linear-gradient(120deg,rgba(255,255,255,.05),rgba(145,59,110,.14));}
  .aicard-m{width:104px; flex:none; filter:drop-shadow(0 8px 14px rgba(74,30,56,.22));}
  .aicard-m img{width:100%; display:block;}
  .aicard-body{flex:1; min-width:0;}
  .aicard-bub{position:relative; display:block; background:var(--plum-soft); border:1px solid var(--plum-200);
    border-radius:14px; padding:11px 13px; margin-bottom:10px;}
  html[data-theme="dark"] .aicard-bub{border-color:var(--plum-600);}
  .aicard-bub::after{content:""; position:absolute; left:-7px; bottom:14px; width:12px; height:12px;
    background:var(--plum-soft); border-left:1px solid var(--plum-200); border-bottom:1px solid var(--plum-200);
    transform:rotate(45deg);}
  html[data-theme="dark"] .aicard-bub::after{border-color:var(--plum-600);}
  .aicard-t{display:block; font-size:14px; font-weight:780; color:var(--ink);}
  .aicard-ask{display:block; font-size:12px; color:var(--muted); line-height:1.4; margin-top:3px;}
  .aicard-s{display:block; font-size:12px; color:var(--plum); font-weight:600; line-height:1.45; margin-top:5px;
    min-height:35px;}
  html[data-theme="dark"] .aicard-s{color:#CB86AF;}
  .ai-caret{display:inline-block; width:1.5px; height:11px; background:var(--plum); margin-left:1px;
    vertical-align:-1px; animation:aiblink 1s step-end infinite;}
  html[data-theme="dark"] .ai-caret{background:#CB86AF;}
  @keyframes aiblink{0%,100%{opacity:1} 50%{opacity:0}}
  @media (prefers-reduced-motion:reduce){
    .ai-caret{display:none;}
    .aicard-m img{content:url("assets/mascot-still.webp");}
  }
  .aicard-cta{display:flex; align-items:center; justify-content:center; height:38px; border-radius:10px;
    background:linear-gradient(180deg,#6E405D,var(--plum-700)); color:#fff; font-size:12.5px; font-weight:750;
    box-shadow:0 4px 10px rgba(74,30,56,.18);}

  .home-tile{
    display:flex; align-items:center; gap:13px; width:100%; text-align:left;
    background:var(--surface); border:1px solid var(--line); border-radius:var(--radius);
    padding:14px 16px; margin-bottom:10px; transition:transform .15s ease, box-shadow .2s ease;
  }
  .home-tile:active{transform:scale(.985); box-shadow:var(--shadow);}
  .home-tile-ico{flex:none; width:42px; height:42px; border-radius:var(--radius-sm);
    background:var(--plum-soft); color:var(--plum); display:flex; align-items:center; justify-content:center;}
  .home-tile-t{display:block; font-weight:700; font-size:13.5px; letter-spacing:-.2px;}
  .home-tile-s{display:block; font-size:12px; color:var(--muted); line-height:1.4; margin-top:2px;}
  .home-tile-cta{flex:none; font-size:12.5px; font-weight:700; color:var(--plum);}
  .home-tile-cta.warn{color:#C2662F;}

  /* First-run empty state */
  .home-empty{
    background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
    padding:28px 22px; text-align:center; box-shadow:var(--shadow);
  }
  .home-empty-ico{width:56px; height:56px; border-radius:var(--radius); margin:0 auto 14px;
    background:var(--plum-soft); color:var(--plum); display:flex; align-items:center; justify-content:center;}
  .home-empty-t{font-size:17px; font-weight:800; letter-spacing:-.4px; margin-bottom:6px;}
  .home-empty-s{font-size:13px; color:var(--ink-soft); line-height:1.5; margin:0 auto; max-width:280px;}
  .home-empty-perks{display:flex; justify-content:center; gap:18px; margin-top:18px;}
  .home-empty-perk{display:flex; flex-direction:column; align-items:center; gap:6px;
    font-size:11px; font-weight:700; color:var(--ink-soft);}
  .home-empty-perk-ico{width:38px; height:38px; border-radius:50%; background:var(--plum-mist);
    color:var(--plum); display:flex; align-items:center; justify-content:center;}

  /* ---------- Catalog carousel + info screen ---------- */
  
  
  
  
  
  
  
  

  .cat-detail-hero{background:var(--plum-mist); border-radius:var(--radius-lg); padding:30px;
    text-align:center; margin-bottom:16px;}
  .cat-detail-hero img{width:100%; max-width:230px; height:200px; object-fit:contain;}
  .cat-detail-kind{font-size:22px; font-weight:800; letter-spacing:-.6px;}
  .cat-detail-name{font-size:14px; color:var(--muted); margin-top:3px;}
  .cat-tip{display:flex; align-items:flex-start; gap:9px; font-size:13.5px; line-height:1.5;
    color:var(--ink-soft); padding:7px 0;}
  .cat-tip:not(:last-child){border-bottom:1px solid var(--line);}
  .cat-tip svg{color:var(--plum); flex-shrink:0; margin-top:2px;}
  .cat-kaspi{margin-top:20px; text-decoration:none; text-align:center;}

  /* ---------- Daily reward card ---------- */
  .daily-card{margin-top:0; background:var(--surface); border:1px solid var(--line);
    border-radius:var(--radius-card); padding:16px 18px; box-shadow:0 7px 22px rgba(74,30,56,.06);
    position:relative; overflow:hidden;}
  .daily-card::before{content:""; position:absolute; width:150px; height:150px; right:-55px; top:-60px;
    background:radial-gradient(circle,rgba(226,199,218,.22),transparent 67%); pointer-events:none;}
  .daily-top{display:flex; align-items:center; gap:13px; margin-bottom:14px; position:relative; z-index:1;}
  .daily-gift{width:62px; height:62px; flex:none;}
  .daily-gift img{width:100%; height:100%; object-fit:contain;}
  .daily-head-txt{flex:1; min-width:0; display:flex; flex-direction:column; gap:3px;}
  .daily-trow{display:flex; align-items:baseline; justify-content:space-between; gap:2px 8px; flex-wrap:wrap;}
  .daily-trow .daily-t{white-space:nowrap;}
  .daily-t{font-weight:780; font-size:var(--fs-title); color:var(--ink);}
  .daily-s{font-size:var(--fs-sub); color:var(--muted); line-height:1.4;}
  .daily-hint{font-size:var(--fs-small); color:var(--muted); position:relative; z-index:1;}
  .daily-streak{display:inline-flex; align-items:center; gap:3px; font-size:var(--fs-small); font-weight:700;
    color:var(--warn); white-space:nowrap; flex:none;}
  .daily-streak svg{width:13px; height:13px;}
  .daily-dots{display:grid; grid-template-columns:repeat(7,1fr); gap:6px; margin-bottom:16px; position:relative; z-index:1;}
  .daily-cell{display:flex; flex-direction:column; align-items:center; gap:5px; min-width:0;}
  .daily-lbl{font-size:10.5px; font-weight:600; color:var(--muted); white-space:nowrap;}
  .daily-lbl.on{color:var(--plum); font-weight:750;}
  .daily-dot{aspect-ratio:1; width:100%; height:auto; border-radius:50%; display:grid; place-items:center;
    font-size:10.5px; font-weight:800; background:var(--surface-alt); color:var(--plum);
    border:1px solid var(--line);}
  .daily-dot svg{width:15px; height:15px;}
  .daily-dot.fill{background:var(--plum-700); color:#fff; border-color:transparent;}
  .daily-dot.next{border:1.5px solid var(--plum); background:var(--plum-soft); color:var(--plum);}
  .daily-dot.mile{background:radial-gradient(circle at 35% 30%,#FFE3BD,#E8A562 65%,#C67B3C); color:#fff;
    border:0; font-size:11px; box-shadow:0 4px 9px rgba(198,123,60,.3);}
  .daily-dot.mile.fill{background:radial-gradient(circle at 35% 30%,#FFE3BD,#E8A562 65%,#C67B3C); color:#fff;}
  .daily-dot.mile.next{border:1.5px solid #C79320;}
  .daily-dot.miss{background:transparent; border:1px dashed var(--line); color:var(--muted); opacity:.65;}
  .daily-dot.past-blank{background:transparent; border:1px dashed var(--line); opacity:.4;}
  .daily-dot.miss svg{width:12px; height:12px;}
  .daily-cell.past .daily-lbl{opacity:.7;}
  .daily-dot-x{line-height:1;}.daily-btn{display:block; width:100%; height:46px; background:linear-gradient(180deg,#6E405D,var(--plum-700) 56%,#3D2935); color:#fff; border:none; font-weight:760; font-size:var(--fs-btn); cursor:pointer; box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 5px 12px rgba(74,30,56,.2); transition:transform .12s ease; position:relative; z-index:1;}
  .daily-btn:active{transform:scale(.98);}
  .daily-doneline{display:flex; align-items:center; gap:11px; border-radius:var(--radius-button);
    background:var(--ok-bg); padding:11px 16px;}.daily-doneline .circle{width:24px; height:24px; border-radius:50%; color:#fff; display:grid; place-items:center; flex:none;}
  .daily-doneline .circle svg{width:14px; height:14px;}
  .daily-doneline .col{display:flex; flex-direction:column; gap:1px;}.daily-doneline .txt{font-size:var(--fs-body);}.daily-doneline .sub{font-size:11.5px; font-weight:600;}

  /* ---------- Notifications ---------- */
  .notif-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;}
  .notif-markall{background:none; border:none; color:var(--plum); font-weight:700; font-size:13px; cursor:pointer;}
  .notif-push{display:flex; align-items:center; justify-content:center; gap:8px; width:100%;
    background:var(--plum-soft); color:var(--plum); border:none; border-radius:var(--radius);
    padding:12px; font-weight:700; font-size:13.5px; cursor:pointer; margin-bottom:14px;}
  .notif-push svg{width:16px; height:16px;}
  .notif-push.done{background:#E7F4EC; color:#2E9E5B; cursor:default;}
  .notif-push.blocked{background:var(--plum-mist); color:var(--muted); cursor:default; font-weight:600; font-size:12.5px;}
  .notif-list{display:flex; flex-direction:column;}
  .notif-row{display:flex; align-items:flex-start; gap:11px; text-align:left; width:100%;
    background:linear-gradient(165deg,var(--surface) 0%,#FCF7FA 100%);
    border:1px solid var(--line); border-radius:14px; padding:14px 16px; margin-bottom:9px;
    box-shadow:0 6px 20px rgba(74,30,56,.05); cursor:pointer;}
  html[data-theme="dark"] .notif-row{background:rgba(255,255,255,.04); box-shadow:none;}
  .notif-row-dot{flex:none; width:8px; height:8px; border-radius:50%; margin-top:6px; background:transparent;}
  .notif-row.unread .notif-row-dot{background:var(--plum);}
  .notif-row-body{flex:1; display:flex; flex-direction:column; gap:3px;}
  .notif-row-t{font-weight:700; font-size:14px; letter-spacing:-.2px;}
  .notif-row.unread .notif-row-t{color:var(--ink);}
  .notif-row-s{font-size:13px; color:var(--ink-soft); line-height:1.45;}
  .notif-row-time{font-size:11.5px; color:var(--muted); margin-top:2px;}
  .notif-empty{text-align:center; padding:48px 20px;}
  .notif-empty-ico{width:56px; height:56px; border-radius:50%; margin:0 auto 16px; background:var(--plum-mist);
    color:var(--plum); display:flex; align-items:center; justify-content:center;}
  .notif-empty-ico svg{width:26px; height:26px;}
  .notif-empty-t{font-size:16px; font-weight:800; margin-bottom:6px;}
  .notif-empty-s{font-size:13px; color:var(--muted); line-height:1.5; max-width:260px; margin:0 auto;}

  /* ---------- Support chat ---------- */
  .chat-fab{position:fixed; right:16px; bottom:calc(84px + env(safe-area-inset-bottom)); z-index:35;
    width:54px; height:54px; border-radius:50%;
    background:var(--plum); color:#fff; border:none; box-shadow:0 6px 20px rgba(74,30,56,.4);
    display:flex; align-items:center; justify-content:center; cursor:pointer; transition:transform .15s ease, opacity .25s ease;}
  .chat-fab:active{transform:scale(.92);}
  .chat-fab svg{width:24px; height:24px;}
  .chat-fab-dot{position:absolute; top:2px; right:2px; width:12px; height:12px; border-radius:50%;
    background:#E0453C; border:2px solid var(--bg);}
  /* One-time intro bubble anchored to the FAB */
  .chat-intro{position:fixed; right:80px; bottom:calc(92px + env(safe-area-inset-bottom)); z-index:35;
    max-width:210px; background:#fff; border:1px solid var(--line); box-shadow:0 6px 20px rgba(74,30,56,.18);
    border-radius:14px; border-bottom-right-radius:4px; padding:11px 13px; font-size:12.5px; line-height:1.45;
    color:var(--ink); animation:introIn .35s ease both;}
  .chat-intro-close{position:absolute; top:5px; right:7px; width:16px; height:16px; border:none; background:none;
    color:var(--muted); font-size:14px; line-height:1; cursor:pointer; padding:0;}
  .chat-intro:after{content:""; position:absolute; right:-7px; bottom:14px; width:0; height:0;
    border-top:7px solid transparent; border-bottom:7px solid transparent; border-left:8px solid #fff;}
  @keyframes introIn{from{opacity:0; transform:translateY(6px) scale(.96);} to{opacity:1; transform:none;}}
  .chat-empty{text-align:center; padding:56px 24px; margin:auto 0;}
  .chat-empty-ico{width:60px; height:60px; border-radius:50%; margin:0 auto 16px; background:var(--plum-mist);
    color:var(--plum); display:flex; align-items:center; justify-content:center;}
  .chat-empty-ico svg{width:28px; height:28px;}
  .chat-empty-t{font-size:16px; font-weight:800; margin-bottom:6px;}
  .chat-empty-s{font-size:13px; color:var(--muted); line-height:1.5;}
  .msg-tick{display:inline-block; margin-left:5px; font-size:10px; opacity:.7; vertical-align:baseline; letter-spacing:-1px;}
  .msg-tick.read{color:#7FD1FF; opacity:1;}

  /* ---------- Product card dropdown (Products tab) ---------- */
  .pcard-wrap{margin-bottom:12px;}
  .pcard-wrap .pcard{margin-bottom:0; border-radius:var(--radius) var(--radius) 0 0;}
  .pcard-wrap:not(.open) .pcard{border-radius:var(--radius);}
  
  .pcard-wrap.open .pcard-toggle{border-radius:0; border-bottom:none;}
  
  .pcard-wrap.open .pcard-toggle svg{transform:rotate(180deg);}
  
  
  
  
  
  
  

  /* ---------- Bottom nav ---------- */
  .nav{
    position:fixed; bottom:0; left:50%; transform:translateX(-50%);
    width:100%; max-width:480px; z-index:30;
    background:rgba(255,255,255,.92); backdrop-filter:saturate(180%) blur(16px);
    border-top:1px solid rgba(74,30,56,.10);
    border-radius:20px 20px 0 0;
    box-shadow:0 -6px 22px -10px rgba(74,30,56,.28);
    display:grid; grid-template-columns:repeat(5,1fr);
    /* The safe-area inset goes below the buttons as spacing, not as padding
       inside the bar — that was leaving a large empty band under the labels. */
    padding:8px 6px 6px;
    padding-bottom:calc(6px + env(safe-area-inset-bottom));
    transition:transform .2s ease, opacity .2s ease;
  }html[data-theme="dark"] .nav{border-top-color:rgba(255,255,255,.10);}html[data-theme="dark"] .nav{background:rgba(46,33,48,.9); border-color:rgba(255,255,255,.10);}
  .nav-btn{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
    flex:1 1 0; min-width:0; width:100%;
    color:var(--muted); font-size:9.5px; font-weight:600; padding:5px 2px; transition:color .2s ease;
    text-align:center;
  }
  /* AI tab: the mascot's head is the button, lifted clear of the bar. */
  .nav-ai{position:relative;}
  .nav-ai-disc{position:absolute; left:50%; transform:translateX(-50%); bottom:20px;
    /* min/max as well as width: a wider rule on nav button children was
       stretching this to the full column width. */
    width:54px; min-width:54px; max-width:54px; height:54px; flex:none;
    border-radius:50%; display:grid; place-items:center;
    background:radial-gradient(circle at 42% 36%,#fff,#EFDCEA 62%,#D9BBD0);
    border:2px solid #fff; box-shadow:0 8px 18px rgba(74,30,56,.26);
    transition:transform .18s ease;}.nav-ai-disc img{width:38px; height:38px; object-fit:contain;}
  .nav-ai.on .nav-ai-disc{transform:translateX(-50%) translateY(-2px);
    box-shadow:0 12px 22px rgba(74,30,56,.34);}
  .nav-ai:active .nav-ai-disc{transform:translateX(-50%) scale(.94);}
  .nav-ai-lbl{position:absolute; left:50%; transform:translateX(-50%); bottom:0;
    font-size:9.5px; font-weight:700; white-space:nowrap;}
  .nav-btn span{display:block; width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}.nav-btn.on{color:var(--plum);}
  .nav-btn.on svg{stroke-width:2.2;}

  /* ---------- Modal ---------- */
  .modal-back{
    position:fixed; inset:0; background:rgba(36,30,35,.42); backdrop-filter:blur(3px);
    /* Above .ai-chatview (50) and the support chat, otherwise a sheet opened
       from inside a full-screen chat renders behind it — the registration
       prompt on the AI screen did exactly that. Still below the toast and the
       update bar (60), which must stay visible over a sheet. */
    z-index:55; display:flex; align-items:flex-end; justify-content:center;
    animation:fadeIn .22s ease;
  }
  @keyframes fadeIn{from{opacity:0;} to{opacity:1;}}
  .modal{
    background:var(--surface); width:100%; max-width:480px;
    border-radius:24px 24px 0 0; padding:14px 20px calc(24px + env(safe-area-inset-bottom));
    box-shadow:0 -14px 46px rgba(44,31,40,.28);
    animation:slideUp .3s cubic-bezier(.32,.72,0,1); max-height:88vh; max-height:88dvh; overflow-y:auto;
  }
  @keyframes slideUp{from{transform:translateY(100%);} to{transform:none;}}
  .modal-grip{width:40px; height:4px; background:var(--line); border-radius:100px; margin:0 auto 16px;}
  .modal-x{width:30px; height:30px; flex:none; border:0; border-radius:50%; background:var(--plum-soft);
    color:var(--plum); font-size:15px; display:flex; align-items:center; justify-content:center; cursor:pointer;}

  /* ---------- Forms ---------- */
  .field-label{font-size:var(--fs-sub); font-weight:600; color:var(--ink); margin-bottom:7px; display:block;}
  input{
    width:100%; height:52px; padding:0 16px; border:1.5px solid var(--line); border-radius:var(--radius-button);
    font-size:var(--fs-body); font-family:inherit; background:var(--surface); color:var(--ink);
    transition:border-color .18s ease;
  }
  input:focus{outline:none; border-color:var(--plum);}
  input::placeholder{color:#C3BCC3;}
  
  
  
  
  
  
  
  
  
  .eye-btn{display:flex; align-items:center; justify-content:center; padding:0 14px; color:var(--muted); height:50px;}
  .eye-btn:active{color:var(--plum);}

  .confirm-btn{
    width:100%; height:52px; background:linear-gradient(180deg,#6E405D,var(--plum-700) 56%,#3D2935); color:#fff;
    border-radius:var(--radius-button); padding:0 16px; box-shadow:0 6px 14px rgba(74,30,56,.24);
    font-size:var(--fs-btn); font-weight:760; display:flex; align-items:center; justify-content:center; gap:8px;
    transition:transform .15s ease;
  }
  .confirm-btn:active{transform:scale(.98);}
  
  .reg-msg{font-size:12px; color:var(--muted); text-align:center; min-height:16px; margin-bottom:12px; line-height:1.45;}
  .reg-msg.err{color:#C0392B; font-weight:600;}
  .prod-select{
    display:flex; align-items:center; gap:12px; width:100%; text-align:left;
    background:var(--surface); border:1.5px solid var(--line); border-radius:14px; padding:13px 15px;
  }
  .prod-select.on{border-color:var(--plum); background:var(--plum-mist);}
  .prod-select img{width:30px; height:30px; object-fit:contain;}

  /* ---------- Auth ---------- */
  /* Auth screens use the warmer cream background (design v2) */
  body:has(.welcome), body:has(.ig-wrap){
    background:radial-gradient(circle at 85% 8%,rgba(203,134,175,.12),transparent 30%),
               linear-gradient(180deg,var(--plum-050) 0%,var(--plum-100) 100%);
    background-attachment:fixed;
  }
  html[data-theme="dark"] body:has(.welcome), html[data-theme="dark"] body:has(.ig-wrap){
    background:radial-gradient(circle at 85% 8%,rgba(120,50,90,.28),transparent 32%),
               linear-gradient(180deg,#1F141B,#140810);
    background-attachment:fixed;
  }
  .welcome{padding-top:34px;}
  
  
  /* Welcome landing (ported) */
  .wel{display:flex; flex-direction:column; align-items:center; text-align:center; padding-bottom:24px;}
  /* Auth mode: hard-hide app chrome regardless of stale inline styles or render races */
  body.authing .nav{display:none !important;}
  body.authing .chat-fab, body.authing .chat-intro{display:none !important;}
  
  
  
  .auth-error{font-size:12.5px; color:#C0392B; font-weight:600; min-height:17px; margin:11px 0 3px; text-align:center;}
  
  

  /* ---------- FAQ ---------- */
  .faq-item{
    display:block; width:100%; text-align:left;
    background:linear-gradient(165deg,var(--surface) 0%,#FCF7FA 100%);
    border:1px solid var(--line); border-radius:14px; padding:14px 16px;
    margin-bottom:10px; cursor:pointer; font-family:inherit;
    box-shadow:0 6px 20px rgba(74,30,56,.05);
  }
  html[data-theme="dark"] .faq-item{background:rgba(255,255,255,.035); box-shadow:none;}
  .faq-q{display:flex; align-items:flex-start; gap:10px; font-size:var(--fs-body); font-weight:650; color:var(--ink); line-height:1.4;}
  .faq-chev{color:var(--plum); flex-shrink:0; transition:transform .18s ease; margin-top:1px;}
  .faq-a{
    max-height:0; overflow:hidden; opacity:0;
    font-size:12.8px; line-height:1.6; color:var(--ink-soft);
    transition:max-height .25s ease, opacity .2s ease, margin-top .2s ease;
  }
  .faq-a.open{max-height:340px; opacity:1; margin-top:10px;}

  /* ---------- Theme toggle switch ---------- */
  
  .theme-switch.on{background:var(--plum);}
  
  .theme-switch.on .theme-knob{transform:translateX(19px);}

  /* ============================================================
     DESIGN v2 COMPONENTS
     ============================================================ */

  /* ---- App bar: wordmark + slogan, bell, avatar ---- */
  .topbar-v2{
    position:sticky; top:0; z-index:20; background:var(--bg);
    padding:calc(env(safe-area-inset-top) + 14px) 20px 12px;
    display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  }.brand-block{display:flex; gap:9px; min-width:0;}
  .brand-mark{display:inline-block;}.brand-mark img{display:block;}
  .brand-mark-svg{color:var(--ink);}
  .brand-mark-svg svg{height:22px; width:auto; display:block;}
  .topbar-actions{display:flex; align-items:center; gap:12px; flex-shrink:0;}
  
  
  .lang-mini button.on{background:var(--plum); color:#fff;}
  .support-opt{display:flex; align-items:center; gap:13px; width:100%; padding:14px; margin-bottom:10px;
    background:var(--surface); border:1px solid var(--line); border-radius:14px; cursor:pointer; transition:all .15s ease;}
  .support-opt:active{transform:scale(.98);}
  .support-opt-ico{display:flex; align-items:center; justify-content:center; width:44px; height:44px; border-radius:12px; flex-shrink:0;}
  .support-opt-ico svg{width:21px; height:21px;}
  .support-opt-t{display:block; font-size:var(--fs-body); font-weight:700; color:var(--ink);}
  .support-opt-s{display:block; font-size:var(--fs-small); color:var(--muted); margin-top:2px;}
  .cert-card{display:flex; flex-direction:column; width:100%; text-align:left; padding:20px;
    background:linear-gradient(150deg,#6D2C52,#4A1E38 52%,#311425); color:#fff;
    border:none; border-radius:var(--radius-card); cursor:pointer; box-shadow:0 8px 24px rgba(74,30,56,.28); transition:transform .15s ease;}
  .cert-card:active{transform:scale(.985);}
  .cert-card-top{display:flex; align-items:center; justify-content:space-between; margin-bottom:14px;}
  
  /* progress block inside the certificate card (shared visual language with Home) */
  .cert-card .track{position:relative; height:8px; border-radius:4px; background:rgba(255,255,255,.2);
    margin:18px 30px 0 0;}
  .cert-card .track-fill{position:absolute; left:0; top:0; bottom:0; border-radius:4px;
    background:linear-gradient(90deg,#F2CBE0,#DAB4CA); transition:width .4s ease;}
  .cert-card .mk{position:absolute; top:-3px; width:14px; height:14px; border-radius:50%;
    transform:translateX(-50%); background:#4A1E38; border:2px solid rgba(255,255,255,.4);}
  .cert-card .mk.on{background:#F2CBE0; border-color:#F2CBE0; box-shadow:0 0 0 3px rgba(242,203,224,.25);}
  .cert-card .labels{position:relative; height:15px; margin-right:30px;}
  .cert-card .mk-lbl{position:absolute; top:5px; font-size:10px; font-weight:700;
    color:rgba(255,255,255,.65); white-space:nowrap; transform:translateX(-50%);}
  .cert-card .mk-lbl.on{color:#F2CBE0;}
  .cert-card .pg-txt{font-size:11.5px; margin-top:10px; opacity:.92;}
  .cert-card .pg-txt b{color:#F2CBE0;}.cert-card-cta{border:none; cursor:pointer;}
  /* Kaspi certificate info modal */
  .cinfo-lead{font-size:13px; color:var(--muted); line-height:1.6;}
  .cinfo-lead b{color:var(--ink); font-weight:750;}
  .cinfo-scroll{display:flex; gap:10px; overflow-x:auto; margin:16px -20px 0; padding:0 20px 4px;
    scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch;}
  .cinfo-card{flex:0 0 auto; width:206px; scroll-snap-align:start;}
  .cinfo-card img{width:100%; display:block; border-radius:12px;}
  .cinfo-cap{font-size:11px; font-weight:700; color:var(--ink); margin-top:7px; text-align:center;}
  .cinfo-cap span{display:block; font-weight:600; color:var(--muted); margin-top:1px;}
  .nd-time{font-size:11.5px; color:var(--muted); margin-bottom:10px;}
  .nd-body{font-size:14px; line-height:1.6; color:var(--ink); white-space:pre-wrap;}
  .cert-info{display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px;
    border-radius:50%; background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.34);
    color:#fff; padding:0; cursor:pointer; flex:none; box-sizing:content-box;}
  
  /* redeem modal: certificate rows */
  .rdrow{display:flex; align-items:center; gap:12px; width:100%; text-align:left; padding:10px;
    border-radius:14px; border:2px solid var(--line); margin-bottom:9px; background:var(--surface); cursor:pointer;}
  .rdrow.on{border-color:var(--plum); background:var(--plum-soft);}
  .rdrow.off{opacity:.45; cursor:default;}
  .rdrow img{width:84px; border-radius:8px; display:block; flex:none;}
  .rdrow.off img{opacity:.55;}
  .rdrow-body{flex:1; min-width:0;}
  .rdrow-t{display:block; font-size:14.5px; font-weight:800; color:var(--ink);}
  .rdrow-s{display:block; font-size:11px; color:var(--muted); margin-top:5px;}
  .rdrow-ok{display:flex; align-items:center; gap:4px; font-size:11.5px; font-weight:700;
    color:var(--ok); margin-top:5px;}
  .rdrow-ok svg{width:12px; height:12px;}
  .rdrow-bar{display:block; height:5px; border-radius:3px; background:var(--plum-soft);
    margin-top:6px; overflow:hidden;}
  .rdrow-fill{display:block; height:100%; border-radius:3px;
    background:linear-gradient(90deg,#B4638F,var(--plum-700));}
  .rd-phone{background:var(--surface-alt); border:1px solid var(--line); border-radius:12px;
    padding:12px 14px; margin-top:14px; font-size:12.5px; line-height:1.5; color:var(--muted);}
  .rd-phone b{color:var(--ink);}
  .rd-alt{display:inline-block; font-size:12px; font-weight:700; color:var(--plum);
    text-decoration:underline; padding:9px 0 2px; background:none; border:none; cursor:pointer;}

  /* ---- Giveaway teaser card ---- */
  .dw{display:block; width:100%; text-align:left; border:none; padding:0; margin-bottom:12px;
    border-radius:18px; overflow:hidden; cursor:pointer; background:transparent;
    box-shadow:0 12px 28px -8px rgba(74,30,56,.32);}
  .dw:active{transform:scale(.99);}
  /* artwork strip, 2.44:1 to match the 1170x480 hero from the admin panel */
  .dw-hero{position:relative; display:block; width:100%; aspect-ratio:1170/480; overflow:hidden;
    background:radial-gradient(ellipse 70% 90% at 62% 45%,#5E2142,#33132A 58%,#1E0B18);}
  .dw-hero-img{width:100%; height:100%; object-fit:cover; display:block;}
  .dw-hero-fallback{position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    padding:14px 0;}
  /* Size against the strip, not the image's intrinsic box: a percentage height
     here resolved against the wrong container and blew the image up. */
  .dw-hero-fallback img{max-height:100%; max-width:52%; width:auto; height:auto; object-fit:contain;
    filter:drop-shadow(0 12px 20px rgba(0,0,0,.5));}
  .dw-badge{position:absolute; top:12px; left:12px; font-size:9.5px; font-weight:800;
    letter-spacing:.07em; text-transform:uppercase; color:#F2D9F2;
    background:rgba(214,168,220,.3); padding:5px 11px; border-radius:100px; backdrop-filter:blur(6px);}
  /* text panel beneath, button centred */
  .dw-panel{display:flex; flex-direction:column; align-items:stretch; text-align:left;
    padding:14px 16px 16px; background:linear-gradient(160deg,#3A1730,#220D1C); color:#fff;}
  .dw-t{display:block; font-size:16px; font-weight:820; letter-spacing:-.02em; line-height:1.25;}
  .dw-s{display:block; font-size:11.5px; color:#C9A6C2; margin-top:6px; line-height:1.45;}
  .dw-cta{display:flex; align-items:center; justify-content:center; gap:6px; width:100%;
    margin-top:13px; height:42px; border-radius:100px;
    background:linear-gradient(180deg,#EBD0F0,#D6A8DC); color:#3A1230;
    font-size:13px; font-weight:850; white-space:nowrap;}
  .dw-cta svg{width:13px; height:13px;}

  /* ---- Giveaway full screen ---- */
  .dws-hero{background:radial-gradient(ellipse 90% 110% at 50% 0%,var(--plum-100),transparent 74%);
    border-radius:16px; padding:18px 0 12px; text-align:center; margin-top:6px;}
  html[data-theme="dark"] .dws-hero{background:radial-gradient(ellipse 90% 110% at 50% 0%,rgba(145,59,110,.22),transparent 74%);}
  .dws-hero img{width:168px; height:168px; object-fit:contain; filter:drop-shadow(0 14px 22px rgba(74,30,56,.2));}
  /* An uploaded 1170x480 banner is not a product cut-out: show it full width at
     its own ratio instead of squeezing it into a 168px square. */
  .dws-hero.wide{padding:0; border-radius:16px; overflow:hidden; background:none;}
  .dws-hero.wide img{width:100%; height:auto; aspect-ratio:1170/480; object-fit:cover;
    border-radius:16px; filter:none; box-shadow:0 10px 26px -8px rgba(74,30,56,.35);}
  .dws-k{font-size:10px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; color:var(--muted); text-align:center; margin-top:14px;}
  .dws-t{font-size:20px; font-weight:820; letter-spacing:-.02em; color:var(--ink); text-align:center; margin-top:4px;}
  .dws-endslbl{font-size:11px; font-weight:700; color:var(--muted); text-align:center; margin-top:14px; text-transform:uppercase; letter-spacing:.06em;}
  .dws-timer{display:flex; gap:8px; justify-content:center; margin-top:8px;}
  .dws-cell{background:var(--plum-soft); border-radius:10px; padding:8px 13px; text-align:center; min-width:52px;}
  .dws-cell b{display:block; font-size:17px; font-weight:820; color:var(--plum); line-height:1;}
  .dws-cell i{display:block; font-style:normal; font-size:9.5px; color:var(--muted); margin-top:3px;}
  .dws-over{text-align:center; font-size:12.5px; color:var(--muted); background:var(--surface-alt);
    border:1px solid var(--line); border-radius:12px; padding:12px 14px; margin-top:8px;}
  .dws-box{background:var(--surface); border:1px solid var(--line); border-radius:14px; padding:14px; margin-top:16px;}
  .dws-row{display:flex; justify-content:space-between; font-size:13px; padding:7px 0; border-bottom:1px solid var(--line);}
  .dws-row:last-of-type{border-bottom:none;}
  .dws-row span{color:var(--muted);} .dws-row b{color:var(--ink); font-weight:750;}
  .dws-ticks{display:flex; gap:5px; margin-top:10px;}
  .dws-tk{flex:1; height:7px; border-radius:4px; background:var(--plum-soft);}
  .dws-tk.on{background:linear-gradient(90deg,#B4638F,var(--plum-700));}
  .dws-rules-t{font-size:12px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--muted); margin:18px 0 8px;}
  .dws-rules{font-size:12.5px; color:var(--muted); line-height:1.6; padding-left:18px;}
  .dws-rules li{margin-bottom:6px;}
  .dws-cta{display:flex; align-items:center; justify-content:center; width:100%; height:50px; border-radius:12px;
    margin-top:18px; border:none; background:linear-gradient(180deg,#6E405D,var(--plum-700) 56%,#3D2935);
    color:#fff; font-size:14.5px; font-weight:780; cursor:pointer;}
  .dws-cta:disabled{opacity:.5; cursor:default;}
  .dws-note{display:flex; align-items:center; justify-content:center; gap:6px; margin-top:18px; height:50px;
    border-radius:12px; background:var(--ok-bg); color:var(--ok); font-size:13.5px; font-weight:750;}
  .cert-info:active{background:rgba(255,255,255,.26);}
  
  
  
  
  .cert-card-cta{margin-top:16px; align-self:stretch; text-align:center;
    background:linear-gradient(180deg,#FCE9A8,#F1C24C 50%,#DFA02A); color:#5A2A10;
    font-size:var(--fs-btn); font-weight:750; padding:0 18px; height:40px; line-height:40px; border-radius:999px;}
  .bell-btn{position:relative; color:var(--plum); display:flex;}
  .bell-dot{position:absolute; top:-1px; right:-1px; width:8px; height:8px; border-radius:50%;
    background:#E0453C; border:1.5px solid var(--bg);}
  .avatar-btn{width:40px; height:40px; border-radius:50%; background:var(--plum-soft);
    color:var(--plum); display:flex; align-items:center; justify-content:center;
    font-weight:800; font-size:15px; flex-shrink:0;}

  /* ---- Page heading ---- */
  .ptitle{font-size:var(--fs-h1); font-weight:820; letter-spacing:-.025em; line-height:1.1; margin-bottom:6px; color:var(--ink);}
  .psub{font-size:var(--fs-sub); color:var(--muted); line-height:1.5; margin:4px 0 16px;}
  /* Home greeting (ported) */
  .greet-eyebrow{color:var(--plum); font-size:var(--fs-body); font-weight:500; margin-bottom:1px;}
  html[data-theme="dark"] .greet-eyebrow{color:#CB86AF;}
  .greet-h1{color:var(--ink); font-size:var(--fs-h1); font-weight:820; letter-spacing:-.025em;}
  .greet-sub{color:var(--muted); font-size:var(--fs-sub); margin-top:4px; margin-bottom:16px;}

  /* ---- Balance card v3 (approved: progress + tiers, coins overflow top) ---- */
  
  
  
  
  
  
  
  
  
  
  .pg-txt{font-size:11.5px; margin-top:9px; opacity:.92;}
  .pg-txt b{color:#F2CBE0;}
  .tiers{display:flex; gap:6px; margin-top:12px;}
  .tier{flex:1; text-align:center; font-size:10.5px; font-weight:700; padding:6px 0; border-radius:8px;
    background:rgba(255,255,255,.12); color:rgba(255,255,255,.7); border:1px solid transparent;}
  .tier.on{background:rgba(240,203,224,.2); color:#F2CBE0; border-color:rgba(240,203,224,.55);}

  /* ---- Balance card ---- */
  .balance{
    position:relative; overflow:hidden; border-radius:var(--radius-card); padding:20px;
    background:linear-gradient(158deg,#5E2142 0%,var(--plum) 48%,#2A0C1B 100%);
    color:#fff; box-shadow:0 16px 34px -10px rgba(74,30,56,.5); margin-bottom:16px;
  }
  .balance::after{content:""; position:absolute; right:-62px; top:-44px; width:210px; height:210px;
    border-radius:50%; border:1px solid rgba(255,255,255,.10); box-shadow:0 0 0 22px rgba(255,255,255,.045);}

  /* ---- Quick actions ---- */
  

  /* ---- Section header ---- */
  .sec-head{display:flex; align-items:center; justify-content:space-between; margin:24px 0 12px;}
  .sec-h{font-size:var(--fs-h2); font-weight:790; letter-spacing:-.01em; color:var(--ink);}
  .sec-more{font-size:var(--fs-sub); font-weight:600; color:var(--plum); display:flex; align-items:center; gap:2px;}
  html[data-theme="dark"] .sec-more{color:#CB86AF;}

  /* ---- Quick bonus grid (ported) ---- */
  .qgrid{display:grid; grid-template-columns:1fr 1fr; gap:10px;}
  .qcard{display:flex; flex-direction:column; align-items:flex-start; text-align:left; padding:14px;
    position:relative; overflow:hidden; min-height:104px; border:1px solid var(--line); border-radius:14px;
    background:linear-gradient(135deg,var(--surface),#F8EFF5); box-shadow:0 5px 17px rgba(75,52,66,.05); cursor:pointer;}
  html[data-theme="dark"] .qcard{background:linear-gradient(135deg,rgba(255,255,255,.05),rgba(255,255,255,.02));}
  .qcard h3{font-size:var(--fs-body); font-weight:750; color:var(--ink);}
  .qcard p{font-size:var(--fs-small); color:var(--muted); margin:4px 0 10px; line-height:1.35;}
  .qcard .qlink{margin-top:auto; color:var(--plum); font-size:var(--fs-small); font-weight:750;}
  html[data-theme="dark"] .qcard .qlink{color:#E9C9DC;}

  /* ---- Product card v3: Tech Spec (approved) ---- */
  .ts{position:relative; width:100%; text-align:left; background:var(--surface); border:1px solid var(--line);
    border-radius:var(--radius-card); padding:16px 16px 14px 20px; overflow:hidden;
    box-shadow:0 7px 22px rgba(74,30,56,.06); cursor:pointer; margin-bottom:0;}
  .ts::before{content:""; position:absolute; left:0; top:0; bottom:0; width:4px;
    background:linear-gradient(180deg,#B4638F,var(--plum-700));}
  .ts.warnrail::before{background:linear-gradient(180deg,#E8A562,#C2662F);}
  .ts.exprail::before{background:var(--line);}
  .ts-top{display:flex; gap:12px;}
  .ts-body{flex:1; min-width:0;}
  .ts-kind{font-size:15.5px; font-weight:800; letter-spacing:-.25px; color:var(--ink);}
  /* Изображение крупнее прежнего, но не уходит за край: оно центрируется в
     свободном месте между текстом и правой границей карточки. Правый padding
     карточки восстановлен, отрицательного отступа справа нет. */
  .ts-img{width:150px; height:132px; flex:none; margin:-6px 0 -10px 0;}
  .ts-img img{width:100%; height:100%; object-fit:contain; object-position:center center;
    filter:drop-shadow(0 14px 22px rgba(0,0,0,.42));}
  .ts.expired .ts-img img{filter:grayscale(.5) opacity(.75);}
  .ts-specs{margin-top:10px; border-top:1px solid var(--line);}
  .ts-row{display:flex; justify-content:space-between; align-items:center; gap:8px; padding:7px 0; border-bottom:1px solid var(--line);}
  .ts-row:last-child{border-bottom:none;}
  .ts-k{font-size:9.5px; font-weight:800; letter-spacing:.12em; color:var(--muted); text-transform:uppercase; flex:none;}
  .ts-v{font-size:12.5px; font-weight:700; color:var(--ink); font-variant-numeric:tabular-nums; text-align:right;}
  .ts-v.ok{color:var(--ok);} .ts-v.warn{color:var(--warn);} .ts-v.mut{color:var(--muted);}
  .ts-extend{display:flex; align-items:center; justify-content:center; width:100%; height:38px; margin-top:11px;
    border:1.5px solid var(--plum-200); border-radius:10px; color:var(--plum); font-size:12.5px; font-weight:750; background:transparent;}
  html[data-theme="dark"] .ts-extend{border-color:var(--plum-600);}
  .pcard-wrap .ts{border-radius:var(--radius-card) var(--radius-card) 0 0;}

  /* ---- Product card v2 ---- */
  
  .pstatus.warn{color:var(--warn);}
  .wbar-fill.warn{background:var(--warn);}

  /* ---- Dashed add card ---- */
  .addcard{display:flex; align-items:center; gap:14px; padding:18px; border-radius:var(--radius);
    border:1.5px dashed var(--line); background:transparent; margin-bottom:13px; width:100%; text-align:left;}
  .addcard-circle{width:44px; height:44px; border-radius:50%; background:var(--plum); color:#fff;
    display:flex; align-items:center; justify-content:center; flex-shrink:0;}
  .addcard-t{font-size:14.5px; font-weight:800; letter-spacing:-.3px;}
  .addcard-s{font-size:11.5px; color:var(--ink-soft); line-height:1.45; margin-top:3px;}

  /* ---- Info banner ---- */
  .infobanner{display:flex; align-items:center; gap:13px; background:var(--surface);
    border:1px solid var(--line); border-radius:var(--radius); padding:15px;}
  .infobanner-ico{width:44px; height:44px; border-radius:50%; background:var(--plum-soft); color:var(--plum);
    display:flex; align-items:center; justify-content:center; flex-shrink:0;}
  .infobanner-t{font-size:14px; font-weight:800; letter-spacing:-.3px;}
  .infobanner-s{font-size:11.5px; color:var(--ink-soft); line-height:1.45; margin-top:3px;}

  /* ---- Menu list ---- */
  .mlist{margin-top:16px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-card); overflow:hidden;}
  .mrow{display:flex; align-items:center; gap:14px; padding:0 18px; min-height:56px; width:100%; text-align:left;
    border-bottom:1px solid var(--line);}
  .mrow:last-child{border-bottom:none;}
  .mrow-ico{width:22px; height:22px; color:var(--plum); display:grid; place-items:center; flex-shrink:0;}
  .mrow-lbl{flex:1; font-size:var(--fs-body); font-weight:600; color:var(--ink);}
  .mrow-val{font-size:var(--fs-sub); color:var(--muted);}

  /* ---- Profile header card ---- */
  .profcard{display:flex; align-items:center; gap:14px; background:var(--surface);
    border:1px solid var(--line); border-radius:var(--radius-card); padding:18px; margin-bottom:13px; width:100%; text-align:left;
    box-shadow:0 7px 22px rgba(74,30,56,.06);}
  .profcard-av{width:56px; height:56px; border-radius:50%;
    background:linear-gradient(150deg,#6E405D,var(--plum) 60%,#2A0C1B); color:#fff;
    display:flex; align-items:center; justify-content:center; font-size:24px; font-weight:800; flex-shrink:0;}
  .profcard-name{font-size:var(--fs-h2); font-weight:780; letter-spacing:-.3px; margin-bottom:4px; color:var(--ink);}
  .profcard-row{display:flex; align-items:center; gap:6px; font-size:var(--fs-sub); color:var(--muted); margin-top:4px;}
  .consent-box{
    appearance:none; -webkit-appearance:none; margin-top:1px;
    /* Pin every axis: inside a flex row the box was being stretched wider than
       it is tall, so it read as a rectangle rather than a square. */
    width:21px; min-width:21px; max-width:21px;
    height:21px; min-height:21px; max-height:21px;
    flex:0 0 21px; box-sizing:border-box; align-self:flex-start;
    /* The global input rule adds horizontal padding, which with border-box
       forced this to 34px wide. Zero it so the box stays square. */
    padding:0;
    border:1.8px solid var(--line); border-radius:6px; background:var(--surface); position:relative;
    transition:background .15s ease, border-color .15s ease;
  }
  .consent-box:checked{background:var(--plum); border-color:var(--plum);}
  .consent-box:checked::after{
    content:""; position:absolute; left:6.5px; top:2.5px; width:5px; height:10px;
    border:solid #fff; border-width:0 2.2px 2.2px 0; transform:rotate(45deg);
  }
  .ig-install{display:flex; align-items:center; justify-content:center; gap:9px; width:100%;
    height:54px; border-radius:16px; border:none; cursor:pointer; margin-bottom:8px;
    background:linear-gradient(180deg,#6E405D,var(--plum-700) 58%,#3D2935); color:#fff;
    font-size:15.5px; font-weight:820; letter-spacing:-.01em;
    box-shadow:0 10px 24px -8px rgba(74,30,56,.42);}
  .ig-install:active{transform:scale(.985)}
  .ig-install:disabled{opacity:.6}
  .ig-oneline{font-size:12px; color:var(--muted); text-align:center; margin-bottom:16px;}
  .ig-tab.active{background:var(--surface); border-color:var(--plum); color:var(--ink);}
  /* removed: stale rule from the previous gate — it forced the step visual
     alongside the text instead of beneath it */
  
  
  

  /* ---------- Toast ---------- */
  .toast{
    position:fixed; bottom:calc(104px + env(safe-area-inset-bottom)); left:50%; transform:translateX(-50%);
    background:var(--ink); color:#fff; padding:13px 20px; border-radius:100px;
    font-size:13px; font-weight:600; z-index:60; animation:toastIn .3s cubic-bezier(.32,.72,0,1);
    box-shadow:0 8px 30px rgba(36,30,35,.22); white-space:nowrap; max-width:90vw; overflow:hidden; text-overflow:ellipsis;
  }
  @keyframes toastIn{from{opacity:0; transform:translate(-50%,14px);} to{opacity:1; transform:translate(-50%,0);}}.ai-change{flex-shrink:0; font-family:inherit;}
/* Chat view: fixed overlay, sized to the visual viewport by JS so the input hugs the keyboard */
.ai-chatview{position:fixed;inset:0;display:flex;flex-direction:column;background:var(--bg);z-index:50;overscroll-behavior:contain;}
body.chat-active{padding-bottom:0 !important;overflow:hidden;}
.ai-chat-head{flex-shrink:0;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:calc(14px + env(safe-area-inset-top)) 18px 12px;border-bottom:1px solid var(--line);background:var(--bg)}
.ai-chat-title{font-size:var(--fs-title);font-weight:780;color:var(--ink)}
.ai-back{flex-shrink:0;background:none;border:none;padding:4px;margin:-4px 2px -4px -4px;cursor:pointer;color:var(--plum);display:flex;align-items:center}
.ai-change{border:0;background:var(--plum-soft);color:var(--plum);font-size:var(--fs-small);font-weight:700;padding:7px 12px;border-radius:999px;cursor:pointer}
.ai-thread{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:14px 18px 6px;display:flex;flex-direction:column;gap:10px}
.ai-row{display:flex}
.ai-user{justify-content:flex-end}
.ai-bot{justify-content:flex-start}
.ai-bubble{max-width:86%;padding:11px 14px;border-radius:16px;font-size:var(--fs-body);line-height:1.5;white-space:normal;word-wrap:break-word}
.ai-b-user{background:linear-gradient(160deg,#6E405D,var(--plum-700));color:#fff;border-top-right-radius:5px}
.ai-b-bot{background:var(--surface);color:var(--ink);border:1px solid var(--line);border-top-left-radius:5px}.ai-typing{color:var(--muted);}
.ai-typing{display:inline-flex;align-items:center;gap:4px;font-style:normal}
.ai-dot{width:7px;height:7px;border-radius:50%;background:var(--plum-accent);opacity:.4;animation:aiDot 1.2s infinite ease-in-out}
.ai-dot:nth-child(2){animation-delay:.2s}
.ai-dot:nth-child(3){animation-delay:.4s}
@keyframes aiDot{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.ai-input-bar{flex-shrink:0;display:flex;gap:8px;align-items:center;padding:8px 12px calc(8px + env(safe-area-inset-bottom));background:var(--bg);border-top:1px solid var(--line)}.ai-input{flex:1; height:46px; padding:0 18px; border-radius:999px; font-size:var(--fs-body); color:var(--ink); outline:none; font-family:inherit;}
.ai-input:focus{border-color:var(--plum-accent)}
.ai-send{flex-shrink:0;width:46px;height:46px;border-radius:50%;background:linear-gradient(160deg,#6E405D,var(--plum-700));color:#fff;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer}
.ai-send:disabled{opacity:.5}
/* ================= AI chat v2 ================= */
.ai-v2{
  background:linear-gradient(180deg,#FED8C1 0px,#FDD5C6 56px,#FBC9DD 336px,#E4D2F6 592px,#D6D2F8 800px),#D6D2F8;
}
.ai-v2 .ai-chat-head{height:56px;background:transparent;border-bottom:1px solid rgba(74,30,56,.08);gap:10px}
.ai-headav{width:34px;height:34px;flex:none;display:grid;place-items:center}
.ai-headav img{width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 2px 4px rgba(74,30,56,.2))}
.ai-v2 .ai-chat-title{flex:1;font-size:14.5px;font-weight:780;color:#3A2030}
.ai-prod{display:flex;align-items:center;gap:6px;border-radius:999px;padding:5px 9px 5px 5px;flex:none;
  background:rgba(255,252,249,.85);border:1px solid rgba(255,255,255,.9);cursor:pointer}
.ai-prod:disabled{cursor:default}
.ai-prod img{width:22px;height:22px;object-fit:contain}
.ai-prod span{font-size:11px;font-weight:700;color:#3A2030}
.ai-prod svg{width:12px;height:12px;color:#8A3F6A}

/* welcome block */
.ai-welcome{margin:-14px -14px 0}
.ai-anim{height:280px;overflow:hidden;position:relative}
.ai-anim video{width:100%;height:100%;object-fit:cover;display:block}
.ai-wcopy{padding:8px 18px 4px}
.ai-w1{font-size:15px;font-weight:800;color:#2A1622;line-height:1.35}
.ai-w2{font-size:13px;color:#5C3D52;line-height:1.55;margin-top:9px}
.ai-gate-cta{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:50px;
  border-radius:14px;margin-top:16px;border:none;cursor:pointer;font-size:14.5px;font-weight:780;
  background:linear-gradient(150deg,#B85C86,#6E2A50);color:#fff;box-shadow:0 8px 20px rgba(110,42,80,.34)}
.ai-gate-cta:active{transform:scale(.985)}
.ai-gate-cta svg{width:18px;height:18px}
.ai-gate-note{font-size:12px;color:#5C3D52;opacity:.75;text-align:center;margin-top:10px;line-height:1.45}

/* bubbles on the gradient */
.ai-v2 .ai-row.ai-bot{display:flex;gap:8px;align-items:flex-end}
.ai-av{width:30px;height:30px;flex:none;display:grid;place-items:center}
.ai-av img{width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 2px 4px rgba(74,30,56,.22))}
.ai-v2 .ai-b-bot{background:rgba(255,252,249,.9);border:1px solid rgba(255,255,255,.85);
  box-shadow:0 4px 14px rgba(90,40,80,.09);color:#2A1622}
.ai-v2 .ai-b-user{background:linear-gradient(150deg,#B85C86,#6E2A50);color:#fff;
  box-shadow:0 6px 16px rgba(110,42,80,.3)}

/* horizontal prompt row above the input */
.ai-picks{display:flex;gap:8px;overflow-x:auto;padding:10px 14px;flex:none;
  scrollbar-width:none;-webkit-overflow-scrolling:touch}
.ai-picks::-webkit-scrollbar{display:none}
/* product chooser inside the welcome screen */
.ai-pgrid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px}
.ai-pcard{display:flex;flex-direction:column;align-items:center;gap:8px;border-radius:16px;padding:14px 10px;
  cursor:pointer;background:rgba(255,255,255,.28);border:1px solid rgba(255,255,255,.55);backdrop-filter:blur(10px)}
.ai-pcard:active{transform:scale(.98)}
.ai-pcard img{width:62px;height:62px;object-fit:contain;filter:drop-shadow(0 6px 12px rgba(74,30,56,.18))}
.ai-pcard span{font-size:12.5px;font-weight:700;color:#2A1622;text-align:center;line-height:1.25}
.ai-pick{flex:0 0 auto;font-size:12.5px;font-weight:650;color:#2A1622;border-radius:999px;padding:10px 14px;
  white-space:nowrap;background:rgba(255,252,249,.9);border:1px solid rgba(255,255,255,.85);
  box-shadow:0 4px 14px rgba(90,40,80,.09);cursor:pointer}

/* input bar sits on the gradient */
.ai-v2 .ai-input-bar{background:transparent;border-top:1px solid rgba(74,30,56,.08)}
.ai-v2 .ai-input{background:rgba(255,252,249,.85);border:1px solid rgba(255,255,255,.9);color:#2A1622}
.ai-v2 .ai-clip{background:rgba(255,252,249,.8);border:1px solid rgba(255,255,255,.9);color:#8A3F6A}
.ai-v2 .ai-send{background:linear-gradient(150deg,#B85C86,#6E2A50);box-shadow:0 6px 16px rgba(110,42,80,.32)}
.ai-v2 .ai-attach{background:transparent;border-top-color:rgba(74,30,56,.06)}
.ai-v2 .ai-attach-x{background:rgba(255,252,249,.8);border:1px solid rgba(255,255,255,.9);color:#8A3F6A}
/* The welcome video is gone — the orb draws here now, and its renderer already
   honours prefers-reduced-motion itself. */
.ai-clip{flex-shrink:0;width:44px;height:44px;border-radius:50%;background:var(--surface-alt);border:1px solid var(--line);color:var(--plum);display:flex;align-items:center;justify-content:center;cursor:pointer}

/* Browsers paint autofilled inputs with a yellow background that ignores
   background-color. The only reliable override is a large inset shadow, with
   a long transition so the browser's own fade never becomes visible. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
textarea:-webkit-autofill,
select:-webkit-autofill{
  -webkit-box-shadow:0 0 0 1000px var(--bg) inset !important;
  box-shadow:0 0 0 1000px var(--bg) inset !important;
  -webkit-text-fill-color:var(--ink) !important;
  caret-color:var(--ink);
  transition:background-color 100000s ease-in-out 0s !important;
}
/* Fields that sit on a white card need the card colour, not the page colour. */
.authv-sheet input:-webkit-autofill,
.authv-sheet input:-webkit-autofill:hover,
.authv-sheet input:-webkit-autofill:focus{
  -webkit-box-shadow:0 0 0 1000px var(--bg) inset !important;
  box-shadow:0 0 0 1000px var(--bg) inset !important;
}
.card input:-webkit-autofill,
.modal input:-webkit-autofill,
.surface input:-webkit-autofill{
  -webkit-box-shadow:0 0 0 1000px var(--surface) inset !important;
  box-shadow:0 0 0 1000px var(--surface) inset !important;
}
html[data-theme="dark"] input:-webkit-autofill,
html[data-theme="dark"] textarea:-webkit-autofill,
html[data-theme="dark"] select:-webkit-autofill{
  -webkit-box-shadow:0 0 0 1000px var(--bg) inset !important;
  box-shadow:0 0 0 1000px var(--bg) inset !important;
  -webkit-text-fill-color:var(--ink) !important;
}

/* Consistent vertical rhythm on Home. Gaps were 0, 12, 16, 24 and 26px with
   the AI card touching the daily card; this makes every block sit 14px apart
   and gives section headings a little more room above. */
.home-glass > * + *{margin-top:14px;}
.home-glass > .greet-h1,
.home-glass > .greet-sub{margin-top:2px;}
.home-glass > .sec-head{margin:26px 0 0;}
.home-glass > .psub{margin:6px 0 0;}
.home-glass .bxwrap,
.home-glass .daily-card,
.home-glass .aicard{margin-bottom:0;}

/* Same material as the app's cards, so the update prompt reads as part of the
   product rather than a system warning. */
.update-bar{position:fixed; left:12px; right:12px; z-index:60;
  bottom:calc(84px + env(safe-area-inset-bottom));
  display:flex; align-items:center; gap:12px; padding:13px 13px 13px 15px;
  border-radius:18px;
  background:rgba(255,255,255,.62); border:1px solid rgba(255,255,255,.85);
  -webkit-backdrop-filter:blur(22px) saturate(190%); backdrop-filter:blur(22px) saturate(190%);
  box-shadow:0 2px 4px rgba(74,30,56,.10), 0 10px 26px -10px rgba(74,30,56,.28),
    inset 0 1px 0 rgba(255,255,255,.9);
  transform:translateY(140%); transition:transform .28s cubic-bezier(.2,.8,.2,1);}
.update-bar.in{transform:translateY(0);}
.ub-ic{width:34px; height:34px; border-radius:11px; flex:none; display:grid; place-items:center;
  background:var(--plum-soft); color:var(--plum);}
.ub-c{flex:1; min-width:0; display:flex; flex-direction:column;}
.ub-t{font-size:13px; font-weight:800; color:var(--ink); line-height:1.25;}
.ub-s{font-size:11.5px; color:var(--muted); margin-top:2px;}
.ub-btn{flex:none; border:none; cursor:pointer; font-family:inherit;
  background:linear-gradient(160deg,#6E405D,var(--plum-700)); color:#fff; border-radius:999px;
  padding:9px 15px; font-size:12.5px; font-weight:820;
  box-shadow:0 6px 16px -8px rgba(74,30,56,.5);}
.ub-btn:active{transform:scale(.97);}
html[data-theme="dark"] .update-bar{background:rgba(40,30,38,.8); border-color:rgba(255,255,255,.12);}
html[data-theme="dark"] .ub-ic{background:rgba(255,255,255,.10); color:#E9A8CE;}

/* With black-translucent the page paints behind the status bar, so the wash
   must reach the very top of the screen rather than stopping at the topbar.
   The topbar itself already pads by the safe-area inset, so nothing collides
   with the clock. */
html, body{min-height:100%;}
html.glass-bg, body.glass-bg{background-attachment:fixed;}
body.glass-bg{background-color:transparent;}
/* With the status bar back to "default" the strip is painted by iOS from the
   document background colour, so no in-page overlay is needed. */

/* Balance in the header: visible on every tab, and a shortcut to Bonuses.
   Replaces the Home balance card, which repeated a number the Bonuses tab
   already presents with progress and context. */
.lang-seg{display:flex; gap:2px; background:var(--plum-soft); border-radius:999px; padding:3px; margin-left:auto;}
.lang-seg button{border:none; cursor:pointer; font-family:inherit; font-size:11px; font-weight:800;
  padding:6px 11px; border-radius:999px; background:none; color:var(--plum); opacity:.6;}
.lang-seg button.on{background:var(--plum); color:#fff; opacity:1;}
.bal-pill{display:inline-flex; align-items:center; gap:6px; border:none; cursor:pointer;
  background:linear-gradient(160deg,#6E405D,var(--plum-700)); color:#fff;
  border-radius:999px; padding:8px 13px; font-size:13px; font-weight:820;
  font-family:inherit; font-variant-numeric:tabular-nums;
  box-shadow:0 6px 16px -8px rgba(74,30,56,.5);}
.bal-pill:active{transform:scale(.97);}
.bal-pill svg{opacity:.85; flex:none;}

/* ===================== Glass across the whole app ========================
   Every white card becomes translucent so the page wash shows through, and the
   topbar and nav do the same. Blur is kept moderate: the cost is per painted
   element, and there can be a dozen on screen at once. */
body.glass-bg .card,
body.glass-bg .ts,
body.glass-bg .pcard,
body.glass-bg .pcard-docs,
body.glass-bg .pcard-toggle,
body.glass-bg .mlist,
body.glass-bg .profcard,
body.glass-bg .quick,
body.glass-bg .rdrow,
body.glass-bg .support-opt,
body.glass-bg .home-tile,
body.glass-bg .infobanner,
body.glass-bg .earn-row,
body.glass-bg .earn-drop,
body.glass-bg .detail-hero,
body.glass-bg .pdx-head,
body.glass-bg .pdx-doc,
body.glass-bg .dws-box,
body.glass-bg .ig-step,
body.glass-bg .cat-item,
body.glass-bg .daily-card,
body.glass-bg .aicard{
  background:rgba(255,255,255,.52);
  border-color:rgba(255,255,255,.8);
  -webkit-backdrop-filter:blur(18px) saturate(180%);
  backdrop-filter:blur(18px) saturate(180%);
  box-shadow:0 8px 24px -14px rgba(74,30,56,.24), inset 0 1px 0 rgba(255,255,255,.6);
}
/* The bars sit over scrolling content, so they get a stronger blur and stay
   translucent enough for the wash to read through them. */
body.glass-bg .topbar{
  background:rgba(255,255,255,.62);
  -webkit-backdrop-filter:blur(22px) saturate(190%);
  backdrop-filter:blur(22px) saturate(190%);
  border-bottom:1px solid rgba(255,255,255,.55);
}
body.glass-bg .nav{
  background:rgba(255,255,255,.62);
  -webkit-backdrop-filter:blur(22px) saturate(190%);
  backdrop-filter:blur(22px) saturate(190%);
  border-top:1px solid rgba(255,255,255,.55);
}
/* Fields and modals need more opacity to stay readable. */
body.glass-bg .modal,
body.glass-bg .field-wrap,
body.glass-bg .phone-field,
body.glass-bg .pass-field,
body.glass-bg .prod-select{
  background:rgba(255,255,255,.82);
  -webkit-backdrop-filter:blur(18px) saturate(170%);
  backdrop-filter:blur(18px) saturate(170%);
}
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] body.glass-bg .nav{
  background:rgba(46,33,48,.66);
  border-color:rgba(255,255,255,.10);
}
@media (prefers-reduced-transparency: reduce){
  body.glass-bg .card, body.glass-bg .ts, body.glass-bg .pcard,
  body.glass-bg .topbar, body.glass-bg .nav{
    background:var(--surface); -webkit-backdrop-filter:none; backdrop-filter:none;
  }
}

/* ============================== Glass on Home ============================
   Cards become translucent and blur what passes behind them. This only reads
   as glass if there is something behind to blur, so the Home screen gets a
   soft gradient wash instead of the flat page colour.
   Scoped to Home: applying it everywhere would cost GPU on every scroll. */
html.glass-bg,
body.glass-bg{
  background:
    radial-gradient(ellipse 120% 60% at 82% -4%, rgba(248,196,221,.55), transparent 60%),
    radial-gradient(ellipse 110% 55% at 6% 34%, rgba(214,210,248,.45), transparent 62%),
    radial-gradient(ellipse 130% 60% at 60% 104%, rgba(252,217,192,.45), transparent 62%),
    linear-gradient(168deg,#FCE7DC 0%,#F6DCEA 34%,#EADFF6 68%,#F1E9EF 100%);
  background-attachment:fixed;
}
.home-glass{position:relative;}
/* One shared recipe so every card matches. */
.home-glass .glass{
  background:rgba(255,255,255,.46);
  border:1px solid rgba(255,255,255,.85);
  -webkit-backdrop-filter:blur(24px) saturate(190%);
  backdrop-filter:blur(24px) saturate(190%);
  box-shadow:0 10px 30px -14px rgba(74,30,56,.26), inset 0 1px 0 rgba(255,255,255,.7);
}
/* The balance card stays plum but gains the same depth. */
.home-glass .bx{
  background:linear-gradient(150deg,rgba(109,44,82,.88),rgba(74,30,56,.9) 52%,rgba(49,20,37,.92));
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%);
  border:1px solid rgba(255,255,255,.14);
  box-shadow:0 14px 34px -16px rgba(49,20,37,.6), inset 0 1px 0 rgba(255,255,255,.16);
}
/* Text on glass needs a touch more weight to hold contrast. Scoped to the light
   theme: these are dark values, and applying them in dark mode dropped section
   headings to 1.2:1 — effectively invisible. */
html:not([data-theme="dark"]) .home-glass .sec-h{color:#2A1622;}
html:not([data-theme="dark"]) .home-glass .psub,
html:not([data-theme="dark"]) .home-glass .greet-sub{color:#6B5460;}
html[data-theme="dark"] .home-glass .sec-h{color:var(--ink);}
html[data-theme="dark"] .home-glass .psub,
html[data-theme="dark"] .home-glass .greet-sub{color:var(--ink-soft);}
/* Glass over a dark page is a different recipe: lift rather than tint. */
html[data-theme="dark"].glass-bg,
html[data-theme="dark"] body.glass-bg{
  background:
    radial-gradient(ellipse 120% 60% at 82% -4%, rgba(142,88,122,.55), transparent 62%),
    radial-gradient(ellipse 110% 55% at 6% 34%, rgba(86,76,128,.48), transparent 64%),
    linear-gradient(168deg,#372838 0%,#2E2130 60%,#271C28 100%);
}
html[data-theme="dark"] .home-glass .glass{
  background:rgba(255,255,255,.07);
  border-color:rgba(255,255,255,.12);
  box-shadow:0 10px 30px -14px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.08);
}
/* Respect users who ask for less motion/effects, and older devices where the
   blur is expensive: fall back to a solid surface. */
@media (prefers-reduced-transparency: reduce){
  .home-glass .glass{background:var(--surface); -webkit-backdrop-filter:none; backdrop-filter:none;}
}

/* ========================= QR landing (install gate) ===================== */
.ig-v2{min-height:100dvh; background:var(--bg);}
.ig-car{position:relative; height:420px; overflow:hidden; background:#2A0F22;}
.ig-car-img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
.ig-car-scrim{position:absolute; inset:0;
  background:linear-gradient(180deg,rgba(20,8,16,.34) 0%,rgba(20,8,16,.10) 34%,
    rgba(20,8,16,.72) 76%,rgba(20,8,16,.94) 100%),
    linear-gradient(165deg,#5E2445 0%,#3E1730 55%,#2A0F22 100%);
  background-blend-mode:normal;}
.ig-car-img + .ig-car-scrim{background:linear-gradient(180deg,rgba(20,8,16,.34) 0%,rgba(20,8,16,.10) 34%,
    rgba(20,8,16,.72) 76%,rgba(20,8,16,.94) 100%);}
.ig-car-cap{position:absolute; left:0; right:0; bottom:38px; z-index:3; text-align:center; padding:0 26px; color:#fff;}
.ig-car-cap h2{font-size:23px; font-weight:840; letter-spacing:-.02em; line-height:1.2;
  text-shadow:0 2px 14px rgba(0,0,0,.45);}
.ig-car-cap p{font-size:13.5px; line-height:1.5; color:#E7D3E0; margin-top:8px; text-shadow:0 1px 10px rgba(0,0,0,.4);}
.ig-car-dots{position:absolute; left:0; right:0; bottom:16px; z-index:4; display:flex; gap:6px; justify-content:center;}
.ig-car-dots i{width:22px; height:3px; border-radius:2px; background:rgba(255,255,255,.34); cursor:pointer;}
.ig-car-dots i.on{background:#fff; width:26px;}
.ig-car-arrow{position:absolute; top:46%; z-index:5; width:34px; height:34px; border-radius:50%; border:none;
  background:rgba(0,0,0,.3); color:#fff; display:grid; place-items:center; backdrop-filter:blur(6px); cursor:pointer;}
.ig-car-arrow.l{left:10px} .ig-car-arrow.r{right:10px}
.ig-body{padding:18px 18px calc(24px + env(safe-area-inset-bottom));}
.ig-hd{font-size:11.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--muted);
  margin-bottom:12px; display:flex; align-items:center; gap:6px;}
.ig-hd svg{width:13px; height:13px;}
.ig-step{background:var(--surface); border:1px solid var(--line); border-radius:16px; padding:14px; margin-bottom:10px;}
.ig-step-h{display:flex; align-items:center; gap:10px;}
.ig-step-n{width:24px; height:24px; border-radius:8px; background:var(--plum-soft); color:var(--plum);
  font-size:11.5px; font-weight:820; display:grid; place-items:center; flex:none;}
.ig-step-t{font-size:13.5px; font-weight:750; color:var(--ink); line-height:1.35;}
.ig-step-v{margin-top:11px;}
.ig-safbar{background:linear-gradient(180deg,#F2EFED,#E6E1DE); border-radius:12px; padding:9px 11px;
  display:flex; align-items:center; gap:11px; border:1px solid rgba(0,0,0,.07);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7);}
.ig-safbar .u{flex:1; background:#fff; border-radius:8px; height:26px; box-shadow:0 1px 2px rgba(0,0,0,.06);}
.ig-safbar .sh{color:#1C7CF5; position:relative; display:grid; place-items:center; width:30px; height:30px;}
.ig-safbar .ring{position:absolute; inset:0; border:2px solid #1C7CF5; border-radius:50%;
  animation:igPulse 1.8s ease-out infinite;}
@keyframes igPulse{0%{transform:scale(.85);opacity:.9}70%{transform:scale(1.35);opacity:0}100%{opacity:0}}
.ig-sheet{background:#fff; border:1px solid var(--line); border-radius:12px; overflow:hidden;
  box-shadow:0 6px 18px -8px rgba(74,30,56,.2);}
.ig-sheet .row{display:flex; align-items:center; gap:9px; font-size:12px; color:#6B6B6B; padding:9px 12px;
  border-bottom:1px solid #F2EEEC;}
.ig-sheet .row:last-child{border-bottom:none;}
.ig-sheet .row.hl{background:linear-gradient(90deg,var(--plum-soft),rgba(233,168,206,.18));
  color:var(--plum); font-weight:800; position:relative;}
.ig-sheet .row.hl:before{content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--plum);}
.ig-home{background:linear-gradient(160deg,#EDE3EA,#E2D3DF); border-radius:12px; padding:13px;
  display:flex; gap:12px; align-items:center;}
.ig-home .ic{width:46px; height:46px; border-radius:11px; background:var(--plum-700); display:grid;
  place-items:center; flex:none; box-shadow:0 4px 10px rgba(74,30,56,.3); overflow:hidden;}
.ig-home .ic img{width:100%; height:100%; object-fit:contain;}
.ig-home .tx{font-size:12.5px; color:#4A3442; line-height:1.45;}
.ig-note{font-size:11.5px; color:var(--muted); text-align:center; margin-top:14px; line-height:1.5;}

/* ============================ Auth screens v2 ============================ */
.authv{position:fixed; inset:0; overflow-y:auto; overflow-x:hidden; overscroll-behavior-x:none;
  -webkit-overflow-scrolling:touch;
  display:flex; flex-direction:column;
  background:linear-gradient(168deg,#5E2445 0%,#431935 52%,#2E1226 100%);}
/* The sheet must reach the bottom of the screen; otherwise the plum stage
   shows as a strip beneath it on shorter forms. */
.authv-sheet:last-child{margin-bottom:0;}
.authv-bg{position:absolute; inset:0; overflow:hidden; pointer-events:none; z-index:0;}
.ab{position:absolute; border-radius:50%; background:rgba(255,255,255,.055); pointer-events:none;}
.ab.b1{width:300px; height:300px; top:-90px; right:-110px;}
.ab.b2{width:150px; height:150px; top:120px; left:-60px;}
.ab.b3{width:80px; height:80px; top:250px; right:44px; background:rgba(255,255,255,.075);}
.ab.b4{width:44px; height:44px; top:90px; left:150px; background:rgba(255,255,255,.09);}
.ab.b5{width:190px; height:190px; bottom:210px; left:-70px; background:rgba(233,168,206,.07);}
.ab-wave{position:absolute; left:0; right:0; bottom:0; height:150px; background:rgba(255,255,255,.05);
  border-radius:52% 48% 0 0/100% 100% 0 0; pointer-events:none;}
.authv-top{position:relative; z-index:3; display:flex; align-items:center; justify-content:space-between;
  padding:calc(18px + env(safe-area-inset-top)) 20px 0;}
.authv-mark svg{width:96px; height:auto; color:#fff;}
.authv-back{background:none; border:none; color:#fff; display:flex; padding:6px; cursor:pointer;}
.authv-lang{display:flex; gap:2px; background:rgba(255,255,255,.16); border-radius:999px; padding:3px;}
.authv-lang button{border:none; background:none; font-size:11.5px; font-weight:700; color:#fff;
  padding:5px 11px; border-radius:999px; cursor:pointer; opacity:.8; font-family:inherit;}
.authv-lang button.on{background:#fff; color:var(--plum); opacity:1; font-weight:750;}
/* welcome */
.authv-hero{position:relative; z-index:3; min-height:calc(100dvh - 90px); display:flex; flex-direction:column;
  justify-content:flex-end; padding:0 24px calc(28px + env(safe-area-inset-bottom)); color:#fff;}
.authv-h1{font-size:30px; font-weight:860; letter-spacing:-.035em; line-height:1.1;}
.authv-h1 em{font-style:normal; color:#E9A8CE;}
.authv-lede{font-size:14px; color:#D2B6C6; line-height:1.55; margin-top:12px; max-width:300px;}
.authv-btns{margin-top:26px;}
.authv-solid{display:flex; align-items:center; justify-content:center; width:100%; height:52px; border:none;
  border-radius:14px; background:#fff; color:var(--plum); font-size:15px; font-weight:820; cursor:pointer;
  box-shadow:0 10px 22px -12px rgba(0,0,0,.5); font-family:inherit;}
.authv-outline{display:flex; align-items:center; justify-content:center; width:100%; height:52px; margin-top:11px;
  border-radius:14px; border:1.5px solid rgba(255,255,255,.5); background:none; color:#fff;
  font-size:15px; font-weight:780; cursor:pointer; font-family:inherit;}
.authv-solid:active,.authv-outline:active{transform:scale(.99);}
/* form screens */
.authv-title{position:relative; z-index:3; padding:24px 24px 0; color:#fff;}
.authv-title h1{font-size:28px; font-weight:860; letter-spacing:-.03em; line-height:1.14;}
.authv-title p{font-size:13.5px; color:#D2B6C6; margin-top:8px; line-height:1.5;}
.authv-title p b{color:#fff;}
.authv-sheet{position:relative; z-index:4; margin-top:26px; flex:1 0 auto; background:var(--bg);
  border-radius:44px 44px 0 0; padding:28px 24px calc(28px + env(safe-area-inset-bottom));}
.authv-fld{display:flex; align-items:center; gap:11px; border-bottom:1.5px solid var(--line); padding:12px 2px;}
.authv-fld + .authv-fld{margin-top:6px;}
.authv-ic{color:var(--plum); opacity:.65; flex:none; display:grid; place-items:center;}
.authv-pf{font-size:15px; font-weight:700; color:var(--ink); flex:none;}
.authv-fld input{flex:1; min-width:0; border:none; background:none; font-size:15px; color:var(--ink);
  outline:none; padding:0; font-family:inherit; font-weight:700;}
/* The placeholder should stay light — only real input matches the +7 prefix. */
.authv-fld input::placeholder{font-weight:600;}
.authv-fld input::placeholder{color:#B5A3AE;}
.authv-eye{background:none; border:none; color:var(--muted); flex:none; padding:4px; cursor:pointer;}
.authv-forgot{display:block; text-align:right; font-size:12.5px; font-weight:700; color:var(--plum);
  margin-top:12px; cursor:pointer;}
.authv-primary{display:flex; align-items:center; justify-content:center; width:100%; height:52px; border:none;
  border-radius:14px; margin-top:18px; cursor:pointer; font-family:inherit;
  background:linear-gradient(180deg,#6E405D,var(--plum-700) 58%,#3D2935); color:#fff;
  font-size:15px; font-weight:820; box-shadow:0 10px 22px -10px rgba(74,30,56,.45);}
.authv-primary:disabled{opacity:.45; box-shadow:none;}
.authv-or{display:flex; align-items:center; gap:12px; margin:16px 0; color:var(--muted); font-size:12px;}
.authv-or:before,.authv-or:after{content:""; flex:1; height:1px; background:var(--line);}
.authv-second{display:flex; align-items:center; justify-content:center; width:100%; height:50px;
  border-radius:14px; border:1.5px solid var(--line); background:none; color:var(--ink);
  font-size:14.5px; font-weight:760; cursor:pointer; font-family:inherit;}
.authv-consent{display:flex; gap:10px; align-items:flex-start; margin-top:16px; font-size:12.5px;
  color:var(--muted); line-height:1.45;}
.authv-consent a{color:var(--plum); font-weight:700;}
/* OTP */
.otp-note{background:linear-gradient(160deg,#6E405D,var(--plum-700)); border-radius:16px; padding:17px;
  color:#fff; box-shadow:0 10px 22px -12px rgba(74,30,56,.5);}
.otp-note-h{display:flex; align-items:center; gap:10px; font-size:16px; font-weight:820; line-height:1.25;}
.otp-note-ic{width:38px; height:38px; border-radius:11px; background:rgba(255,255,255,.18);
  display:grid; place-items:center; flex:none;}
.otp-note-ic svg{width:20px; height:20px;}
.otp-note-s{font-size:14px; color:#EBD5E2; margin-top:10px; line-height:1.5;}
.otp-note-c{font-size:12.5px; font-weight:750; color:#F3D9E9; margin-top:12px;
  padding-top:11px; border-top:1px solid rgba(255,255,255,.16);}
.otp-note-s b{color:#fff; font-weight:800;}
.otp-cells{position:relative; display:flex; gap:10px; justify-content:center; margin-top:22px;}
.otp-cell{width:60px; height:66px; border-radius:14px; background:var(--surface); border:1.5px solid var(--line);
  display:grid; place-items:center; font-size:26px; font-weight:820; color:var(--ink);}
.otp-cell.on{border-color:var(--plum); box-shadow:0 0 0 3px rgba(74,30,56,.09);}
.otp-hidden{position:absolute; inset:0; width:100%; height:100%; opacity:0; border:none; background:none;
  font-size:16px; letter-spacing:2em; color:transparent; caret-color:transparent; cursor:pointer;}
.authv-resend{display:flex; align-items:center; justify-content:center; width:100%; height:46px;
  margin-top:14px; border:none; background:none; color:var(--plum); font-size:13.5px; font-weight:700;
  cursor:pointer; font-family:inherit;}
.authv-resend:disabled{color:var(--muted); font-weight:600;}
.ai-clip:disabled{opacity:.45}
/* ---- Voice notes ---- */
.ai-mic{margin-left:2px; touch-action:none; user-select:none; -webkit-user-select:none;
  transition:transform .1s linear, width .16s ease, height .16s ease, background .18s ease;}
/* While recording the bar keeps every element in place — only their visibility
   changes. Replacing the bar would destroy the button being held, which broke
   both the slide gesture and release-to-send. */
.ai-input-bar .ai-show-rec{display:none;}
.ai-input-bar.recording .ai-hide-rec{display:none;}
.ai-input-bar.recording .ai-show-rec{display:flex;}
.ai-input-bar.recording .ai-mic{width:52px; height:52px; border-radius:50%;
  background:linear-gradient(150deg,#B85C86,#6E2A50); color:#fff; border:none;
  box-shadow:0 6px 18px rgba(110,42,80,.34);}
.ai-input-bar.recording .ai-mic svg{width:22px; height:22px;}
.ai-input-bar.recording .ai-mic.cancelling{background:linear-gradient(150deg,#C2553F,#8E3421);}
.ai-recmid{flex:1; display:flex; align-items:center; gap:10px; height:44px; padding:0 14px;
  border-radius:999px; background:rgba(255,252,249,.85); border:1px solid rgba(255,255,255,.9);
  min-width:0; transition:background .18s ease;}
.ai-recmid.cancelling{background:rgba(255,235,230,.92); border-color:rgba(194,85,63,.35);}
.ai-recdot{width:9px; height:9px; border-radius:50%; background:#C2553F; flex:none;
  animation:recPulse 1.1s ease-in-out infinite;}
@keyframes recPulse{0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.35;transform:scale(.82)}}
.ai-rectime{font-size:13px; font-weight:750; color:#2A1622; font-variant-numeric:tabular-nums; flex:none;}
.ai-recslide{flex:1; display:flex; align-items:center; gap:3px; justify-content:flex-end;
  font-size:12px; color:#8A7280; white-space:nowrap; transition:opacity .12s linear;}
.ai-recslide svg{width:13px; height:13px;}
.ai-micbig.cancel{background:linear-gradient(150deg,#C2553F,#8E3421);}
.ai-vplayer{display:flex; align-items:center; gap:10px; min-width:190px;}
.ai-vplay{width:34px; height:34px; border-radius:50%; flex:none; display:grid; place-items:center;
  background:rgba(255,255,255,.22); color:#fff; border:1px solid rgba(255,255,255,.3); cursor:pointer;}
.ai-vplay:disabled{opacity:.5; cursor:default;}
.ai-vwave{flex:1; display:flex; align-items:center; gap:2px; height:24px; min-width:80px;}
.ai-vwave i{flex:1; min-width:2px; max-width:3px; border-radius:2px; background:rgba(255,255,255,.55);}
.ai-vsecs{font-size:11.5px; opacity:.85; flex:none; font-variant-numeric:tabular-nums;}

@media (prefers-reduced-motion:reduce){ .ai-recdot{animation:none} }
.ai-attach{flex-shrink:0;display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--surface-alt);border-top:1px solid var(--line)}
.ai-attach img{width:44px;height:44px;object-fit:cover;border-radius:8px;display:block}
.ai-attach-lbl{flex:1;font-size:12px;color:var(--muted)}
.ai-attach-x{width:28px;height:28px;border-radius:50%;background:var(--plum-soft);color:var(--plum);border:none;display:grid;place-items:center;cursor:pointer}
.ai-attach-x svg{width:13px;height:13px}
.ai-shot{display:block;width:100%;max-width:220px;border-radius:10px;margin-bottom:6px}
/* ---- Header, navigation and text legibility ---- */
/* Logo was 22px and sat slightly above the action row; 30px with a shared
   baseline lines it up with the pill, bell and avatar. */
.brand-mark-svg svg{height:30px;}
.brand-mark img{height:30px;}
.topbar-v2{align-items:center;}
.brand-block{align-items:center;}

/* Navigation labels were 9.5px at weight 600 in a light grey — small and low
   contrast at once. */
.nav-btn{font-size:11px; font-weight:700;}
.nav-btn.on{font-weight:800;}

/* The AI button's disc was near-white, so the mascot's head had almost no
   backing. Plum matches the buttons and makes the head read clearly. */
.nav-ai-disc{
  background:radial-gradient(circle at 42% 34%, #6E405D, var(--plum-700) 62%, #35182A);
  border:2px solid rgba(255,255,255,.85);
  box-shadow:0 8px 20px rgba(74,30,56,.38);
  /* A wider rule on nav children was resetting this to display:block, so
     place-items had no effect and the head sat against the top edge. */
  display:flex !important; align-items:center !important; justify-content:center !important;
}
.nav-ai-disc img{display:block; margin:0;}
html[data-theme="dark"] .nav-ai-disc{
  background:radial-gradient(circle at 42% 34%, #6E405D, #3A2333 70%);
  border-color:rgba(255,255,255,.20);
}

/* ============================ Depth and material ==========================
   A single soft shadow reads as flat because real objects cast two: a tight
   contact shadow and a wide ambient one. These variables layer three, add a lit
   top edge and a shaded bottom edge, and make surfaces a slight gradient rather
   than a flat fill — which implies a light source above. */
:root{
  --lift-1:
    0 1px 2px rgba(74,30,56,.08),
    0 3px 8px -3px rgba(74,30,56,.10);
  --lift-2:
    0 1px 2px rgba(74,30,56,.10),
    0 4px 8px -2px rgba(74,30,56,.10),
    0 14px 32px -10px rgba(74,30,56,.20);
  --lift-3:
    0 2px 4px rgba(74,30,56,.10),
    0 8px 16px -4px rgba(74,30,56,.14),
    0 22px 44px -14px rgba(74,30,56,.26);
  --edge: inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1px 0 rgba(74,30,56,.07);
  --surface-lit: linear-gradient(170deg, rgba(255,255,255,.66), rgba(255,255,255,.42));
}
body.glass-bg .card,
body.glass-bg .ts,
body.glass-bg .pcard,
body.glass-bg .mlist,
body.glass-bg .profcard,
body.glass-bg .quick,
body.glass-bg .rdrow,
body.glass-bg .support-opt,
body.glass-bg .home-tile,
body.glass-bg .infobanner,
body.glass-bg .detail-hero,
body.glass-bg .pdx-head,
body.glass-bg .pdx-doc,
body.glass-bg .dws-box,
body.glass-bg .ig-step,
body.glass-bg .cat-item,
body.glass-bg .daily-card,
body.glass-bg .aicard{
  background:var(--surface-lit);
  border-color:rgba(255,255,255,.55);
  box-shadow:var(--lift-2), var(--edge);
}
/* Cards that carry the screen's main action sit higher than the rest. */
body.glass-bg .daily-card,
body.glass-bg .cert-card{ box-shadow:var(--lift-3), var(--edge); }
/* Rows inside a list are part of the card, not separate objects. */
body.glass-bg .mrow,
body.glass-bg .earn-row{ box-shadow:none; }

/* Press states: depth is felt through interaction as much as seen. */
.card, .ts, .pcard, .quick, .cat-item, .aicard, .daily-btn, .profcard,
.mrow, .support-opt, .home-tile, .bal-pill, .qcard, .rdrow{
  transition:transform .12s cubic-bezier(.2,.8,.2,1), box-shadow .12s ease;
}
.card:active, .ts:active, .pcard:active, .quick:active, .cat-item:active,
.aicard:active, .profcard:active, .support-opt:active, .home-tile:active,
.qcard:active, .rdrow:active{
  transform:scale(.985);
  box-shadow:var(--lift-1), var(--edge);
}
.daily-btn:active, .bal-pill:active{ transform:scale(.97); }
.mrow:active{ background:rgba(255,255,255,.34); }
/* Records, not controls: no press feedback, no pointer cursor. */
.mrow-static, .mrow-static:active{ background:transparent; cursor:default; }

/* Nested radii: an inner element must be tighter than its container or the
   corners look mismatched. */
.pcard-docs, .pdx-doc, .ig-sheet, .ig-safbar, .ig-home{ border-radius:12px; }
.daily-btn{ border-radius:13px; }

html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .aicard{
  background:linear-gradient(170deg, rgba(255,255,255,.09), rgba(255,255,255,.05));
  border-color:rgba(255,255,255,.12);
  box-shadow:
    0 2px 4px rgba(0,0,0,.30),
    0 10px 24px -8px rgba(0,0,0,.38),
    inset 0 1px 0 rgba(255,255,255,.10);
}
@media (prefers-reduced-motion: reduce){
  .card, .ts, .pcard, .quick, .cat-item, .aicard, .daily-btn, .profcard,
  .mrow, .support-opt, .home-tile, .bal-pill, .qcard, .rdrow{ transition:none; }
  .card:active, .ts:active, .pcard:active, .aicard:active{ transform:none; }
}

/* ---- Profile screen ---- */
.pf-top{padding-top:2px;}
.pf-title{font-size:22px; font-weight:840; letter-spacing:-.025em; color:var(--ink); margin-top:8px;}
.pf-reward{display:flex; align-items:center; gap:7px; margin:14px 0 10px;
  font-size:11px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--plum);}
.pf-reward svg{width:16px; height:16px; flex:none;}
.pf-card{border-radius:16px; overflow:hidden;
  background:linear-gradient(170deg,rgba(255,255,255,.66),rgba(255,255,255,.42));
  border:1px solid rgba(255,255,255,.55);
  -webkit-backdrop-filter:blur(18px) saturate(180%); backdrop-filter:blur(18px) saturate(180%);
  box-shadow:0 1px 2px rgba(74,30,56,.10), 0 4px 8px -2px rgba(74,30,56,.10),
    0 14px 32px -10px rgba(74,30,56,.20), inset 0 1px 0 rgba(255,255,255,.9);}
.pf-row{display:block; padding:11px 14px; border-bottom:1px solid rgba(74,30,56,.09); cursor:text;}
.pf-row:last-child{border-bottom:none;}
.pf-row.locked{cursor:default; opacity:.55;}
.pf-k{display:block; font-size:10.5px; font-weight:750; letter-spacing:.04em;
  text-transform:uppercase; color:var(--muted);}
.pf-v{display:block; font-size:15px; font-weight:700; color:var(--ink); margin-top:3px;}
.pf-in{display:block; width:100%; border:none; background:none; padding:0; margin-top:3px;
  font-family:inherit; font-size:15px; font-weight:700; color:var(--ink); outline:none;}
.pf-in::placeholder{color:#A796A0; font-weight:600;}
.pf-note{font-size:11.5px; color:var(--muted); margin-top:10px; line-height:1.45;}
.pf-save{display:block; width:100%; height:48px; border:none; border-radius:14px; margin-top:14px;
  cursor:pointer; font-family:inherit; font-size:14.5px; font-weight:820; color:#fff;
  background:linear-gradient(160deg,#6E405D,var(--plum-700));
  box-shadow:0 8px 20px -10px rgba(74,30,56,.5);}
.pf-save:active{transform:scale(.985);}
.pf-ghost{display:flex; align-items:center; justify-content:center; gap:7px; width:100%; height:46px;
  border-radius:14px; margin-top:10px; cursor:pointer; font-family:inherit;
  border:1px solid rgba(74,30,56,.16); background:rgba(255,255,255,.5);
  color:var(--ink); font-size:14px; font-weight:760;}
.pf-ghost:active{transform:scale(.985);}
.authv-static{flex:1; min-width:0; font-size:15px; font-weight:700; color:var(--ink);}
.authv-fld.locked{opacity:.6;}
.authv-hint{font-size:11.5px; color:var(--muted); line-height:1.45; margin-top:9px;}
/* The nav is fixed to the bottom, but on iOS a short page can leave a sliver
   below it. Extending its own background past the bottom edge means nothing can
   show through, whatever the viewport reports. */
.nav::after{
  content:""; position:absolute; left:0; right:0; top:100%; height:60px;
  background:inherit; -webkit-backdrop-filter:inherit; backdrop-filter:inherit;
  pointer-events:none;
}
/* Belt and braces: pin it with bottom AND inset so no single property decides. */
.nav{bottom:0 !important;}

/* The claimed state used a green success colour that predates the plum
   palette — the only green left in the app. */
.daily-doneline{background:var(--plum-soft) !important;}
.daily-doneline .circle{background:var(--plum) !important;}
.daily-doneline .txt{color:var(--plum) !important; font-weight:800;}
.daily-doneline .sub{color:var(--muted) !important;}
html[data-theme="dark"] .daily-doneline{background:rgba(255,255,255,.08) !important;}
html[data-theme="dark"] .daily-doneline .txt{color:#E9A8CE !important;}
/* ---- Glass on the chat screens ----
   The chat kept the flat ivory it was designed with, so it was the only screen
   not carrying the wash. Same recipe as the rest of the app. */
.ai-chatview{
  background:
    radial-gradient(ellipse 120% 50% at 82% 0%, rgba(248,196,221,.5), transparent 62%),
    radial-gradient(ellipse 110% 45% at 4% 42%, rgba(214,210,248,.42), transparent 64%),
    linear-gradient(168deg,#FCE7DC 0%,#F6DCEA 38%,#EADFF6 72%,#F1E9EF 100%) !important;
}
/* Head and input bar float over the thread, so they blur what passes beneath. */
.ai-chat-head, .ai-input-bar{
  background:rgba(255,255,255,.6) !important;
  -webkit-backdrop-filter:blur(22px) saturate(190%);
  backdrop-filter:blur(22px) saturate(190%);
  border-color:rgba(255,255,255,.55) !important;
}
/* Assistant bubbles become glass; the customer's stay solid plum so the two
   sides of the conversation remain clearly distinct. */
.ai-b-bot{
  background:linear-gradient(170deg,rgba(255,255,255,.68),rgba(255,255,255,.46)) !important;
  border:1px solid rgba(255,255,255,.7);
  -webkit-backdrop-filter:blur(16px) saturate(180%);
  backdrop-filter:blur(16px) saturate(180%);
  box-shadow:0 1px 2px rgba(74,30,56,.08), 0 6px 16px -8px rgba(74,30,56,.16),
    inset 0 1px 0 rgba(255,255,255,.8);
}
.ai-clip, .ai-mic{
  background:rgba(255,255,255,.6) !important;
  border:1px solid rgba(255,255,255,.8) !important;
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
}
.ai-input{
  background:rgba(255,255,255,.6) !important;
  border:1px solid rgba(255,255,255,.8);
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
}

html[data-theme="dark"] .ai-chatview{
  background:
    radial-gradient(ellipse 120% 50% at 82% 0%, rgba(142,88,122,.5), transparent 64%),
    linear-gradient(168deg,#372838 0%,#2E2130 62%,#271C28 100%) !important;
}
html[data-theme="dark"] .ai-chat-head,
html[data-theme="dark"] .ai-input-bar{background:rgba(46,33,48,.72) !important; border-color:rgba(255,255,255,.10) !important;}
html[data-theme="dark"] .ai-b-bot{
  background:linear-gradient(170deg,rgba(255,255,255,.09),rgba(255,255,255,.05)) !important;
  border-color:rgba(255,255,255,.12);}
/* iOS gives date inputs their own internal padding and alignment, so they sit
   differently from the text fields beside them. Normalise the box and pull the
   value back to the same left edge. */
.pf-in[type="date"]{
  -webkit-appearance:none; appearance:none;
  min-height:20px; line-height:1.25; text-align:left;
  padding:0; margin:0; background:none;
}
.pf-in[type="date"]::-webkit-date-and-time-value{
  text-align:left; margin:0; padding:0; line-height:1.25;
}
.pf-in[type="date"]::-webkit-datetime-edit{padding:0;}
.pf-in[type="date"]::-webkit-datetime-edit-fields-wrapper{padding:0;}
/* The picker button is Safari blue by default; tint it to the palette. */
.pf-in[type="date"]::-webkit-calendar-picker-indicator{
  opacity:.5; cursor:pointer; margin:0; padding:0;
  filter:invert(16%) sepia(24%) saturate(1600%) hue-rotate(280deg);
}
/* An empty date shows the browser's own mm/dd/yyyy; keep it as quiet as the
   other placeholders rather than full-weight text. */
.pf-in[type="date"]:invalid,
.pf-in[type="date"]:not(:focus):in-range:placeholder-shown{color:#A796A0; font-weight:600;}

/* In dark mode --plum is a light pink (#C9A0BC), so anything painting white
   text on it drops to ~2:1. These need dark text on the light chip instead. */
html[data-theme="dark"] .lang-seg button.on{
  background:var(--plum); color:#1B1116;
}
html[data-theme="dark"] .bal-pill{
  background:linear-gradient(160deg,#5A3A50,#3A2333); color:var(--ink);
}
html[data-theme="dark"] .daily-doneline .circle{
  background:var(--plum) !important; color:#1B1116 !important;
}
html[data-theme="dark"] .pf-reward{color:var(--plum);}
/* The last element in a screen sometimes carries its own bottom margin, so the
   space above the nav varied from 22px to 49px between tabs. The screen's own
   padding is the single source of that spacing. */
#app .screen > *:last-child{margin-bottom:0 !important;}

/* Anything below the nav is painted by the nav itself. A spread shadow offset
   downwards is drawn as part of the element, so it cannot be separated from it
   by a layout quirk the way a positioned pseudo-element can. */
.nav{
  bottom:0 !important;
  box-shadow:
    0 -6px 22px -10px rgba(74,30,56,.28),
    0 120px 0 0 rgba(255,255,255,.62) !important;
}
html[data-theme="dark"] .nav{
  box-shadow:
    0 -6px 22px -10px rgba(0,0,0,.55),
    0 120px 0 0 rgba(46,33,48,.74) !important;
}
/* The pseudo-element stays as a second layer for the blur, since a shadow
   cannot carry backdrop-filter. */
.nav::after{height:120px;}

/* Beyond the viewport — the home-indicator strip and any rubber-band overscroll
   — iOS paints the document's background COLOUR. It never uses a background
   image, so a gradient-only wash left that strip at the browser default (white),
   which showed as a pale band under the nav in dark mode.
   A solid colour matching each end of the wash fixes it. */
html.glass-bg{background-color:#F1E9EF;}
html[data-theme="dark"].glass-bg{background-color:#271C28;}
/* The auth stage runs plum to the edges, so it needs its own. */
html:has(body.authing){background-color:#2E1226;}
body.authing{background-color:#2E1226;}

/* The band below the nav labels is the iOS home-indicator reserve, not a gap.
   Apple's full 34pt is more clearance than the indicator needs (~15-20pt), and
   on a translucent, rounded bar the extra reads as empty space rather than part
   of the bar. Reserve enough to stay clear of the swipe area, no more. */
.nav{
  padding-bottom:max(10px, calc(4px + env(safe-area-inset-bottom) * 0.6)) !important;
}
/* The background still paints the full area beneath, so nothing shows through. */

/* ---- Text selection ----
   A long press selecting text and raising the copy bar makes a web app feel
   like a web page. Disabled everywhere, with deliberate exceptions below for
   the places where copying is the point. */
html, body{
  -webkit-user-select:none; user-select:none;
  -webkit-touch-callout:none;      /* no long-press preview on links/images */
  -webkit-tap-highlight-color:transparent;
}
/* Fields must stay selectable or typing and editing break. */
input, textarea, select, [contenteditable="true"]{
  -webkit-user-select:text !important; user-select:text !important;
  -webkit-touch-callout:default;
}
/* Things a customer has a real reason to copy: the referral code, the AI's
   answers, and support replies. */
.refer-code, .refer-code *,
.ai-b-bot, .ai-b-bot *,
.cinfo-card, .cinfo-card *{
  -webkit-user-select:text; user-select:text;
  -webkit-touch-callout:default;
}
/* Images should not offer "Save image" on long press. */
img{-webkit-touch-callout:none; -webkit-user-drag:none; user-drag:none;}

/* iOS paints the status-bar strip a fixed white (default) or black (black) — it
   never takes the app's colour. Before the glass redesign the app was
   near-white, so the strip blended and looked adaptive. The topbar sits
   directly beneath the strip, so fading ITS top edge to the strip's colour
   restores that seamless join without the dead space translucent causes. */
body.glass-bg .topbar{
  background:linear-gradient(180deg,
    #FFFFFF 0px,
    rgba(255,255,255,.86) 10px,
    rgba(255,255,255,.62) 34px,
    rgba(255,255,255,.62) 100%) !important;
}
html[data-theme="dark"] body.glass-bg .topbar{
  background:linear-gradient(180deg,
    #000000 0px,
    rgba(20,14,22,.88) 10px,
    rgba(46,33,48,.74) 34px,
    rgba(46,33,48,.74) 100%) !important;
}

/* The splash covers the screen during launch, so its top edge joins the iOS
   strip too. It was flat #F7F3F1 against a white strip — a visible seam for the
   first second of every launch. Match the strip and fade into the app colour. */
#boot{
  background:linear-gradient(180deg, #FFFFFF 0px, #FDF6F8 40px, #F7F3F1 140px) !important;
}
html[data-theme="dark"] #boot{
  background:linear-gradient(180deg, #000000 0px, #1C1420 40px, #271C28 140px) !important;
}


/* ===================== Dark-only: glowing card edge =====================
   A hairline of light along the card's edge plus a faint outer bloom. The
   top edge is brightest, as if lit from above, which is what makes it read
   as a raised object rather than a drawn outline. */
html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .quick,
html[data-theme="dark"] body.glass-bg .rdrow,
html[data-theme="dark"] body.glass-bg .support-opt,
html[data-theme="dark"] body.glass-bg .home-tile,
html[data-theme="dark"] body.glass-bg .infobanner,
html[data-theme="dark"] body.glass-bg .detail-hero,
html[data-theme="dark"] body.glass-bg .pdx-head,
html[data-theme="dark"] body.glass-bg .pdx-doc,
html[data-theme="dark"] body.glass-bg .dws-box,
html[data-theme="dark"] body.glass-bg .ig-step,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .aicard,
html[data-theme="dark"] body.glass-bg .pf-card{
  border:1px solid rgba(233,168,206,.18);
  box-shadow:
    0 0 0 1px rgba(233,168,206,.06),           /* hairline just outside */
    0 0 18px -4px rgba(233,168,206,.16),        /* soft bloom */
    0 2px 4px rgba(0,0,0,.30),
    0 10px 24px -8px rgba(0,0,0,.38),
    inset 0 1px 0 rgba(255,255,255,.13),        /* lit top edge */
    inset 0 -1px 0 rgba(0,0,0,.22);             /* shaded bottom edge */
}
/* The card that carries the screen's main action glows a little more. */
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .cert-card{
  border-color:rgba(233,168,206,.26);
  box-shadow:
    0 0 0 1px rgba(233,168,206,.09),
    0 0 26px -4px rgba(233,168,206,.22),
    0 3px 6px rgba(0,0,0,.4),
    0 16px 34px -10px rgba(0,0,0,.5),
    inset 0 1px 0 rgba(255,255,255,.16),
    inset 0 -1px 0 rgba(0,0,0,.24);
}
/* Pressing dims the bloom, so the card reads as pushed in. */
html[data-theme="dark"] body.glass-bg .card:active,
html[data-theme="dark"] body.glass-bg .ts:active,
html[data-theme="dark"] body.glass-bg .pcard:active,
html[data-theme="dark"] body.glass-bg .cat-item:active,
html[data-theme="dark"] body.glass-bg .aicard:active{
  box-shadow:
    0 0 0 1px rgba(233,168,206,.05),
    0 0 10px -6px rgba(233,168,206,.12),
    0 1px 2px rgba(0,0,0,.3),
    inset 0 1px 0 rgba(255,255,255,.10);
}

/* The AI screen was designed light-only, so its headings and body text are dark
   plum. Now that the panel carries the dark wash they were rendering at ~1.2:1
   — effectively invisible. */
html[data-theme="dark"] .ai-chat-title{color:var(--ink);}
html[data-theme="dark"] .ai-w1{color:var(--ink);}
html[data-theme="dark"] .ai-w2{color:var(--ink-soft, #C9BCC4);}


html[data-theme="dark"] .ai-pcard span{color:var(--ink);}

/* =================== Dark-only corrections =====================
   Several components were given light-mode values during the glass work with
   no dark variant, so in a dark-only app they render light-on-light. */

/* Modals and fields were painted near-white by the glass rules. */
html[data-theme="dark"] body.glass-bg .modal,
html[data-theme="dark"] body.glass-bg .field-wrap,
html[data-theme="dark"] body.glass-bg .phone-field,
html[data-theme="dark"] body.glass-bg .pass-field,
html[data-theme="dark"] body.glass-bg .prod-select{
  background:rgba(58,42,60,.96) !important;
  border:1px solid rgba(233,168,206,.16);
  box-shadow:0 0 26px -6px rgba(233,168,206,.14), 0 18px 40px -12px rgba(0,0,0,.6);
}
/* Primary buttons used --ink as a background, which inverts to near-white. */
html[data-theme="dark"] .add-btn,
html[data-theme="dark"] .pd-extend{
  background:linear-gradient(160deg,#8A5478,#5A2A46) !important;
  color:#fff !important;
}
/* Secondary actions inside modals. */
html[data-theme="dark"] .rd-alt{color:#E9A8CE;}
html[data-theme="dark"] .modal .mod-cancel,
html[data-theme="dark"] .mod-cancel{color:var(--ink-soft, #C9BCC4);}

/* Auth: the white button carried plum text, and --plum is light in dark mode. */
html[data-theme="dark"] .authv-solid{background:#fff; color:#3A1730;}
html[data-theme="dark"] .authv-lang button.on{background:#fff; color:#3A1730;}
html[data-theme="dark"] .authv-lang button{color:#F0DCE8;}

/* The assistant's bubble kept the light glass recipe. */
html[data-theme="dark"] .ai-b-bot{
  background:linear-gradient(170deg,rgba(255,255,255,.10),rgba(255,255,255,.06)) !important;
  color:var(--ink) !important;
  border:1px solid rgba(233,168,206,.16);
}

/* The AI welcome hero and its controls were built for the light peach screen.
   In a dark app the hero reads as a bright slab and the input bar as a white
   strip, so both are re-toned rather than left as leftovers. */
html[data-theme="dark"] .ai-anim{
  background:linear-gradient(168deg,#4A2E46,#3A2438 60%,#2E2130);
}
/* Blend the hero's lower edge into the screen instead of ending on a hard line. */
html[data-theme="dark"] .ai-anim::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:56px;
  background:linear-gradient(180deg, rgba(39,28,40,0), rgba(39,28,40,.94));
  pointer-events:none;
}
html[data-theme="dark"] .ai-anim video,
html[data-theme="dark"] .ai-anim img{ mix-blend-mode:normal; }

/* Input row */
html[data-theme="dark"] .ai-input{
  background:rgba(255,255,255,.08) !important;
  border:1px solid rgba(233,168,206,.16) !important;
  color:var(--ink);
}
html[data-theme="dark"] .ai-input::placeholder{color:var(--muted);}
html[data-theme="dark"] .ai-clip,
html[data-theme="dark"] .ai-mic{
  background:rgba(255,255,255,.08) !important;
  border:1px solid rgba(233,168,206,.16) !important;
  color:#E9A8CE !important;
}
/* Product picker cards */
html[data-theme="dark"] .ai-pcard{
  background:linear-gradient(170deg,rgba(255,255,255,.09),rgba(255,255,255,.05)) !important;
  border:1px solid rgba(233,168,206,.16) !important;
}

/* ==================== Dark surfaces: single source of truth ===============
   The depth pass introduced --surface-lit as a white gradient and, sitting at
   the end of the stylesheet, it overrode the earlier dark rules — which is why
   cards rendered light grey with unreadable text. Redefining the variable per
   theme fixes every consumer at once rather than patching each rule. */
html[data-theme="dark"]{
  --surface-lit:linear-gradient(170deg, rgba(255,255,255,.13), rgba(255,255,255,.075));
  --edge: inset 0 1px 0 rgba(255,255,255,.12), inset 0 -1px 0 rgba(0,0,0,.28);
  --glass:rgba(255,255,255,.11);
  --glass-line:rgba(233,168,206,.20);
  --bar:rgba(46,33,48,.74);
  --sheet:rgba(58,42,60,.96);
}

/* Every card surface, whatever rule set it. */
html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .pcard-docs,
html[data-theme="dark"] body.glass-bg .pcard-toggle,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .quick,
html[data-theme="dark"] body.glass-bg .rdrow,
html[data-theme="dark"] body.glass-bg .support-opt,
html[data-theme="dark"] body.glass-bg .home-tile,
html[data-theme="dark"] body.glass-bg .infobanner,
html[data-theme="dark"] body.glass-bg .earn-row,
html[data-theme="dark"] body.glass-bg .earn-drop,
html[data-theme="dark"] body.glass-bg .detail-hero,
html[data-theme="dark"] body.glass-bg .pdx-head,
html[data-theme="dark"] body.glass-bg .pdx-doc,
html[data-theme="dark"] body.glass-bg .dws-box,
html[data-theme="dark"] body.glass-bg .ig-step,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .aicard,
html[data-theme="dark"] .pf-card,
html[data-theme="dark"] .home-glass .glass{
  background:var(--surface-lit) !important;
  border-color:var(--glass-line) !important;
}
/* Bars and sheets. */
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] body.glass-bg .nav,
html[data-theme="dark"] .nav{
  background:var(--bar) !important;
}
html[data-theme="dark"] body.glass-bg .modal,
html[data-theme="dark"] body.glass-bg .field-wrap,
html[data-theme="dark"] body.glass-bg .phone-field,
html[data-theme="dark"] body.glass-bg .pass-field,
html[data-theme="dark"] body.glass-bg .prod-select,
html[data-theme="dark"] .modal{
  background:var(--sheet) !important;
}
/* Secondary buttons and controls that were white-tinted. */
html[data-theme="dark"] .pf-ghost,
html[data-theme="dark"] .ai-chip,
html[data-theme="dark"] .ai-input,
html[data-theme="dark"] .ai-clip,
html[data-theme="dark"] .ai-mic,
html[data-theme="dark"] .ai-pcard,
html[data-theme="dark"] .authv-second{
  background:var(--glass) !important;
  border-color:var(--glass-line) !important;
}
html[data-theme="dark"] .ai-b-bot{
  background:var(--surface-lit) !important;
  border-color:var(--glass-line) !important;
}
html[data-theme="dark"] .chat-intro{
  background:var(--sheet) !important; color:var(--ink) !important;
}

/* ---- Legibility corrections found by pixel sampling ----
   These sit between 2.0 and 4.4:1 against the card surfaces they actually
   render on, which DOM-based checking had missed. */
html[data-theme="dark"]{
  --muted:#C6BAC1;          /* lifted with the palette: the lighter cards need more */
  --ink-soft:#D6CBD2;
}
/* "Скоро" badges were 2.7:1 */
html[data-theme="dark"] .pdx-doc-badge,
html[data-theme="dark"] .pd-soon{
  background:rgba(233,168,206,.14); color:#E4C6D8;
}
/* The locked phone row dimmed the whole row to 55%, taking its label with it. */
html[data-theme="dark"] .pf-row.locked{opacity:1;}
html[data-theme="dark"] .pf-row.locked .pf-k{color:var(--muted);}
html[data-theme="dark"] .pf-row.locked .pf-v{color:var(--ink-soft);}
/* Inactive language chips */
html[data-theme="dark"] .authv-lang button{color:#EBD8E4; opacity:.92;}
html[data-theme="dark"] .lang-seg button{color:#D9C4D2; opacity:1;}
html[data-theme="dark"] .lang-seg button.on{background:var(--plum); color:#1B1116;}
/* Notification meta and the mark-all action */
html[data-theme="dark"] .notif-row-time,
html[data-theme="dark"] .nd-time{color:var(--muted);}
html[data-theme="dark"] .notif-markall{color:#E9A8CE;}
/* Draw stat labels and small keys sat just under the threshold */
html[data-theme="dark"] .dws-k,
html[data-theme="dark"] .ts-k,
html[data-theme="dark"] .pf-k,
html[data-theme="dark"] .daily-lbl,
html[data-theme="dark"] .pdx-model{color:var(--muted);}

/* Final pass: items still sitting between 2.3 and 4.5:1 on their real surface. */
html[data-theme="dark"] .authv-lang button{color:#F4E6EE; opacity:1;}
html[data-theme="dark"] .pdx-doc-badge,
html[data-theme="dark"] .pd-soon{background:rgba(233,168,206,.18); color:#F0D8E6;}
/* Rows for certificates the balance cannot yet cover are dimmed to show they
   are unavailable, but the text explaining why must still be readable. */
html[data-theme="dark"] .rdrow.off,
html[data-theme="dark"] .rdrow[disabled]{opacity:1;}
html[data-theme="dark"] .rdrow.off .rdrow-t,
html[data-theme="dark"] .rdrow[disabled] .rdrow-t{color:var(--muted);}
html[data-theme="dark"] .rdrow-s{color:#B9AAB3;}

/* The QR landing is the first thing a customer ever sees. With no slide artwork
   yet it was a near-black rectangle, which reads as broken rather than
   deliberate. A richer plum with light coming from the top-right gives it
   depth, and the caption still sits on a dark enough base to stay legible. */
.ig-car{background:#3A1730;}
.ig-car-scrim{
  background:
    radial-gradient(ellipse 90% 70% at 78% 8%, rgba(233,168,206,.30), transparent 62%),
    radial-gradient(ellipse 80% 60% at 12% 30%, rgba(150,96,168,.26), transparent 66%),
    linear-gradient(180deg, rgba(30,12,26,.20) 0%, rgba(30,12,26,.10) 38%,
                    rgba(24,10,20,.72) 78%, rgba(20,8,16,.92) 100%),
    linear-gradient(158deg,#6E2A50 0%,#4A1B3C 52%,#2E1226 100%);
}
/* With artwork present the photo carries the colour, so only the scrim shows. */
.ig-car-img + .ig-car-scrim{
  background:linear-gradient(180deg, rgba(20,8,16,.34) 0%, rgba(20,8,16,.10) 34%,
    rgba(20,8,16,.72) 76%, rgba(20,8,16,.94) 100%);
}
/* Badges: 4.24:1 at 9px was still short of the 4.5 needed at that size. */
html[data-theme="dark"] .pdx-doc-badge,
html[data-theme="dark"] .pd-soon{
  background:rgba(233,168,206,.26); color:#FFFFFF; font-weight:800; letter-spacing:.04em;
}

/* The install steps mock iOS's own chrome. In a dark-only app three white slabs
   dominate the screen, and iOS in dark mode shows these panels dark anyway, so
   the dark rendering is both calmer and no less accurate. */
.ig-safbar{
  background:linear-gradient(180deg,#3A3340,#2C2632);
  border:1px solid rgba(255,255,255,.10);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.08);
}
.ig-safbar .u{background:rgba(255,255,255,.12); box-shadow:none;}
.ig-safbar .sh{color:#6FA8FF;}
.ig-safbar .ring{border-color:#6FA8FF;}
.ig-sheet{
  background:#2C2632; border:1px solid rgba(255,255,255,.10);
  box-shadow:0 8px 20px -10px rgba(0,0,0,.6);
}
.ig-sheet .row{color:#C9C2CC; border-bottom-color:rgba(255,255,255,.07);}
.ig-sheet .row.hl{
  background:linear-gradient(90deg, rgba(233,168,206,.18), rgba(233,168,206,.08));
  color:#F0D8E6;
}
.ig-sheet .row.hl:before{background:#E9A8CE;}
.ig-home{
  background:linear-gradient(160deg, rgba(255,255,255,.09), rgba(255,255,255,.05));
  border:1px solid rgba(233,168,206,.16);
}
.ig-home .tx{color:#D6CBD2;}

/* The AI welcome video has a pink background baked into the asset. Until a dark
   version exists, tone it back so it sits in the screen rather than glaring out
   of it — the mascot stays clearly visible. */
html[data-theme="dark"] .ai-anim video,
html[data-theme="dark"] .ai-anim img{
  /* Enough to stop the pink glaring, not so much that the mascot goes grey. */
  filter:brightness(.78) saturate(1.02) contrast(1.02);
}
/* A plum veil over the asset's pink, so the hero belongs to the palette. */
html[data-theme="dark"] .ai-anim::before{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(168deg, rgba(74,30,56,.34), rgba(46,18,38,.30));
  mix-blend-mode:multiply;
}
html[data-theme="dark"] .ai-anim::after{z-index:2;}

/* ---- Option C: values that need lifting on the lighter card surfaces ----
   Every one of these was measured against the surface it actually renders on,
   not against the page background. */
html[data-theme="dark"]{
  --ok:#8FD3A6;             /* the warranty green was 3.6:1 on lighter cards */
  --sage:#8FD3A6;
  --success:#8FD3A6;
  --warn:#F0A877;
  --amber:#F0A877;
  --warning:#F0A877;
}
html[data-theme="dark"] .ts-k,
html[data-theme="dark"] .pf-k,
html[data-theme="dark"] .dws-k,
html[data-theme="dark"] .support-opt-s,
html[data-theme="dark"] .daily-lbl,
html[data-theme="dark"] .pdx-model,
html[data-theme="dark"] .psub{ color:#CFC3CA; }
html[data-theme="dark"] .ts-v.ok{ color:#8FD3A6; }

/* Final three on the lighter surfaces. */
html[data-theme="dark"] .greet-eyebrow{color:#EFC4DE;}
html[data-theme="dark"] .daily-s,
html[data-theme="dark"] .daily-hint{color:#D8CDD4;}
/* A translucent pill over a light card left this ambiguous at 9px. A solid
   plum pill with white text is unambiguous at any size. */
html[data-theme="dark"] .pdx-doc-badge,
html[data-theme="dark"] .pd-soon{
  background:#6E2A50; color:#FFFFFF; font-weight:800; letter-spacing:.04em;
  border:1px solid rgba(233,168,206,.28);
}

/* ==================== Glass intensity: level C ==========================
   Heavier blur with a brightness lift so the glass appears to gather light,
   a brighter lit edge, a side bevel, and shadows carried further out. */
html[data-theme="dark"]{
  --surface-lit:linear-gradient(160deg, rgba(255,255,255,.26), rgba(255,255,255,.09) 40%, rgba(255,255,255,.03));
  --glass:rgba(255,255,255,.16);
  --glass-line:rgba(233,168,206,.34);
  --edge:
    inset 0 1.5px 0 rgba(255,255,255,.42),
    inset 0 -1.5px 0 rgba(0,0,0,.40),
    inset 2px 0 0 rgba(255,255,255,.14),
    inset -2px 0 0 rgba(0,0,0,.20);
  --lift-2:
    0 0 40px -6px rgba(233,168,206,.32),
    0 2px 6px rgba(0,0,0,.38),
    0 12px 26px -6px rgba(0,0,0,.44),
    0 36px 70px -20px rgba(0,0,0,.58);
  --lift-3:
    0 0 52px -6px rgba(233,168,206,.38),
    0 3px 8px rgba(0,0,0,.42),
    0 16px 32px -6px rgba(0,0,0,.48),
    0 46px 88px -22px rgba(0,0,0,.62);
  --lift-1:
    0 0 16px -6px rgba(233,168,206,.20),
    0 1px 3px rgba(0,0,0,.32),
    0 4px 10px -4px rgba(0,0,0,.38);
}
/* Every card surface gets the heavier blur. */
html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .pcard-docs,
html[data-theme="dark"] body.glass-bg .pcard-toggle,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .quick,
html[data-theme="dark"] body.glass-bg .rdrow,
html[data-theme="dark"] body.glass-bg .support-opt,
html[data-theme="dark"] body.glass-bg .home-tile,
html[data-theme="dark"] body.glass-bg .infobanner,
html[data-theme="dark"] body.glass-bg .earn-row,
html[data-theme="dark"] body.glass-bg .earn-drop,
html[data-theme="dark"] body.glass-bg .detail-hero,
html[data-theme="dark"] body.glass-bg .pdx-head,
html[data-theme="dark"] body.glass-bg .pdx-doc,
html[data-theme="dark"] body.glass-bg .dws-box,
html[data-theme="dark"] body.glass-bg .ig-step,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .aicard,
html[data-theme="dark"] .pf-card,
html[data-theme="dark"] .ai-b-bot,
html[data-theme="dark"] .home-glass .glass{
  -webkit-backdrop-filter:blur(40px) saturate(220%) brightness(1.06);
  backdrop-filter:blur(40px) saturate(220%) brightness(1.06);
  box-shadow:var(--lift-2), var(--edge) !important;
}
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .cert-card{
  box-shadow:var(--lift-3), var(--edge) !important;
}
/* Bars gain the same treatment so they read as the same material. */
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] body.glass-bg .nav,
html[data-theme="dark"] .ai-chat-head,
html[data-theme="dark"] .ai-input-bar{
  -webkit-backdrop-filter:blur(34px) saturate(210%) brightness(1.04);
  backdrop-filter:blur(34px) saturate(210%) brightness(1.04);
}
/* Buttons pick up the lit top edge so they sit in the same light. */
html[data-theme="dark"] .daily-btn,
html[data-theme="dark"] .pf-save,
html[data-theme="dark"] .authv-primary,
html[data-theme="dark"] .add-btn,
html[data-theme="dark"] .pd-extend,
html[data-theme="dark"] .bal-pill{
  box-shadow:0 8px 20px -8px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.26),
    inset 0 -1px 0 rgba(0,0,0,.28);
}
/* Pressed: the bloom collapses, which is what makes it feel physical. */
html[data-theme="dark"] body.glass-bg .card:active,
html[data-theme="dark"] body.glass-bg .ts:active,
html[data-theme="dark"] body.glass-bg .pcard:active,
html[data-theme="dark"] body.glass-bg .cat-item:active,
html[data-theme="dark"] body.glass-bg .aicard:active{
  box-shadow:var(--lift-1), inset 0 1px 0 rgba(255,255,255,.20) !important;
}

/* The heavier glass brightens the top of each card, which is exactly where the
   small uppercase labels sit — they need lifting again to hold 4.5:1 there. */
html[data-theme="dark"] .ts-k,
html[data-theme="dark"] .pf-k,
html[data-theme="dark"] .dws-k,
html[data-theme="dark"] .daily-lbl,
html[data-theme="dark"] .pdx-model,
html[data-theme="dark"] .support-opt-s,
html[data-theme="dark"] .psub{ color:#E4DBE0; }
html[data-theme="dark"] .dws-box div,
html[data-theme="dark"] .dws-k{ color:#E4DBE0; }
html[data-theme="dark"] .dws-row span{ color:#E4DBE0; }

/* ===================== Floating capsule navigation =======================
   The bar detaches from the bottom edge and becomes a rounded capsule. The
   active tab is marked by a lighter pill behind it rather than by colour
   alone, and the AI disc stays raised above the capsule. */
.nav{
  left:14px !important; right:14px !important;
  width:auto !important; max-width:calc(480px - 28px) !important;
  margin:0 auto !important;
  bottom:calc(14px + env(safe-area-inset-bottom)) !important;
  transform:none !important;
  border-radius:999px !important;
  padding:7px 8px !important;
  overflow:visible !important;
  border:1px solid rgba(255,255,255,.13) !important;
  background:rgba(46,33,48,.80) !important;
  -webkit-backdrop-filter:blur(34px) saturate(210%) brightness(1.04);
  backdrop-filter:blur(34px) saturate(210%) brightness(1.04);
  box-shadow:
    0 14px 34px -10px rgba(0,0,0,.62),
    0 0 26px -8px rgba(233,168,206,.24),
    inset 0 1.5px 0 rgba(255,255,255,.20),
    inset 0 -1.5px 0 rgba(0,0,0,.34) !important;
}
/* The old rules painted the area below the bar; a floating capsule must not. */
.nav::after{display:none !important;}

.nav-btn{
  height:46px; border-radius:999px; gap:2px !important;
  padding:0 2px !important;
  transition:background .18s ease, color .18s ease;
}
/* Active tab: a lighter pill behind it, as in the reference. */
.nav-btn.on{
  background:rgba(255,255,255,.14);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22), 0 2px 8px -3px rgba(0,0,0,.40);
}
.nav-btn span{font-size:9px; line-height:1.1;}
.nav-btn svg{width:19px; height:19px;}

/* The AI disc keeps its lift, measured from the capsule rather than the bar. */
.nav-ai{overflow:visible;}
.nav-ai-disc{
  bottom:26px !important;
  width:50px !important; min-width:50px !important; max-width:50px !important; height:50px !important;
  border:2px solid rgba(255,255,255,.22) !important;
  box-shadow:0 10px 24px -6px rgba(0,0,0,.62), inset 0 1px 0 rgba(255,255,255,.24) !important;
}
.nav-ai-disc img{width:34px !important; height:34px !important;}
.nav-ai-lbl{margin-top:26px; font-size:9px;}
/* The active pill would collide with the raised disc, so the AI tab shows its
   state on the disc itself. */
.nav-ai.on{background:none !important; box-shadow:none !important;}
.nav-ai.on .nav-ai-disc{
  border-color:rgba(233,168,206,.55) !important;
  box-shadow:0 10px 26px -6px rgba(0,0,0,.62), 0 0 22px -4px rgba(233,168,206,.5),
    inset 0 1px 0 rgba(255,255,255,.28) !important;
}

/* The earlier rule that painted a 120px block beneath the bar is scoped to
   html[data-theme="dark"] .nav, which outranks a plain .nav selector — so the
   capsule was still being backed by a full-width slab. Same specificity here. */
html[data-theme="dark"] .nav{
  left:14px !important; right:14px !important;
  width:auto !important; max-width:calc(480px - 28px) !important;
  margin:0 auto !important;
  bottom:calc(14px + env(safe-area-inset-bottom)) !important;
  transform:none !important;
  border-radius:999px !important;
  background:rgba(46,33,48,.80) !important;
  box-shadow:
    0 14px 34px -10px rgba(0,0,0,.62),
    0 0 26px -8px rgba(233,168,206,.24),
    inset 0 1.5px 0 rgba(255,255,255,.20),
    inset 0 -1.5px 0 rgba(0,0,0,.34) !important;
}
html[data-theme="dark"] .nav::after{display:none !important;}

/* The active tab now sits on a lighter pill, so its label needs to be brighter
   than the plum accent that worked on the darker bar. */
html[data-theme="dark"] .nav-btn.on,
html[data-theme="dark"] .nav-btn.on span,
html[data-theme="dark"] .nav-btn.on svg{ color:#FFFFFF; }
html[data-theme="dark"] .nav-btn span{ color:#CFC3CA; }
html[data-theme="dark"] .nav-ai-lbl{ color:#CFC3CA; }
html[data-theme="dark"] .nav-ai.on .nav-ai-lbl{ color:#FFFFFF; }
html[data-theme="dark"] .pf-row.locked .pf-k{ color:#E4DBE0; }

/* The AI label was pushed down by a fixed margin below the raised disc, leaving
   it 7px lower than the rest. Anchoring every label to the bottom of its button
   lines them up regardless of what sits above. */
.nav-btn{
  justify-content:flex-end !important;
  padding-bottom:7px !important;
}
.nav-btn span,
.nav-ai-lbl{
  font-size:10.5px !important;
  line-height:1.15 !important;
  margin-top:0 !important;
}
/* The disc no longer pushes the label; it is positioned over the button. */
.nav-ai{justify-content:flex-end !important;}

/* The AI label was absolutely positioned with bottom:0, which pinned it to the
   button's padding edge instead of letting flex align it with the others. Made
   static so every label sits on the same baseline. */
.nav-ai-lbl{
  position:static !important;
  transform:none !important;
  bottom:auto !important; left:auto !important;
}

/* The AI tab is the primary action, so its label is set apart: heavier weight
   and a gradient that drifts across the text. background-clip:text paints the
   gradient into the glyphs; animating background-position moves it. */
@keyframes aiHue{
  0%   { background-position:0% 50%; }
  50%  { background-position:100% 50%; }
  100% { background-position:0% 50%; }
}
.nav-ai-lbl{
  font-weight:850 !important;
  letter-spacing:.02em;
  background:linear-gradient(90deg,
    #E9A8CE 0%, #F3C7E0 18%, #C9A0BC 34%, #9E86E0 52%,
    #E9A8CE 70%, #F7D9EA 86%, #E9A8CE 100%);
  background-size:300% 100%;
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent !important;
  animation:aiHue 6s ease-in-out infinite;
}
/* The active state brightens the run rather than replacing it. */
.nav-ai.on .nav-ai-lbl{
  background:linear-gradient(90deg,
    #FFFFFF 0%, #F9DCEE 16%, #E9A8CE 32%, #B9A2F0 50%,
    #FFFFFF 68%, #F3C7E0 84%, #FFFFFF 100%);
  background-size:300% 100%;
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
  animation:aiHue 4.5s ease-in-out infinite;
}
/* Anyone who has asked for less motion gets a solid colour instead. */
@media (prefers-reduced-motion: reduce){
  .nav-ai-lbl, .nav-ai.on .nav-ai-lbl{
    animation:none;
    background:none;
    -webkit-text-fill-color:currentColor;
    color:#E9A8CE !important;
  }
  .nav-ai.on .nav-ai-lbl{ color:#FFFFFF !important; }
}

/* ===================== AI orb ============================================
   Replaces the welcome video. Pure CSS, so it costs no download and stays
   sharp at any size. Depth comes from four cues a renderer would use: a sharp
   specular highlight, a terminator wrapping the far limb, a rim light bounced
   from behind, and a contact shadow on the ground. */
.ai-anim{
  height:280px; position:relative; display:grid; place-items:center;
  overflow:hidden; perspective:600px; background:none !important;
}
.ai-anim::before, .ai-anim::after{ display:none !important; }

@keyframes orbSpinA{ from{transform:rotate(0)}      to{transform:rotate(360deg)} }
@keyframes orbSpinB{ from{transform:rotate(0)}      to{transform:rotate(-360deg)} }
@keyframes orbDrift{ 0%,100%{transform:translate(0,0) scale(1)}
  33%{transform:translate(12%,-8%) scale(1.12)} 66%{transform:translate(-10%,9%) scale(.94)} }
@keyframes orbBreathe{ 0%,100%{transform:scale(1)} 50%{transform:scale(1.05)} }
@keyframes orbRing1{ from{transform:rotateX(74deg) rotateZ(0)} to{transform:rotateX(74deg) rotateZ(360deg)} }
@keyframes orbRing2{ from{transform:rotateX(66deg) rotateZ(0)} to{transform:rotateX(66deg) rotateZ(-360deg)} }

.orb{
  position:relative; z-index:2; width:132px; height:132px; border-radius:50%;
  overflow:hidden; isolation:isolate; background:#1B1024;
  animation:orbBreathe 4s ease-in-out infinite;
  box-shadow:0 0 60px -8px rgba(233,168,206,.55), 0 24px 40px -14px rgba(10,4,14,.85);
}


/* Rings sit behind the sphere so it occludes them, as a real orbit would. */

.orb-ring.b{ width:178px; height:178px; border-color:rgba(150,120,255,.42);
  animation:orbRing2 13s linear infinite; }


@media (prefers-reduced-motion: reduce){
  .orb, .orb-l, .orb-ring{ animation:none !important; }
}

/* ---- Gradient banding ----
   A wide, low-contrast gradient cannot be represented smoothly in 8-bit colour,
   so it steps into visible bands. A very fine noise layer dithers those steps
   away; it is invisible on its own but breaks up the boundaries. */
html.glass-bg::after{
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  opacity:.035; mix-blend-mode:overlay;
  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='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px;
}
/* The AI stage carries its own gradient, so it needs the same treatment. */
.ai-anim::after{
  content:"" !important; display:block !important;
  position:absolute; inset:0; z-index:4; pointer-events:none;
  opacity:.04; mix-blend-mode:overlay;
  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='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px;
}

/* The orb is now drawn on a canvas, so the CSS sphere layers are retired. */
.ai-anim canvas{ position:relative; z-index:2; width:100%; height:100%; display:block; }
.orb-bloom{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:radial-gradient(circle at 50% 48%, rgba(160,90,255,.22), transparent 58%);
}

/* The .45 opacity on unavailable certificate rows also dimmed the line that
   explains why they are unavailable, to 2.5:1. The row still reads as inactive
   through its muted text colour rather than by fading the whole element. */
html[data-theme="dark"] .rdrow.off{ opacity:1 !important; }
html[data-theme="dark"] .rdrow.off .rdrow-t{ color:#CFC3CA !important; }
html[data-theme="dark"] .rdrow.off .rdrow-s{ color:#C6B8C0 !important; }
html[data-theme="dark"] .rdrow.off img{ opacity:.65 !important; }
/* At 11px over the progress bar this line is mostly antialiased edge pixels;
   a touch more size and weight makes it solid rather than shimmering. */
html[data-theme="dark"] .rdrow.off .rdrow-s{
  font-size:11.5px !important; font-weight:650 !important; color:#DCD2D8 !important;
}

/* Height restored — the ask was to sit the capsule lower, not to make it
   smaller. The bottom offset below does that instead. */
.nav{ padding:7px 8px !important; }
.nav-btn{ height:46px !important; padding-bottom:7px !important; gap:2px !important; }
.nav-btn svg{ width:19px !important; height:19px !important; }
.nav-ai-disc{ bottom:26px !important; width:50px !important; min-width:50px !important;
  max-width:50px !important; height:50px !important; }
.nav-ai-disc img{ width:34px !important; height:34px !important; }

/* Sit the capsule closer to the bottom edge: 14px above the home-indicator
   inset was leaving it floating higher than intended. */
.nav{ bottom:calc(6px + env(safe-area-inset-bottom)) !important; }
html[data-theme="dark"] .nav{ bottom:calc(6px + env(safe-area-inset-bottom)) !important; }

/* The glow that canvas shadows used to draw per-segment now lives here — one
   composited layer instead of thousands of blurred strokes. */
.orb-bloom{
  background:
    radial-gradient(circle at 42% 46%, rgba(90,130,255,.26), transparent 46%),
    radial-gradient(circle at 60% 54%, rgba(230,70,200,.24), transparent 48%),
    radial-gradient(circle at 50% 50%, rgba(150,90,255,.16), transparent 62%) !important;
  filter:blur(6px);
}

/* The bloom spread across the whole 280px stage in blue and magenta, tinting
   the background away from the plum used everywhere else — it read as a
   different backdrop rather than as light coming off the orb. Now a tight
   circle centred on the sphere, at roughly half the strength, so it stops well
   inside the stage and the panel's own gradient carries the rest. */
.orb-bloom{
  background:
    radial-gradient(circle at 50% 47%, rgba(180,120,255,.18), transparent 30%),
    radial-gradient(circle at 50% 47%, rgba(233,168,206,.10), transparent 42%) !important;
  filter:blur(10px);
}

/* The motes orbit out to roughly the stage edge, leaving only 8px before the
   greeting — they read as colliding with the text. There is ~260px of unused
   space below the picker grid, so the whole block moves down. */
.ai-wcopy{ margin-top:30px !important; }
.ai-pgrid{ margin-top:18px !important; }


/* ---- Assistant avatar: a miniature wireframe orb ----
   The same mesh as the large orb, coarser, drawn on a transparent canvas — the
   earlier CSS sphere had a solid dark disc behind it, which read as a patch of
   the wrong background, and it did not match the mesh on the welcome screen. */
.ai-av-orb{ background:none !important; border:none !important; box-shadow:none !important; }
.mini-orb-c{ width:30px; height:30px; display:block; background:none; }

/* The motes orbit out to about 1.5x the sphere radius, which reached past the
   canvas edge and cut them off against the header above and the copy below.
   A taller stage gives them clear space; the sphere itself keeps its size
   because the radius factor drops to match. */
.ai-anim{ height:330px !important; overflow:visible !important; background:none !important; }

/* A little more spill from the CSS layer, still tight enough that it stops well
   inside the stage — the wash across the whole panel is what made the
   background look wrong before. */
.orb-bloom{
  background:
    radial-gradient(circle at 50% 47%, rgba(180,120,255,.26), transparent 32%),
    radial-gradient(circle at 50% 47%, rgba(233,168,206,.14), transparent 46%) !important;
  filter:blur(14px);
}

/* ---- Navigation capsule: glowing outline (C1) ----
   A crisp 1px line at high opacity, with the glow reading as light coming off
   the rim rather than a halo sitting behind it. Kept to 1px so the capsule
   stays in the same material family as the cards, which have a 1px lit edge. */
.nav, html[data-theme="dark"] .nav{
  border:1px solid rgba(240,190,220,.85) !important;
  box-shadow:
    0 14px 34px -10px rgba(0,0,0,.62),
    0 0 0 1px rgba(233,168,206,.40),
    0 0 18px 0 rgba(233,168,206,.55),
    0 0 40px -4px rgba(180,120,255,.36),
    inset 0 0 14px -4px rgba(233,168,206,.36),
    inset 0 1.5px 0 rgba(255,255,255,.34) !important;
}

/* ===================== Bonuses screen: option C ==========================
   The three cards each carried their own treatment — a maroon slab with a gold
   button, a plain dark box, and a light lavender card in a dark app. All three
   now use the same glass and glow as every other surface, with the lit-border
   button style established by the nav capsule. */

/* --- Certificate card --- */
html[data-theme="dark"] .cert-card{
  background:var(--surface-lit) !important;
  border:1px solid var(--glass-line) !important;
  box-shadow:var(--lift-2), var(--edge) !important;
  -webkit-backdrop-filter:blur(40px) saturate(220%) brightness(1.06);
  backdrop-filter:blur(40px) saturate(220%) brightness(1.06);
}


/* The gold CTA was the only gold in the app; now the glowing plum button. */
html[data-theme="dark"] .cert-card-cta{
  background:linear-gradient(160deg,#B06898,#6E3358) !important;
  color:#fff !important;
  border:1px solid rgba(240,190,220,.55) !important;
  box-shadow:0 0 18px -2px rgba(233,168,206,.5),
    0 8px 20px -8px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.30) !important;
}
/* Progress track picks up the palette gradient. */


html[data-theme="dark"] .mk-lbl{ color:#C6BAC1 !important; }
html[data-theme="dark"] .mk-lbl.on{ color:var(--ink) !important; }

/* --- Draw card --- */
html[data-theme="dark"] .dw{
  background:var(--surface-lit) !important;
  border:1px solid var(--glass-line) !important;
  box-shadow:var(--lift-2), var(--edge) !important;
}
html[data-theme="dark"] .dw-cta{
  background:linear-gradient(160deg,#B06898,#6E3358) !important;
  color:#fff !important;
  border:1px solid rgba(240,190,220,.55) !important;
  box-shadow:0 0 18px -2px rgba(233,168,206,.5),
    0 8px 20px -8px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.30) !important;
}


/* --- Referral card: was light lavender --- */
html[data-theme="dark"] .refer-card{
  background:var(--surface-lit) !important;
  border:1px solid var(--glass-line) !important;
  box-shadow:var(--lift-2), var(--edge) !important;
  color:var(--ink) !important;
  -webkit-backdrop-filter:blur(40px) saturate(220%) brightness(1.06);
  backdrop-filter:blur(40px) saturate(220%) brightness(1.06);
}
html[data-theme="dark"] .refer-card *{ color:inherit; }
html[data-theme="dark"] .refer-code{
  background:rgba(255,255,255,.10) !important;
  border:1px solid rgba(233,168,206,.24) !important;
}

html[data-theme="dark"] .refer-copy{
  background:rgba(233,168,206,.16) !important; color:#F0D8E6 !important;
}
html[data-theme="dark"] .refer-share{
  background:linear-gradient(160deg,#B06898,#6E3358) !important;
  color:#fff !important;
  border:1px solid rgba(240,190,220,.55) !important;
  box-shadow:0 0 18px -2px rgba(233,168,206,.5),
    0 8px 20px -8px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.30) !important;
}

html[data-theme="dark"] .refer-help,
html[data-theme="dark"] .refer-sub{ color:#CFC3CA !important; }

/* The share button reuses the code-field class with inline styles, so it needs
   targeting by its action rather than by a class of its own. */
html[data-theme="dark"] .refer-card [data-act="refer"]{
  background:linear-gradient(160deg,#B06898,#6E3358) !important;
  border:1px solid rgba(240,190,220,.55) !important;
  color:#fff !important;
  box-shadow:0 0 18px -2px rgba(233,168,206,.5),
    0 8px 20px -8px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.30) !important;
  border-radius:13px !important; height:46px !important;
}
html[data-theme="dark"] .refer-code-val{ color:#fff !important; letter-spacing:.16em; }

html[data-theme="dark"] .refer-card [data-act="refer-how"]{ color:#E9A8CE !important; opacity:1 !important; }
/* The two counters below the button. */
html[data-theme="dark"] .refer-card > div:last-child > div{
  background:rgba(255,255,255,.07);
  border:1px solid rgba(233,168,206,.18);
  border-radius:12px; padding:10px 6px;
}

/* ---- The grey flash on tab switch ----
   Every tab switch rebuilds the screen, so each card is a new element and the
   browser paints one frame before it has sampled the backdrop to blur. With
   `background` set to a translucent gradient and no colour beneath it, that
   first frame is the white gradient over nothing — which reads as grey.
   A solid plum underneath means the pre-blur frame is already in palette, so
   the transition is invisible rather than a flash. */
html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .pcard-docs,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .quick,
html[data-theme="dark"] body.glass-bg .rdrow,
html[data-theme="dark"] body.glass-bg .support-opt,
html[data-theme="dark"] body.glass-bg .home-tile,
html[data-theme="dark"] body.glass-bg .infobanner,
html[data-theme="dark"] body.glass-bg .earn-row,
html[data-theme="dark"] body.glass-bg .earn-drop,
html[data-theme="dark"] body.glass-bg .detail-hero,
html[data-theme="dark"] body.glass-bg .pdx-head,
html[data-theme="dark"] body.glass-bg .pdx-doc,
html[data-theme="dark"] body.glass-bg .dws-box,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .aicard,
html[data-theme="dark"] .pf-card,
html[data-theme="dark"] .cert-card,
html[data-theme="dark"] .dw,
html[data-theme="dark"] .refer-card,
html[data-theme="dark"] .ai-b-bot,
html[data-theme="dark"] .home-glass .glass{
  background-color:rgba(74,52,74,.55) !important;
}
/* Bars and sheets need the same base for the same reason. */
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] body.glass-bg .nav,
html[data-theme="dark"] .nav,
html[data-theme="dark"] .ai-chat-head,
html[data-theme="dark"] .ai-input-bar{
  background-color:rgba(46,33,48,.80) !important;
}

/* The redeem modal's secondary link and the tier progress lines sit on the new
   sheet base and need forcing past the earlier, less specific rules. */
html[data-theme="dark"] .modal .rd-alt,
html[data-theme="dark"] #rd-alt-toggle{ color:#E9A8CE !important; }
html[data-theme="dark"] .modal .rdrow-s,
html[data-theme="dark"] .rdrow .rdrow-s{
  color:#DCD2D8 !important; font-size:11.5px !important; font-weight:650 !important;
}

/* ==================== Cards: no backdrop blur ============================
   The grey flash on every tab switch was the browser painting a frame before
   it had sampled the backdrop to blur. Since each tab switch rebuilds the
   markup, every card is a new element and pays that cost again.

   The cards sit on a smooth gradient wash, and blurring a smooth gradient
   returns very nearly the same gradient — a flat colour matches the blurred
   result to within 4 units per channel. So the filter is removed and its
   effect baked into the colour: the flash disappears, and 14 fewer blurred
   layers composite on every frame.

   The bars and sheets keep their blur: real content scrolls behind those, and
   they are not rebuilt on a tab switch. */
html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .pcard-docs,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .quick,
html[data-theme="dark"] body.glass-bg .rdrow,
html[data-theme="dark"] body.glass-bg .support-opt,
html[data-theme="dark"] body.glass-bg .home-tile,
html[data-theme="dark"] body.glass-bg .infobanner,
html[data-theme="dark"] body.glass-bg .earn-row,
html[data-theme="dark"] body.glass-bg .earn-drop,
html[data-theme="dark"] body.glass-bg .detail-hero,
html[data-theme="dark"] body.glass-bg .pdx-head,
html[data-theme="dark"] body.glass-bg .pdx-doc,
html[data-theme="dark"] body.glass-bg .dws-box,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .aicard,
html[data-theme="dark"] .pf-card,
html[data-theme="dark"] .cert-card,
html[data-theme="dark"] .dw,
html[data-theme="dark"] .refer-card,
html[data-theme="dark"] .ai-b-bot,
html[data-theme="dark"] .home-glass .glass{
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
  background-color:rgba(82,60,84,.55) !important;
}

/* ---- Profile fields: one consistent row height ----
   The phone row renders a <span> rather than an <input>, so it was 19px tall
   against the inputs' 52px — a 33px shorter row in the middle of the card. The
   inputs also disagreed with each other by up to 3px because the date field
   carries its own line-height. Every field is now given the same explicit box,
   so all five rows measure the same. */
.pf-row{
  padding:11px 14px 12px !important;
  min-height:0 !important;
}
.pf-in, .pf-v{
  display:block !important;
  height:22px !important;
  line-height:22px !important;
  margin-top:4px !important;
  padding:0 !important;
  font-size:15px !important;
  box-sizing:content-box !important;
}
/* The date input needs its inner parts pinned too, or Safari re-introduces its
   own vertical metrics. */
.pf-in[type="date"]{ height:22px !important; line-height:22px !important; }
.pf-in[type="date"]::-webkit-date-and-time-value{ line-height:22px !important; height:22px !important; }
.pf-in[type="date"]::-webkit-datetime-edit{ line-height:22px !important; padding:0 !important; }

/* The save-result message sits between the two buttons and reserved its line
   height plus margins even when empty, pushing "Сменить пароль" 36px down for
   no reason. It collapses when there is nothing to say. */
#pf-extra-msg:empty{ display:none !important; margin:0 !important; }
.pf-ghost{ margin-top:12px !important; }

/* ---- Balance pill: the same drifting gradient as the AI label ----
   Applied to the number only, so the coin icon stays solid and the pill keeps
   a readable, static base. The palette is shifted lighter than the AI label's,
   because this text sits on a plum pill rather than on the dark capsule. */
.bal-pill span{
  font-weight:850;
  /* Stronger stops than the first attempt: with white at most positions the
     drift was barely visible. These stay light enough for contrast on the plum
     pill while actually moving through pink and lilac. */
  background:linear-gradient(90deg,
    #FFFFFF 0%, #FFB8E4 15%, #E9A8CE 30%, #B9A2F0 48%,
    #FFFFFF 66%, #FFC2E8 83%, #FFFFFF 100%);
  background-size:300% 100%;
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
  animation:aiHue 6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce){
  .bal-pill span{
    animation:none; background:none;
    -webkit-text-fill-color:currentColor; color:#fff;
  }
}

/* The card's bottom corners were squared so it would sit flush against the
   documents toggle beneath it. With that removed the card ends on a hard edge,
   so the radius is restored on all four corners. */
.pcard-wrap .ts{
  border-radius:var(--radius-card) !important;
}
.pcard-wrap{ border-radius:var(--radius-card); }

/* ---- The horizontal line above the nav ----
   The wash was painted twice: once by <body> across its own height, once by
   <html> across the viewport. The body is shorter than the screen whenever the
   content is, and a gradient stretched over 699px does not match the same
   gradient stretched over 885px — so a visible step appeared exactly where the
   body ended, on every screen.

   Only <html> paints it now, so there is one continuous gradient from the top
   of the screen to the bottom regardless of how tall the content is. */
body.glass-bg{
  background:none !important;
}

/* Two labels that sit on the lighter sheet and keep losing to earlier rules. */
html[data-theme="dark"] .pdx-doc-lbl{ color:#E4DBE0 !important; }
html[data-theme="dark"] .rdrow .rdrow-s,
html[data-theme="dark"] .rdrow.off .rdrow-s,
html[data-theme="dark"] .modal .rdrow-s{
  color:#E4DBE0 !important; opacity:1 !important;
  font-size:11.5px !important; font-weight:650 !important;
}
html[data-theme="dark"] .rdrow.off, html[data-theme="dark"] .rdrow[disabled]{ opacity:1 !important; }

/* The document tiles are dimmed to show they are not ready, but that dimmed the
   label with them. The tile still reads as inactive through its "Скоро" badge
   and muted icon, so the opacity comes off and the label stays legible. */
html[data-theme="dark"] .pdx-doc{ opacity:1 !important; }
html[data-theme="dark"] .pdx-doc-ic{ opacity:.65; }

/* ---- Joining the app to the iOS status bar ----
   iOS paints that strip pure black in an installed app; it cannot take a colour
   from the page. The topbar therefore starts black and fades into the app's own
   tone over the first 34px, so the boundary disappears.

   This fade existed but was later overwritten by a flat --bar colour applied
   with !important, which left a black strip sitting above a plum topbar. */
/* Measured on the device: iOS paints the strip with the document background
   colour (#271C28), not pure black. Fading the header from black therefore
   created a dark band exactly where the app began. The header now starts at
   that same colour, so the strip and the app are continuous. */
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] .topbar{
  background-color:transparent !important;
  background-image:linear-gradient(180deg,
    #271C28 0px,
    #2B1F2C 10px,
    rgba(46,33,48,.80) 30px,
    rgba(46,33,48,.80) 100%) !important;
}

/* The chat panel and the auth stage have their own headers rather than the
   topbar, so they need the same fade to black or the strip shows as a band
   above them. */
html[data-theme="dark"] .ai-chat-head{
  background-color:transparent !important;
  background-image:linear-gradient(180deg,
    #271C28 0px,
    #2B1F2C 10px,
    rgba(46,33,48,.72) 30px,
    rgba(46,33,48,.72) 100%) !important;
}
.authv::before{
  content:""; position:absolute; left:0; right:0; top:0; height:44px; z-index:5;
  pointer-events:none;
  background:linear-gradient(180deg, #271C28 0px, rgba(39,28,40,.75) 14px, rgba(46,18,38,0) 44px);
}

/* The auth fade sits at z-index 5 over the top of the stage, which put it in
   front of the back button and language toggle. Those need to sit above it. */
.authv-top{ position:relative; z-index:6; }

/* ==================== Solid page background ==============================
   The wash is replaced by a single colour, the same one iOS paints the status
   strip with — so the strip and the page are one continuous surface with
   nothing to match. That also removes the whole class of problem behind both
   seams found today: two nearly-identical surfaces meeting at an edge.

   With no gradient there is nothing to band, so the dither layer that existed
   to hide banding is switched off too. */
html.glass-bg,
html[data-theme="dark"].glass-bg{
  background-image:none !important;
  background-color:#271C28 !important;
}
html.glass-bg::after{ display:none !important; }   /* dither no longer needed */
.ai-anim::after{ display:none !important; }

/* The chat panel carried its own copy of the wash. */
html[data-theme="dark"] .ai-chatview{
  background-image:none !important;
  background-color:#271C28 !important;
}
/* Headers now sit on a flat page, so they need no fade — a single translucent
   tone over a solid colour is already continuous with the strip. */
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] .topbar,
html[data-theme="dark"] .ai-chat-head{
  background-image:none !important;
  background-color:rgba(46,33,48,.80) !important;
}
.authv::before{ display:none !important; }

/* On a flat page the header no longer needs its own tone — a translucent layer
   over a solid colour just produces a slightly different solid colour, which is
   exactly the 6-unit mismatch against the strip. Same colour, separated by its
   border instead. */
html[data-theme="dark"] body.glass-bg .topbar,
html[data-theme="dark"] .topbar,
html[data-theme="dark"] .ai-chat-head{
  background-color:#271C28 !important;
  border-bottom:1px solid rgba(233,168,206,.14) !important;
}
/* The auth stage stays deliberately plum, so it does need a fade to meet the
   strip; the rest of the app no longer does. */
.authv::before{
  display:block !important;
  content:""; position:absolute; left:0; right:0; top:0; height:44px; z-index:5;
  pointer-events:none;
  background:linear-gradient(180deg, #271C28 0px, rgba(39,28,40,.78) 14px, rgba(46,18,38,0) 44px);
}

/* ==================== Card edges: option 4 ==============================
   A single soft 1px rail across the top, no side bevels. The previous 2px rail
   plus a 3px left bevel converged at the rounded corner and stacked, which read
   as a white glow there — measured 15 units brighter than the same rail's
   middle. With the bevels gone that hotspot is zero.

   The page is a solid colour now, so backdrop-filter does nothing on cards;
   what makes them read as glass is the lit top edge, the shaded bottom, and the
   inner shadow that gives the card thickness. */
html[data-theme="dark"] body.glass-bg .card,
html[data-theme="dark"] body.glass-bg .ts,
html[data-theme="dark"] body.glass-bg .pcard,
html[data-theme="dark"] body.glass-bg .pcard-docs,
html[data-theme="dark"] body.glass-bg .mlist,
html[data-theme="dark"] body.glass-bg .profcard,
html[data-theme="dark"] body.glass-bg .quick,
html[data-theme="dark"] body.glass-bg .rdrow,
html[data-theme="dark"] body.glass-bg .support-opt,
html[data-theme="dark"] body.glass-bg .home-tile,
html[data-theme="dark"] body.glass-bg .infobanner,
html[data-theme="dark"] body.glass-bg .earn-row,
html[data-theme="dark"] body.glass-bg .earn-drop,
html[data-theme="dark"] body.glass-bg .detail-hero,
html[data-theme="dark"] body.glass-bg .pdx-head,
html[data-theme="dark"] body.glass-bg .pdx-doc,
html[data-theme="dark"] body.glass-bg .dws-box,
html[data-theme="dark"] body.glass-bg .cat-item,
html[data-theme="dark"] body.glass-bg .aicard,
html[data-theme="dark"] .pf-card,
html[data-theme="dark"] .cert-card,
html[data-theme="dark"] .dw,
html[data-theme="dark"] .refer-card,
html[data-theme="dark"] .ai-b-bot,
html[data-theme="dark"] .home-glass .glass{
  background-image:linear-gradient(160deg, rgba(255,255,255,.28), rgba(255,255,255,.07) 42%, rgba(255,255,255,.02)) !important;
  border:1px solid rgba(233,168,206,.30) !important;
  box-shadow:
    0 0 34px -6px rgba(233,168,206,.28),
    0 10px 22px -6px rgba(0,0,0,.44),
    0 30px 60px -20px rgba(0,0,0,.52),
    inset 0 1px 0 rgba(255,255,255,.34),
    inset 0 -2px 0 rgba(0,0,0,.52),
    inset 0 -14px 22px -14px rgba(0,0,0,.5) !important;
}
/* The card carrying the screen's main action still sits higher. */
html[data-theme="dark"] body.glass-bg .daily-card,
html[data-theme="dark"] body.glass-bg .cert-card{
  background-image:linear-gradient(160deg, rgba(255,255,255,.28), rgba(255,255,255,.07) 42%, rgba(255,255,255,.02)) !important;
  border:1px solid rgba(233,168,206,.34) !important;
  box-shadow:
    0 0 44px -6px rgba(233,168,206,.34),
    0 14px 28px -6px rgba(0,0,0,.48),
    0 40px 78px -22px rgba(0,0,0,.58),
    inset 0 1px 0 rgba(255,255,255,.38),
    inset 0 -2px 0 rgba(0,0,0,.54),
    inset 0 -16px 24px -16px rgba(0,0,0,.52) !important;
}

/* ---- Home AI card: orb in place of the mascot ----
   Layout A with the orb centred vertically rather than sitting on the baseline
   as the mascot did — a sphere has no feet, so aligning it to the bottom of the
   bubble made it look like it was resting on something. */
.aicard{ align-items:center !important; }
.aicard-m{
  width:112px !important; height:112px !important; flex:none;
  display:grid; place-items:center;
  margin:0 -8px 0 -10px !important;
  filter:none !important;
}
.card-orb{ display:block; width:112px; height:112px; }

/* ---- AI card bubble: single-path outline ----
   A rotated square tail overlapping a bordered rectangle always leaves breaks
   where the two outlines meet. The bubble and its tail are now one SVG path,
   stroked once, so the gradient runs continuously around the whole shape. */
.aicard-bub{
  position:relative !important;
  background:none !important;
  border:none !important;
  padding:0 !important;
  margin-bottom:0 !important;
  overflow:visible;
}
.aicard-bub .bub-outline{
  position:absolute; inset:0; width:100%; height:100%;
  overflow:visible; pointer-events:none;
}
.aicard-bub .bub-in{
  position:relative; z-index:1; display:block; padding:11px 13px;
}
/* The tail overhangs the bubble, so the card must not clip it. */
.aicard{ overflow:visible !important; }
.aicard-body{ min-width:0; }

/* The SVG is sized in script, so it must not be stretched by CSS. */
.aicard-bub .bub-outline{
  position:absolute; left:0; top:0; width:auto !important; height:auto !important;
  overflow:visible; pointer-events:none;
}

/* The old CSS tail is superseded by the SVG path and was still painting a dark
   diamond beside the bubble. */
.aicard-bub::after,
html[data-theme="dark"] .aicard-bub::after{ display:none !important; content:none !important; }

/* Restore the gap the bubble lost when its own margin was zeroed for the SVG
   outline — the button was sitting flush against it. */
.aicard-bub{ margin-bottom:12px !important; }

/* ---- Daily card: the days already gone ----
   Past days were drawn at 40% opacity with a border only two shades from the
   card itself, which made them effectively invisible. They now have a visible
   ring and a faint fill so the week reads as a full row with the earlier days
   clearly spent. */
html[data-theme="dark"] .daily-dot.past-blank{
  opacity:1 !important;
  background:rgba(255,255,255,.05) !important;
  border:1px dashed rgba(233,168,206,.34) !important;
}
html[data-theme="dark"] .daily-dot.miss{
  opacity:1 !important;
  background:rgba(255,255,255,.04) !important;
  border:1px solid rgba(233,168,206,.26) !important;
}
html[data-theme="dark"] .daily-dot-x{ color:#B9A6B4 !important; opacity:1 !important; }

/* ---- Daily card dots: centring and legibility ----
   The dots were display:grid with align-items:center only, so their contents
   were centred vertically but left to stretch horizontally. place-items plus a
   text-align centres them on both axes. The labels were also 10.5px in a muted
   grey, which is small and dim for the one number on the card that tells you
   what you are about to earn. */
.daily-dot{
  display:grid !important;
  place-items:center !important;
  place-content:center !important;
  text-align:center !important;
  line-height:1 !important;
}
html[data-theme="dark"] .daily-dot{
  font-size:12.5px !important;
  font-weight:800 !important;
  color:#EDE2E9 !important;
}
html[data-theme="dark"] .daily-dot-x{
  font-size:12.5px !important;
  font-weight:800 !important;
  color:#EDE2E9 !important;
  line-height:1 !important;
  display:block !important;
}
/* The day already claimed keeps its tick prominent. */
html[data-theme="dark"] .daily-dot.fill{ color:#FFFFFF !important; }
html[data-theme="dark"] .daily-dot.fill svg{ width:17px; height:17px; }
/* Missed days: a clear cross rather than a faint mark. */
html[data-theme="dark"] .daily-dot.miss .daily-dot-x,
html[data-theme="dark"] .daily-dot.past-blank .daily-dot-x{
  color:#C9B6C4 !important; font-size:14px !important;
}

/* The cross rendered at 12px against the tick's 17px, so a missed day read as
   fainter than a claimed one even at the same colour. Matched in size and given
   a slightly heavier stroke so it holds up at this scale. */
html[data-theme="dark"] .daily-dot.miss svg{
  width:15px !important; height:15px !important;
  stroke-width:2.4 !important;
  color:#D9C8D4 !important;
}
html[data-theme="dark"] .daily-dot.fill svg{
  width:17px !important; height:17px !important; stroke-width:2.6 !important;
}

/* ---- Auth screens: the dark band at the top ----
   The stage was faded to the page colour over 44px so it would meet the status
   strip. Over that short a distance a jump from #271C28 to plum reads as a dark
   header bar rather than a blend. The stage's own gradient now begins at the
   page colour and grows into plum across the whole upper third, so there is no
   edge to see. */
.authv::before{ display:none !important; }
/* The stage begins at exactly the colour iOS paints the strip with, so the two
   are continuous and there is no header band to see. */
.authv{
  background:linear-gradient(174deg,
    #54203F 0%,
    #5A2243 14%,
    #5E2445 34%,
    #4A1D3A 62%,
    #351428 86%,
    #2A1020 100%) !important;
}

/* ---- Splash and auth: matching the status strip ----
   The splash faded from #000000, which put a black bar above it wherever the
   strip was another colour. It now takes the same colour the pre-paint script
   gives the document. The auth stage likewise begins at the strip colour, and
   its top fade is retired — over 44px that fade read as a dark header band. */
#boot,
html[data-theme="dark"] #boot{
  background:var(--boot-bg, #271C28) !important;
}
.authv::before{ display:none !important; content:none !important; }
.authv{
  background:linear-gradient(174deg,
    #54203F 0%,
    #5A2243 14%,
    #5E2445 34%,
    #4A1D3A 62%,
    #351428 86%,
    #2A1020 100%) !important;
}

/* ---- Chat button ----
   var(--plum) in dark mode is #C9A0BC — bright but desaturated, so against a
   plum page it read as background rather than as a control. A light circle with
   a dark icon separates cleanly and is unambiguously tappable. */
html[data-theme="dark"] .chat-fab{
  background:#F7EDF3 !important;
  color:#4A1E38 !important;
  box-shadow:
    0 6px 20px rgba(0,0,0,.50),
    0 2px 6px rgba(0,0,0,.35),
    inset 0 -1px 0 rgba(0,0,0,.12),
    inset 0 1px 0 rgba(255,255,255,.85) !important;
}
html[data-theme="dark"] .chat-fab svg{ color:#4A1E38 !important; }
/* The unread dot needs to hold up against a light button now. */
html[data-theme="dark"] .chat-fab-dot{
  background:#E0453C !important;
  border:2px solid #F7EDF3 !important;
}

/* ---- Notification bell ----
   The button was the icon and nothing else: a 16x16 tap target, against 44px
   recommended and 32-40px for everything beside it in the header. It now has a
   40px hit area with the icon centred inside, and a brighter colour so it sits
   at the same weight as the balance and the avatar. */
.bell-btn{
  width:40px !important; height:40px !important;
  padding:0 !important;
  display:grid !important; place-items:center !important;
  background:none !important; border:none !important;
  border-radius:50% !important;
  -webkit-tap-highlight-color:transparent;
}
html[data-theme="dark"] .bell-btn{ color:#EDE2E9 !important; }
.bell-btn svg{ width:19px !important; height:19px !important; }
/* Pressed state, since there is no container to shade. */
.bell-btn:active{ background:rgba(255,255,255,.10) !important; }
/* The dot follows the icon rather than the old 16px box. */
.bell-dot{
  top:7px !important; right:7px !important;
  width:9px !important; height:9px !important;
  border:2px solid #271C28 !important;
}

/* The unread dot at 7px sat directly on the bell's upper-right stroke, eating
   into the dome so the icon looked cropped. Moved clear of the glyph: the icon
   is 19px centred in a 40px button, so its top-right corner is about 10px in
   from the button edge — the dot now sits just outside that. */
.bell-dot{
  top:5px !important; right:4px !important;
  width:10px !important; height:10px !important;
  border:2px solid #271C28 !important;
  box-shadow:0 0 0 1px rgba(39,28,40,.9);
}

/* ---- Coin: one turn every 3 seconds ----
   Rotated about the vertical axis so it reads as a coin flipping edge-on rather
   than spinning like a wheel. scaleX is used instead of rotateY because a real
   3D transform on an inline SVG inside a flex row can shift its layout box on
   iOS; scaling the width produces the same silhouette without touching layout. */
@keyframes coinFlip{
    0%   { transform:scaleX(1); }
   25%   { transform:scaleX(.06); }
   50%   { transform:scaleX(-1); }
   75%   { transform:scaleX(-.06); }
  100%   { transform:scaleX(1); }
}
.bal-pill .coin-spin{
  animation:coinFlip 3s linear infinite;
  transform-origin:50% 50%;
  will-change:transform;
  flex:none;
}
@media (prefers-reduced-motion: reduce){
  .bal-pill .coin-spin{ animation:none; }
}


@media (prefers-reduced-motion: reduce){
  .bal-pill .coin-spin .coin-face{ animation:none; opacity:1; }
}

/* ---- Coin: two faces through the flip ----
   A flip mirrors whatever it rotates, so a single B would read backwards on the
   far side. The coin carries two B groups — the reverse one is pre-mirrored, so
   when the coin itself is flipped the letter comes out the right way round. The
   two swap at the moments the coin passes edge-on. */
.bal-pill .coin-spin .coin-back{ opacity:0; }
@keyframes coinFrontFace{
    0%{opacity:1} 23%{opacity:1} 26%{opacity:0}
   74%{opacity:0} 77%{opacity:1} 100%{opacity:1}
}
@keyframes coinBackFace{
    0%{opacity:0} 23%{opacity:0} 26%{opacity:1}
   74%{opacity:1} 77%{opacity:0} 100%{opacity:0}
}
.bal-pill .coin-spin .coin-front{ animation:coinFrontFace 3s linear infinite; }
.bal-pill .coin-spin .coin-back { animation:coinBackFace  3s linear infinite; }
@media (prefers-reduced-motion: reduce){
  .bal-pill .coin-spin .coin-front{ animation:none; opacity:1; }
  .bal-pill .coin-spin .coin-back { animation:none; opacity:0; }
}

/* ==================== Daily card: the 7-day cycle =======================
   Completed days brighten toward the milestone so the row reads as a climb
   rather than a set of identical marks. The first step is lifted well clear of
   the card so day 1 still reads as claimed rather than pending. */
html[data-theme="dark"] .daily-dot.fill.step1{ background:#63456841 !important; }
html[data-theme="dark"] .daily-dot.fill.step1{ background:#5E4159 !important; border:1px solid #8A5C7C !important; }
html[data-theme="dark"] .daily-dot.fill.step2{ background:#674762 !important; border:1px solid #93628A !important; }
html[data-theme="dark"] .daily-dot.fill.step3{ background:#714C6B !important; border:1px solid #9C6894 !important; }
html[data-theme="dark"] .daily-dot.fill.step4{ background:#7B5274 !important; border:1px solid #A66F9D !important; }
html[data-theme="dark"] .daily-dot.fill.step5{ background:#85587D !important; border:1px solid #B075A6 !important; }
html[data-theme="dark"] .daily-dot.fill.step6{ background:#8F5E86 !important; border:1px solid #BA7BAF !important; }
html[data-theme="dark"] .daily-dot.fill.step7{ background:#995F8D !important; border:1px solid #C481B8 !important; }
html[data-theme="dark"] .daily-dot.fill{ color:#FFFFFF !important; }

/* The milestone dot carries the week's payoff, so it is lifted like a button. */
html[data-theme="dark"] .daily-dot.mile{
  background:linear-gradient(160deg,#8A5478,#5A2A46) !important;
  border:1px solid rgba(240,190,220,.6) !important;
  box-shadow:0 0 14px -2px rgba(233,168,206,.5) !important;
}
/* Its number uses the same drifting gradient as the balance and the AI label,
   so "the reward" reads the same way everywhere in the app. */
.daily-dot .daily-dot-x.mile-num{
  font-weight:850;
  background:linear-gradient(90deg,
    #FFFFFF 0%, #FFB8E4 15%, #E9A8CE 30%, #B9A2F0 48%,
    #FFFFFF 66%, #FFC2E8 83%, #FFFFFF 100%);
  background-size:300% 100%;
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
  animation:aiHue 6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce){
  .daily-dot .daily-dot-x.mile-num{
    animation:none; background:none;
    -webkit-text-fill-color:currentColor; color:#FFFFFF;
  }
}

/* ---- Day 7, not yet earned ----
   Filled means claimed everywhere else in the row, so the milestone must not be
   filled until it is. It carries the same pink-to-violet gradient ring as the
   AI card's speech bubble, so "the reward" reads the same way in both places.
   The inner layer must be opaque or the gradient shows through the centre —
   #3F2E40 is exactly what the card composites to. */
html[data-theme="dark"] .daily-dot.mile{
  border:2px solid transparent !important;
  background:
    linear-gradient(#3F2E40, #3F2E40) padding-box,
    linear-gradient(120deg, #F3C7E0 0%, #E9A8CE 42%, #9B6ACF 100%) border-box !important;
  box-shadow:
    0 0 16px -2px rgba(233,168,206,.55),
    0 0 34px -8px rgba(155,106,207,.45) !important;
}
html[data-theme="dark"] .daily-dot.fill.step7{
  background:#995F8D !important;
  border:1px solid #C481B8 !important;
  box-shadow:0 0 14px -3px rgba(233,168,206,.45) !important;
}

/* ---- Support chat: agent avatar ---------------------------------------- */
.chat-av{
  width:28px; height:28px; border-radius:50%; flex:none; overflow:hidden;
  display:grid; place-items:center; align-self:flex-end; margin-bottom:2px;
  background:#433041; border:1px solid rgba(233,168,206,.26);
}
.chat-av img{ width:100%; height:100%; object-fit:cover; display:block; }
.chat-av.head{ width:36px; height:36px; align-self:center; margin:0; }
/* Shown until a photo loads, and if one is missing. */
.chat-av.fallback{
  background:
    radial-gradient(circle at 50% 34%, #C9A0BC 0 34%, transparent 35%),
    radial-gradient(ellipse 78% 60% at 50% 108%, #C9A0BC 0 60%, transparent 61%),
    #433041;
}
.chat-av.searching{ animation:agentPulse 1.4s ease-in-out infinite; }
@keyframes agentPulse{ 0%,100%{opacity:.5} 50%{opacity:1} }

/* The "looking for an agent" line is chat furniture, not an agent speaking. */
html[data-theme="dark"] .ai-bubble.chat-sys{
  background:rgba(255,255,255,.06) !important;
  border:1px dashed rgba(233,168,206,.28) !important;
  color:#CFC3CA !important;
  display:inline-flex; align-items:center; gap:8px;
}
.chat-dots{ display:inline-flex; gap:3px; }
.chat-dots i{
  width:4px; height:4px; border-radius:50%; background:#C9A0BC; display:block;
  animation:chatDot 1.2s ease-in-out infinite;
}
.chat-dots i:nth-child(2){ animation-delay:.15s; }
.chat-dots i:nth-child(3){ animation-delay:.30s; }
@keyframes chatDot{ 0%,60%,100%{opacity:.3; transform:translateY(0)} 30%{opacity:1; transform:translateY(-2px)} }

/* System notices sit centred, clearly not from either party. */
.chat-joined{
  text-align:center; font-size:11px; color:#C6BAC1; font-weight:650;
  padding:4px 0; margin:2px 0;
}
.chat-joined.chat-closed{ color:#B9A6B4; }
.chat-sub{ font-size:11.5px; color:var(--muted); display:flex; align-items:center; gap:5px; }
.chat-live{ width:6px; height:6px; border-radius:50%; background:#8FD3A6; display:block; flex:none; }
@media (prefers-reduced-motion: reduce){
  .chat-av.searching, .chat-dots i{ animation:none; }
}

/* The bubble's 86% cap was set when bot rows had no avatar. With a 28px avatar
   and an 8px gap the bubble overran the row and sat under it. */
.ai-row.ai-bot{ align-items:flex-end; gap:8px; }
.ai-row.ai-bot .chat-av{ flex:0 0 28px; }
.ai-row.ai-bot .ai-bubble{
  max-width:calc(100% - 44px) !important;
  min-width:0;
}
.ai-row.ai-bot .ai-bubble.chat-sys{ max-width:calc(100% - 44px) !important; }

/* Bot rows from earlier sessions carry no avatar, so they need the same
   indent as the ones that do — otherwise the thread steps sideways. */
.ai-row.ai-bot.no-av{ padding-left:36px; }
/* The agent's typing bubble: dots only, sized like a short message. */
html[data-theme="dark"] .ai-bubble.chat-typing{
  padding:13px 14px !important;
  min-width:0;
}
.ai-bubble.chat-typing .chat-dots i{ width:5px; height:5px; }

/* An unaffordable tier is disabled, so tapping it does nothing — which reads
   as "the selection is broken" rather than "you cannot afford this yet".
   Making the unavailable state obvious removes the ambiguity. */
html[data-theme="dark"] .rdrow.off{
  cursor:default;
}
html[data-theme="dark"] .rdrow.off .rdrow-t{ color:#B9A6B4 !important; }
html[data-theme="dark"] .rdrow.off img{ opacity:.55; }
/* The selected tier needs to be unmistakable: it is pre-selected on open, so a
   faint highlight looks like nothing happened when you tap it. */
html[data-theme="dark"] .rdrow.on{
  border:2px solid #E9A8CE !important;
  box-shadow:0 0 16px -3px rgba(233,168,206,.5) !important;
  background:rgba(233,168,206,.10) !important;
}

/* The selected tier was invisible: the glass-card rule for .rdrow carries
   `body.glass-bg` and !important, so it outranked a plainer .rdrow.on. Tapping
   a tier worked all along — nothing on screen changed, which reads as the
   selection being broken. Matching the specificity fixes it. */
html[data-theme="dark"] body.glass-bg .rdrow.on,
html[data-theme="dark"] .modal .rdrow.on{
  border:2px solid #E9A8CE !important;
  background-color:rgba(233,168,206,.13) !important;
  box-shadow:
    0 0 18px -3px rgba(233,168,206,.55),
    inset 0 1px 0 rgba(255,255,255,.30) !important;
}

/* ---- Certificate delivery: alternate number ----
   The bare box asked for "the number linked to Kaspi" without saying what a
   valid one looks like, and gave no feedback until the exchange was attempted.
   It now matches the login field — fixed +7, ten digits, formatted as typed —
   and states validity while typing. */
.rd-fld{ margin-top:2px; }
html[data-theme="dark"] .modal .rd-fld{
  background:rgba(255,255,255,.07) !important;
  border:1px solid rgba(233,168,206,.26) !important;
  border-radius:14px !important;
  transition:border-color .16s ease, box-shadow .16s ease;
}
html[data-theme="dark"] .modal .rd-fld .authv-pf{ color:#EDE2E9 !important; }
html[data-theme="dark"] .modal .rd-fld input{ color:#F4EDF1 !important; }
html[data-theme="dark"] .modal .rd-fld input::placeholder{ color:#9C8FA0 !important; }
/* A complete number confirms itself; an incomplete one says so without waiting
   for the customer to submit. */
html[data-theme="dark"] .modal .rd-fld.ok{
  border-color:rgba(143,211,166,.65) !important;
  box-shadow:0 0 12px -4px rgba(143,211,166,.45) !important;
}
html[data-theme="dark"] .modal .rd-fld.bad{
  border-color:rgba(224,69,60,.55) !important;
}
.rd-fld .rd-fld-ok{
  margin-left:auto; display:none; color:#8FD3A6; flex:none;
}
.rd-fld .rd-fld-ok svg{ width:17px; height:17px; }
.rd-fld.ok .rd-fld-ok{ display:block; }
.rd-fld-hint{
  font-size:11px; color:#B9A6B4; margin:6px 2px 0;
}

/* ---- Toast ----
   It used `background: var(--ink)` with white text, which works in light mode
   where --ink is near-black. In dark mode --ink is #F4EDF1, so every toast was
   white text on a white pill — invisible. It now uses the app's own surface
   treatment so it reads as part of the interface rather than an inversion. */
html[data-theme="dark"] .toast{
  background:#3A2A3C !important;
  color:#F4EDF1 !important;
  border:1px solid rgba(233,168,206,.34);
  box-shadow:
    0 0 26px -6px rgba(233,168,206,.30),
    0 10px 30px -8px rgba(0,0,0,.60),
    inset 0 1px 0 rgba(255,255,255,.20) !important;
  /* Long messages were clipped to one line; the claim errors we added can run
     to a sentence. */
  white-space:normal !important;
  text-align:center;
  line-height:1.4;
  max-width:calc(100vw - 48px) !important;
  overflow:visible !important;
  text-overflow:clip !important;
}

/* ---- Input bar while the keyboard is up ----
   The bar reserves the home-indicator inset at its foot. With the keyboard
   covering that strip the inset is reserving space for something that is not
   on screen, leaving the bar floating a home-indicator's height above the
   keys. It comes off while the keyboard is open and returns when it closes. */
body.kb-open .ai-input-bar{
  padding-bottom:8px !important;
}
/* The thread can then use the space the inset was holding. */
body.kb-open .ai-thread{
  padding-bottom:4px;
}

/* ---- Message times and date dividers ---- */
.msg-meta{
  display:inline-flex; align-items:center; gap:4px;
  margin-left:8px; float:right; margin-top:4px;
  white-space:nowrap;
}
.msg-time{ font-size:10.5px; opacity:.62; font-weight:600; }
html[data-theme="dark"] .ai-b-bot .msg-time{ color:#C6BAC1; }
html[data-theme="dark"] .ai-b-user .msg-time{ color:rgba(255,255,255,.78); }
/* A divider whenever the day changes, so replies days apart do not read as one
   continuous conversation. */
.chat-day{
  display:flex; align-items:center; gap:10px;
  margin:6px 0 2px; padding:0 4px;
}
.chat-day::before, .chat-day::after{
  content:""; flex:1; height:1px; background:rgba(233,168,206,.16);
}
.chat-day span{
  font-size:10.5px; font-weight:700; color:#B9A6B4;
  text-transform:lowercase; letter-spacing:.01em;
}

/* ---- More tab: icon sizing ----
   The icons come from the shared set, each carrying its own width, height and
   stroke-width — 13px to 23px, strokes 1.7 to 2.0. In a vertical list of rows
   that reads as sloppy: the row labels line up but the marks beside them do
   not. The container is 22px, so the icon is sized to fill it and the stroke
   normalised, regardless of what each glyph declares. */
.mrow-ico svg{
  width:21px !important;
  height:21px !important;
  stroke-width:1.85 !important;
}

/* ---- Ways to earn: trigger ----
   A quiet outlined link, not a card. It sits above the certificate and draw
   cards, which are the things to act on — this only explains where points come
   from, so it should be easy to find without competing for the same attention.
   The dashed edge marks it as informational rather than an action. */
.earn-open{
  width:100%; display:flex; align-items:center; justify-content:center; gap:8px;
  padding:13px 14px; margin-bottom:16px;
  border-radius:15px; cursor:pointer;
  background:none;
  border:1px dashed rgba(233,168,206,.30);
  box-shadow:none;
}
.earn-open:active{ background:rgba(233,168,206,.06); }
.earn-open-ico{ display:grid; place-items:center; color:#E9A8CE; flex:none; }
.earn-open-ico svg{ width:16px; height:16px; }
.earn-open-t{ font-size:13px; font-weight:800; color:#E9A8CE; }

/* The sheet */
.earn-sheet-head{ display:flex; align-items:center; justify-content:space-between; }
.earn-sheet-head h3{ font-size:17px; font-weight:850; color:#F4EDF1; margin:0; }
.earn-sheet-sub{ font-size:12.5px; color:#CFC3CA; margin:4px 0 14px; line-height:1.4; }
.earn-sheet-list{ display:flex; flex-direction:column; gap:8px; }
html[data-theme="dark"] .earn-sheet-list .earn-row{
  display:flex; align-items:center; gap:12px;
  padding:11px 12px; border-radius:14px;
  background:rgba(255,255,255,.05);
  border:1px solid rgba(233,168,206,.18);
}
.earn-sheet-list .earn-icon{
  width:34px; height:34px; border-radius:11px; flex:none;
  display:grid; place-items:center;
  background:rgba(233,168,206,.14); color:#E9A8CE;
}
.earn-sheet-list .earn-icon svg{ width:17px; height:17px; }
.earn-row-body{ flex:1; min-width:0; }
html[data-theme="dark"] .earn-sheet-list .earn-title{
  display:block; font-size:13.5px; font-weight:800; color:#F4EDF1;
}
.earn-note{ display:block; font-size:11px; color:#B9A6B4; margin-top:2px; line-height:1.35; }
html[data-theme="dark"] .earn-sheet-list .earn-pts{
  flex:none; font-size:14px; font-weight:850; color:#8FD3A6;
}
.earn-sheet-foot{
  font-size:11px; color:#B9A6B4; margin:14px 2px 0; line-height:1.45; text-align:center;
}

/* ---- Ways to earn: amount-led rows ----
   The amount moved to the front of the row. A column of numbers can be read at
   a glance; a column of identical icons cannot. The gradient is the balance's,
   so the two read as the same currency. */
.earn-sheet-list .earn-amt{
  flex:none; width:64px; text-align:center;
}
.earn-sheet-list .earn-amt b{
  display:block; font-size:18px; font-weight:860; line-height:1.15;
  background:linear-gradient(90deg, #FFFFFF, #FFB8E4 40%, #B9A2F0);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}
.earn-sheet-list .earn-amt span{
  display:block; font-size:9.5px; font-weight:700; letter-spacing:.04em;
  color:#9C8FA0; margin-top:1px;
}
/* A rule separates the amount from what earns it, so the two columns stay
   distinct without another background. */
html[data-theme="dark"] .earn-sheet-list .earn-row-body{
  border-left:1px solid rgba(233,168,206,.16);
  padding-left:13px;
}
html[data-theme="dark"] .earn-sheet-list .earn-row{
  gap:13px; padding:12px;
}
@media (prefers-reduced-motion: reduce){
  .earn-sheet-list .earn-amt b{
    background:none; -webkit-text-fill-color:#F4EDF1; color:#F4EDF1;
  }
}

/* ---- Primary buttons: one treatment ----
   The three main actions had drifted apart — the daily claim on Home was 46px
   with a 13px radius and a plum gradient; the certificate button was 40px and
   a full pill in a lighter plum; the share button matched neither in type. The
   daily button is the reference, since it is the one people see most.
   Applied by name rather than a shared class so no markup has to change. */
html[data-theme="dark"] .cert-card-cta,
html[data-theme="dark"] .refer-code,
html[data-theme="dark"] .dw-cta-btn{
  height:46px !important;
  border-radius:13px !important;
  background-image:linear-gradient(rgb(110,64,93), rgb(74,30,56) 56%, rgb(61,41,53)) !important;
  background-color:transparent !important;
  color:#FFFFFF !important;
  font-size:14px !important;
  font-weight:760 !important;
  border:none !important;
  box-shadow:
    0 8px 20px -8px rgba(0,0,0,.55),
    inset 0 1px 0 rgba(255,255,255,.26),
    inset 0 -2px 0 rgba(0,0,0,.28) !important;
}
html[data-theme="dark"] .cert-card-cta:active,
html[data-theme="dark"] .refer-code:active{
  transform:scale(.99);
}

/* A range like "5–20" is wider than a single figure; let it shrink rather than
   wrap or push the description across. */
.earn-sheet-list .earn-amt b{ font-size:18px; }
.earn-sheet-list .earn-amt b:not(:empty){ white-space:nowrap; }
.earn-sheet-list .earn-amt{ width:72px; }

/* ---- Install gate: nothing from the app shell ----
   The gate is shown before the app exists, so the navigation, its AI disc, the
   chat button and the top bar have nothing to act on. Hiding them by class as
   well as inline style means a stray re-render cannot put a glowing capsule
   across the bottom of the screen with nothing behind it. */
body.install-gate .nav,
body.install-gate #nav,
body.install-gate .nav-ai-disc,
body.install-gate .topbar,
body.install-gate .chat-fab,
body.install-gate #chat-layer{
  display:none !important;
}

/* ---- Install gate: help ----
   Sits after the steps, for someone the steps have not worked for. WhatsApp
   rather than more instructions: this is before the app exists, so the in-app
   chat is not available, and someone stuck on step 2 has already shown that
   written steps are not landing. */
.ig-help{
  margin-top:22px; padding-top:20px;
  border-top:1px solid rgba(233,168,206,.16);
  text-align:center;
}
.ig-help-t{ font-size:14px; font-weight:840; color:#F4EDF1; }
.ig-help-s{ font-size:12px; color:#B9A6B4; margin:4px 0 13px; line-height:1.4; }
.ig-help-wa{
  width:100%; height:48px; border-radius:14px; border:none; cursor:pointer;
  display:flex; align-items:center; justify-content:center; gap:9px;
  background:#25D366; color:#08301A;
  font-size:14px; font-weight:840; font-family:inherit;
  box-shadow:0 8px 20px -8px rgba(37,211,102,.45);
}
.ig-help-wa:active{ transform:scale(.99); }
.ig-help-wa svg{ width:19px; height:19px; flex:none; }

/* ================= Spacing scale ==================
   Gaps between top-level elements had drifted to 2, 4, 6, 8, 10, 12, 14, 16,
   18, 26 and 30px across the app — eleven values with no relationship, so
   nothing lined up between screens. These are the recurring elements, put on a
   4px scale: 8 / 12 / 16 / 24. Applied to the shared classes rather than each
   screen, so every page inherits the same rhythm. */

/* Screen title block. The subtitle belongs to the title, so it sits close;
   the space below separates the block from the content. */
.ptitle{ margin-bottom:4px !important; }
.psub{ margin:0 0 20px !important; }

/* A section label introduces what follows, so it sits nearer to it than to
   what came before — 24 above, 8 below, rather than 30 and 12. */
.section-label{ margin:24px 0 8px !important; }
/* The first one on a screen has the title block above it already. */
.screen > .section-label:first-of-type{ margin-top:8px !important; }

/* Cards stacked directly on one another. */
.screen > .cert-card + .section-label,
.screen > .refer-card + .section-label{ margin-top:24px !important; }

/* Sub-screens: title, then straight into content. */
.pf-top, .fq-top{ margin-bottom:12px !important; }

/* Home and the giveaway page kept their own margins — 14, 26, 6, 18 — set
   before the scale existed. Brought onto the same 4px steps: cards 16 apart,
   section heads 24 above and 12 below, and the greeting block tight. */
.greet-h1{ margin-top:0 !important; }
.greet-sub{ margin:2px 0 16px !important; }
.daily-card{ margin-top:0 !important; }
.aicard{ margin-top:16px !important; }
.sec-head{ margin:24px 0 12px !important; }
.qgrid{ margin-top:0 !important; }

.home .psub, .screen > .psub{ margin-bottom:12px !important; }

/* Giveaway page. */
.dws-hero{ margin-top:8px !important; }
.dws-k{ margin-top:16px !important; }
.dws-t{ margin-top:4px !important; }
.dws-endslbl{ margin-top:16px !important; }
.dws-timer{ margin-top:8px !important; }
.dws-box{ margin-top:16px !important; }
.dws-rules-t{ margin:20px 0 8px !important; }
.dws-cta{ margin-top:20px !important; }

/* Profile and FAQ, the last two off the scale. */
.pf-reward{ margin:12px 0 12px !important; }
.pf-note{ margin-top:12px !important; }
.pf-save{ margin-top:16px !important; }
.pf-ghost{ margin-top:12px !important; }
.detail-hero{ margin-bottom:16px !important; }
.add-btn{ margin-top:20px !important; }

/* ================= Type scale ==================
   The app declares a nine-step scale but renders nineteen sizes, including
   half-pixel values — 9.5, 10.5, 11.5, 12.5, 14.5, 15.5 — that came from
   nudging individual elements rather than choosing a step. Half-pixels also
   round unpredictably between devices, so the same label is not the same size
   on two phones.

   Two rules: nothing below 11px, and no fractional sizes. 11px is the floor
   for a label someone actually has to read on a phone; below that it is
   decoration.  */

/* Uppercase kickers and labels — were 9.5 to 10.5px. */
.dw-badge, .ts-k, .dws-k, .mk-lbl, .pf-k, .daily-lbl,
.earn-amt span, .earn-sheet-list .earn-amt span,
.cd-k, .rd-k, .nt-k{
  font-size:11px !important;
  letter-spacing:.05em;
}
/* The countdown's unit labels sit under large numbers, so they can stay small
   but not fractional. */
.dws-timer i, .dw-timer i{ font-size:11px !important; }

/* Fractional body sizes rounded to the nearest step. */
.psub, .earn-open-s, .ig-help-s{ font-size:13px !important; }
.earn-note, .chat-sub, .msg-time{ font-size:11px !important; }
.earn-title, .mrow-lbl, .earn-open-t{ font-size:14px !important; }
.dws-t, .cert-card-t{ font-size:15px !important; }

/* The rest of the fractional sizes, rounded to the nearest step. Buttons and
   card titles to 15/14, secondary lines to 12, small labels to 11. */
.pf-save, .dws-cta, .add-btn, .addcard-t{ font-size:15px !important; }
.ts-kind{ font-size:15px !important; }
.aicard-cta, .ts-v, .daily-dot-x{ font-size:13px !important; }
.addcard-s, .dw-s, .pf-note, .pg-txt{ font-size:12px !important; }
/* The milestone number sits in a 44px circle, so it holds its own size. */
.daily-dot-x.mile-num{ font-size:13px !important; }

/* The last two fractional sizes, overridden later in the sheet than the rules
   that set them. */
html[data-theme="dark"] .daily-dot .daily-dot-x,
html[data-theme="dark"] .daily-dot .daily-dot-x.mile-num{ font-size:13px !important; }
.dws-rules, .dws-rules li{ font-size:13px !important; }

/* ---- Install carousel: swipe ----
   The image follows the finger so the gesture is acknowledged before the slide
   changes; without it a swipe feels like it did nothing until it suddenly did.
   `touch-action: pan-y` lets the page scroll vertically while the carousel
   claims horizontal movement. */
.ig-car{ touch-action:pan-y; }
.ig-car-img{
  transform:translateX(var(--drag, 0px));
  transition:transform .18s cubic-bezier(.32,.72,0,1);
}
.ig-car[style*="--drag"] .ig-car-img{ transition:none; }
.ig-car-cap{
  transform:translateX(calc(var(--drag, 0px) * 0.4));
  transition:transform .18s cubic-bezier(.32,.72,0,1);
}
.ig-car[style*="--drag"] .ig-car-cap{ transition:none; }
/* The arrows stay — a swipe is not discoverable on its own, and someone on a
   desktop browser has no other way through. */

/* ---- Install carousel scrim, with an image behind it ----
   The scrim carries a plum gradient beneath its darkening layer, from when the
   carousel had no image and needed a background of its own. With a real image
   the two stack and the caption area falls to near-black — the headline
   measured 2.39:1, below the 4.5:1 the rest of the app holds to.

   The second layer is dropped when an image is present, and the darkening
   eased: the supplied artwork already fades to #2A0F22 at its foot, so the
   scrim only has to guarantee legibility, not create the fade itself. */
.ig-car:has(.ig-car-img) .ig-car-scrim{
  background:linear-gradient(180deg,
    rgba(20,8,16,.10) 0%,
    rgba(20,8,16,0) 34%,
    rgba(20,8,16,.40) 72%,
    rgba(20,8,16,.62) 100%) !important;
}
/* The caption sits on its own solid ground rather than on whatever the artwork
   happens to be. A text-shadow was tried first and did not help: the audit
   measures the darkest pixel behind the type, and the artwork itself is nearly
   black there — white on #1E0716 is 2.38:1, well under the 4.5:1 the rest of
   the app holds to. A defined band guarantees the contrast whatever image is
   behind it, including the two still to come. */
.ig-car:has(.ig-car-img) .ig-car-cap{
  bottom:0; padding:26px 26px 34px;
  background:linear-gradient(180deg,
    rgba(42,15,34,0) 0%,
    rgba(42,15,34,.86) 26%,
    rgba(42,15,34,.97) 60%,
    #2A0F22 100%);
}
.ig-car-cap h2{ text-shadow:0 2px 10px rgba(12,4,10,.6); }

/* ---- Auth landing: photograph ----
   The screen was 60% empty plum with three soft circles. The image occupies
   that space and fades into the panel below rather than meeting it at a hard
   edge — the render ends near black while the screen is plum, so the seam would
   otherwise be obvious. The blobs are dropped here: two textures competing. */
.authv-landing .authv-blobs,
.authv-landing .authv-blob{ display:none !important; }
.authv-art{
  position:absolute; inset:0 0 auto 0;
  height:62%;
  overflow:hidden;
  z-index:0;
  pointer-events:none;
}
.authv-art img{
  width:100%; height:100%; object-fit:cover; object-position:center top;
  display:block;
}
/* The fade carries the image into the copy panel. It has to start well above
   the join or the transition reads as a band rather than a dissolve. */
.authv-art-fade{
  position:absolute; inset:auto 0 0 0; height:46%;
  background:linear-gradient(to bottom,
    rgba(51,19,38,0) 0%,
    rgba(51,19,38,.45) 42%,
    rgba(51,19,38,.86) 74%,
    #4A1C38 100%);
}
/* The copy sits above the image, and the hero is pushed down so it starts
   below the photograph rather than over it. */
.authv-landing .authv-top,
.authv-landing .authv-hero{ position:relative; z-index:2; }
.authv-landing .authv-hero{ margin-top:auto; }

/* ---- Catalogue: feature slots ----
   Each slot is a close-up of a real component. The image proves the feature
   exists; the caption says what it does for the customer. A product without
   feature data renders nothing here rather than a placeholder. */
.cat-feat{ margin-top:20px; }
.cat-feat-img{
  height:196px; border-radius:16px; overflow:hidden;
  border:1px solid rgba(233,168,206,.16);
  background:rgba(255,255,255,.035);
}
.cat-feat-img img{
  width:100%; height:100%; object-fit:cover; display:block;
}
.cat-feat-k{
  font-size:11px; font-weight:800; letter-spacing:.1em; text-transform:uppercase;
  color:#E9A8CE; margin-top:13px;
}
.cat-feat-s{
  font-size:13px; color:#CFC3CA; line-height:1.55; margin-top:6px;
}

/* ---- Home catalogue: photographic cards ----
   Was a horizontal scroll of 152px tiles showing the product render on a flat
   surface. Now a stacked list where each card is a photograph of the product
   in use, with the name over it — the image does the selling, not a cutout on
   a field. The scrim runs bottom to top so it darkens the empty base rather
   than the subject, which sits centred in these compositions. */
/* Horizontal carousel rather than a stack. Eight products as full-width cards
   was a very long scroll on Home, and the catalogue is something to browse
   past, not read through. Cards are wide enough to carry a photograph and
   narrow enough that the next one peeks in, which is what invites the swipe. */
.cat-list{
  display:flex; gap:12px;
  overflow-x:auto; overflow-y:hidden;
  scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;
  /* Bleed to the screen edges so the row reads as continuing beyond them. */
  margin:0 -20px; padding:2px 20px 8px;
  scrollbar-width:none;
}
.cat-list::-webkit-scrollbar{ display:none; }
.cat-card{
  position:relative; display:block;
  flex:0 0 auto; width:311px; height:186px;
  scroll-snap-align:start;
  border-radius:18px; overflow:hidden; padding:0; cursor:pointer;
  border:1px solid rgba(233,168,206,.16);
  background:rgba(255,255,255,.04);
  text-align:left;
}
.cat-card:active{ transform:scale(.994); }
.cat-card-bg{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block;
}
.cat-card-scrim{
  position:absolute; inset:0;
  background:linear-gradient(to top,
    rgba(39,28,40,.94) 0%,
    rgba(39,28,40,.55) 38%,
    rgba(39,28,40,0) 74%);
}
.cat-card-copy{
  position:absolute; left:18px; bottom:18px; right:18px; z-index:2;
}
.cat-card-name{
  display:block; font-size:20px; font-weight:860; color:#F4EDF1;
  letter-spacing:-.02em; line-height:1.12;
}
.cat-card-model{
  display:block; font-size:13px; color:#D6CAD2; margin-top:5px;
}

/* ---- Notification opt-in sheet ----
   Shown once at registration. The stack of example notifications does the
   arguing: it shows what will actually arrive, rather than describing it. */
.push-sheet{ text-align:center; }
.push-art{
  position:relative; margin:6px 0 20px;
  display:flex; flex-direction:column; gap:8px;
  padding:4px 2px 0;
}
.push-toast{
  display:flex; align-items:center; gap:11px;
  padding:11px 13px; border-radius:14px; text-align:left;
  background:rgba(255,255,255,.085);
  border:1px solid rgba(233,168,206,.20);
  box-shadow:0 8px 20px -10px rgba(0,0,0,.6);
}
/* The stack recedes: the first is what you would see, the rest suggest more
   without asking to be read. */
.push-toast.dim{ opacity:.72; transform:scale(.965); }
.push-toast.dimmer{ opacity:.44; transform:scale(.93); }
.push-toast-ico{
  width:36px; height:36px; border-radius:11px; flex:none;
  display:grid; place-items:center;
  background:rgba(233,168,206,.16); color:#E9A8CE;
}
.push-toast-ico svg{ width:17px; height:17px; }
.push-toast-body{ flex:1; min-width:0; }
.push-toast-t{
  display:block; font-size:13px; font-weight:820; color:#F4EDF1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.push-toast-s{
  display:block; font-size:11px; color:#B9A6B4; margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.push-h{
  font-size:21px; font-weight:850; color:#F4EDF1; margin:0 0 8px; line-height:1.2;
}
.push-s{
  font-size:13px; color:#CFC3CA; line-height:1.5; margin:0 0 20px;
}
.push-allow{
  width:100%; height:50px; border-radius:14px; border:none; cursor:pointer;
  font-family:inherit; font-size:14px; font-weight:840; color:#fff;
  background:linear-gradient(rgb(110,64,93), rgb(74,30,56) 56%, rgb(61,41,53));
  box-shadow:0 8px 20px -8px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.26);
}
.push-allow:active{ transform:scale(.99); }
/* Declining must be as easy as accepting — a hidden dismiss is a dark pattern
   and irritates exactly the people who might have said yes later. */
.push-later{
  width:100%; height:44px; margin-top:8px; border:none; background:none;
  font-family:inherit; font-size:13.5px; font-weight:750; color:#B9A6B4;
  cursor:pointer;
}

/* ---- More: notification setting ----
   Sits with the other rows, but carries its state on the right where the other
   rows carry a chevron — it is a setting with a value, not a destination. */
.mrow-state{
  font-size:12.5px; font-weight:780; flex:none; margin-left:auto;
}
html[data-theme="dark"] .mrow-state.on{ color:#8FD3A6; }
html[data-theme="dark"] .mrow-state.off{ color:#B9A6B4; }
html[data-theme="dark"] .mrow-state.cta{ color:#E9A8CE; font-weight:820; }
/* Granted is not actionable, so it must not look tappable. */
.mrow.mrow-static{ cursor:default; }
.mrow.mrow-static:active{ transform:none; background:inherit; }

/* Products without a hero photograph fall back to the product render. It is a
   cutout on transparency, so `cover` would crop and stretch it — it sits
   contained on a lit field instead, and the scrim is lighter since there is no
   photograph to darken. */
.cat-card-plain{
  background:
    radial-gradient(ellipse 66% 58% at 50% 44%, rgba(233,168,206,.15), transparent 70%),
    rgba(255,255,255,.04);
}
.cat-card-plain .cat-card-bg{
  object-fit:contain;
  padding:18px 18px 44px;
  filter:drop-shadow(0 16px 24px rgba(0,0,0,.55));
}
.cat-card-plain .cat-card-scrim{
  background:linear-gradient(to top,
    rgba(39,28,40,.88) 0%,
    rgba(39,28,40,.34) 30%,
    rgba(39,28,40,0) 58%);
}

/* ---- Scroll lock behind modals ----
   position:fixed on the body is the only lock iOS Safari respects; overflow
   alone does not hold. `top` is set in script to preserve the reading
   position, which fixing the body would otherwise discard. */
body.modal-open{
  position:fixed;
  left:0; right:0;
  width:100%;
  overflow:hidden;
  overscroll-behavior:none;
}
/* The sheet itself may need to scroll — a long list of certificate tiers, for
   instance — without passing the gesture to the page beneath. */
.modal{
  max-height:88vh;
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
}
.modal-back{ overscroll-behavior:none; }

/* ---- Certificate card: header ----
   The balance and the "?" are gone. The link sits on its own row so neither it
   nor the lede has to wrap — the Kazakh copy is longer, and a two-line lede
   beside the link left it stranded at the top. */
html[data-theme="dark"] .cert-card-top{
  display:flex !important;
  justify-content:flex-end !important;
  align-items:center !important;
  margin-bottom:0 !important;
}
.cert-how{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:12px; font-weight:700;
  color:#E9A8CE; text-decoration:underline;
  flex:none;
}
html[data-theme="dark"] .cert-card-lede{
  font-size:12.5px; color:#CFC3CA; line-height:1.45;
  margin:10px 0 0;
}

/* ---- Referral card ----
   The reward split leads. Amounts use the balance gradient so they read as the
   app's own currency, and the two boxes make the friend's 500 as visible as
   the inviter's 1000. */
.refer-top{ display:flex; justify-content:flex-end; align-items:center; }
.refer-how{
  background:none; border:none; padding:0; cursor:pointer; font-family:inherit;
  font-size:12px; font-weight:700; color:#E9A8CE; text-decoration:underline;
}
.refer-split{ display:flex; gap:10px; margin-top:14px; }
.refer-half{
  flex:1; padding:11px 12px; border-radius:13px;
  background:rgba(255,255,255,.05);
  border:1px solid rgba(233,168,206,.16);
}
.refer-half b{
  display:block; font-size:18px; font-weight:860; line-height:1.15;
  background:linear-gradient(90deg, #FFFFFF, #FFB8E4 45%, #B9A2F0);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}
.refer-half span{ display:block; font-size:11.5px; color:#B9A6B4; margin-top:3px; }
html[data-theme="dark"] .refer-card .refer-sub{
  font-size:12.5px; color:#CFC3CA; line-height:1.45; margin:12px 0 0;
}
/* The code is the thing to copy, so it is marked out as an object rather than
   another filled row. */
html[data-theme="dark"] .refer-card .refer-code{
  margin-top:14px;
  border:1px dashed rgba(233,168,206,.36);
  background:rgba(255,255,255,.07);
}
.refer-code-val{ letter-spacing:.14em; }
@media (prefers-reduced-motion: reduce){
  .refer-half b{ background:none; -webkit-text-fill-color:#F4EDF1; color:#F4EDF1; }
}

/* Both of these override rules that carry !important earlier in the sheet, so
   they must too — one more layer, and a reminder of why the stylesheet needs
   the pass in the TODO. */
html[data-theme="dark"] .refer-card .refer-code{
  background:rgba(255,255,255,.07) !important;
  border:1px dashed rgba(233,168,206,.36) !important;
  box-shadow:none !important;
}
/* The share button is the action: full width, and the same primary treatment
   as every other main button since v320. */
html[data-theme="dark"] .refer-card .refer-share{
  display:flex !important;
  width:100% !important;
  height:48px !important;
  margin-top:10px !important;
  align-items:center !important;
  justify-content:center !important;
  gap:8px !important;
  border-radius:13px !important;
  border:none !important;
  font-size:14px !important;
  font-weight:820 !important;
  background:linear-gradient(rgb(110,64,93), rgb(74,30,56) 56%, rgb(61,41,53)) !important;
  box-shadow:0 8px 20px -8px rgba(0,0,0,.55),
             inset 0 1px 0 rgba(255,255,255,.26) !important;
}

/* ---- Referral code check ----
   Verdict under the field rather than a figure on the button: the button says
   what it does, and the code's status belongs beside the code. */
.refer-check{
  display:flex; align-items:center; gap:6px;
  color:var(--muted);
  min-height:16px;
  transition:color .15s ease;
}
.refer-check svg{ width:14px; height:14px; flex:none; }
html[data-theme="dark"] .refer-check.ok{ color:#8FD3A6; }
html[data-theme="dark"] .refer-check.bad{ color:#E88B9A; }
html[data-theme="dark"] .refer-check.checking{ color:#B9A6B4; }

/* The carousel bleeds to the screen edges and pads itself back in, but
   `scroll-snap-align: start` snapped the first card flush against the
   container — scrolling the padding away and leaving no margin at the left
   edge. `scroll-padding-inline` tells the snap where the content actually
   starts, so the card lands inside the padding rather than on top of it. */
.cat-list{
  scroll-padding-inline:20px;
}

/* ---- Room for the navigation bar ----
   The nav is fixed and floats over the content, so a screen has to reserve
   space for it or the last element sits under the bar. It was reserving 8px
   against a footprint of 84 — the bar is 62px tall and the AI disc rises 22px
   above it — so content ended flush against the disc.
   84 to clear it, 20 to breathe, and the home-indicator inset on top. */
.screen{
  padding-bottom:calc(62px + env(safe-area-inset-bottom)) !important;
}
/* Full-screen views carry their own footer and are not behind the nav. */
.authv .screen,
body.install-gate .screen{
  padding-bottom:24px !important;
}

/* ---- Registration fields ----
   The order number is nine or ten digits copied from Kaspi, and the task is
   checking them against the source. Large, centred and letterspaced makes that
   easy — and the referral code is the same kind of thing, so it matches. */
html[data-theme="dark"] .modal input.reg-big{
  height:64px !important;
  font-size:24px !important;
  font-weight:800 !important;
  letter-spacing:.10em !important;
  text-align:center !important;
  background:rgba(255,255,255,.06) !important;
  border:1px solid rgba(233,168,206,.22) !important;
  border-radius:13px !important;
}
html[data-theme="dark"] .modal input.reg-big::placeholder{
  font-size:20px; font-weight:600; letter-spacing:.10em; color:#8C7B88;
}
html[data-theme="dark"] .modal input.reg-big:focus{
  border-color:rgba(233,168,206,.55) !important;
  outline:none !important;
}
/* The code is shorter, so it does not need quite the same size to be legible. */
html[data-theme="dark"] .modal input.reg-big-code{
  font-size:21px !important;
  letter-spacing:.16em !important;
}
html[data-theme="dark"] .modal input.reg-big-code::placeholder{
  font-size:17px; letter-spacing:.16em;
}
/* Where to find the number: the likeliest reason a registration fails is the
   wrong number, and nothing in the app said where to look. */
.reg-where{
  font-size:11px; color:#B9A6B4; line-height:1.45;
  margin:7px 0 0; text-align:center;
}
/* The referral verdict sits under a centred field, so it centres too. */
.refer-check{ justify-content:center; text-align:center; }

/* --- AI reply formatting (aiFormat) — variant B: plum accents ------------- */
.ai-b-bot .ai-p{margin:0 0 5px;}
.ai-b-bot .ai-p:last-child{margin-bottom:0;}
.ai-b-bot .ai-gap{height:5px;}
.ai-b-bot .ai-h{font-weight:700; margin:8px 0 4px; font-size:calc(var(--fs-body) + 1px);}
.ai-b-bot .ai-h:first-child{margin-top:0;}
.ai-b-bot .ai-ul, .ai-b-bot .ai-ol{margin:2px 0 6px; padding-left:20px;
  display:flex; flex-direction:column; gap:4px;}
.ai-b-bot .ai-ul:last-child, .ai-b-bot .ai-ol:last-child{margin-bottom:0;}
.ai-b-bot li{line-height:1.45;}
.ai-b-bot li::marker{color:#E9A8CE;}
.ai-b-bot b{color:#F2C4DD;}
.ai-b-bot code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:.92em; background:rgba(127,127,127,.16); padding:1px 5px; border-radius:6px;}

/* --- Privacy policy screen and auth sheet --------------------------------- */
.priv-updated{ font-size:12px; color:var(--muted); margin-top:2px; align-self:flex-start; }
/* Continuous legal text, not cards: headings, clauses, enumerated sub-items. */
.priv-h{ font-weight:800; font-size:12.5px; letter-spacing:.04em;
  margin:20px 0 8px; color:var(--ink); }
.priv-h:first-child{ margin-top:0; }
.priv-b{ font-size:13.5px; line-height:1.6; color:var(--ink); opacity:.9;
  margin-bottom:8px; }
.priv-l{ font-size:13.5px; line-height:1.6; color:var(--ink); opacity:.9;
  margin:0 0 5px 14px; }
.consent-link{ background:none; border:none; padding:0; font:inherit; color:inherit;
  text-decoration:underline; cursor:pointer; }
.priv-sheet{ display:flex; flex-direction:column; max-height:82vh; }
.priv-sheet-h{ font-weight:700; font-size:17px; }
.priv-sheet .priv-updated{ margin-bottom:8px; }
.priv-sheet-scroll{ overflow-y:auto; -webkit-overflow-scrolling:touch; flex:1; min-height:0; }
.priv-sheet .priv-accept{ flex:0 0 auto; height:52px; min-height:52px; margin-top:14px; }

/* --- Product page hero: full-bleed scene photograph ----------------------- */
/* The photographs are shot on the brand plum, so the padded panel that suits a
   cut-out render only shrinks them. Full bleed, fixed ratio so every product
   page opens to the same height. overflow:hidden is what actually rounds the
   photo — the panel already had a radius, but a flush-filling child overflows
   it and paints square corners on top. */
.cat-detail-hero.cat-detail-photo{ padding:0; aspect-ratio:1074/934; height:auto;
  overflow:hidden; border-radius:var(--radius-lg);
  /* Same raised-material recipe as the home catalogue cards: hairline lit
     border plus the shared lift and edge tokens. Size and ratio unchanged —
     the border sits inside, since box-sizing is border-box. */
  border:1px solid rgba(233,168,206,.16);
  box-shadow:var(--lift-2), var(--edge);
}
.cat-detail-hero.cat-detail-photo img{
  width:100%; height:100%; max-width:none; object-fit:cover; display:block;
  border-radius:inherit;
}

/* An anchor styled as a document tile: the button rules set display via the
   class, but an <a> needs the text-decoration and colour reset explicitly. */
a.pdx-doc{ text-decoration:none; color:inherit; opacity:1; display:block; }
a.pdx-doc .pdx-doc-ic{ background:var(--plum-mist); color:var(--ink); }
a.pdx-doc:active{ transform:scale(.985); }

/* --- Гарантийный талон: on-screen card, and the print sheet ---------------- */
.talon-sheet{ background:#FAF6F0; color:#4E3B47; border-radius:16px;
  padding:22px 20px 26px; position:relative; }
.talon-brand{ font-size:9px; letter-spacing:.22em; text-transform:uppercase; color:#7A6A74; }
.talon-h1{ font-size:22px; font-weight:800; letter-spacing:-.4px; margin:8px 0 2px; }
.talon-sub{ font-size:12.5px; color:#7A6A74; }
.talon-rule{ height:2px; background:#4E3B47; margin:14px 0 16px; }
.talon-h2{ font-size:10px; font-weight:800; letter-spacing:.14em;
  text-transform:uppercase; margin:16px 0 7px; }
.talon-tbl{ width:100%; border-collapse:collapse; }
.talon-tbl td{ font-size:13px; padding:6px 0; border-bottom:1px solid #D8CDD4;
  vertical-align:top; }
.talon-tbl td:first-child{ color:#7A6A74; width:52%; padding-right:10px; }
.talon-tbl td:last-child{ font-weight:700; text-align:right; }
.talon-ul{ margin:0; padding-left:17px; }
.talon-ul li{ font-size:12.5px; line-height:1.5; margin-bottom:5px; }
.talon-p{ font-size:12.5px; line-height:1.55; }
.talon-law{ margin-top:14px; padding:11px 13px; background:#F1E8EE;
  border-radius:10px; font-size:11px; line-height:1.5; margin-right:74px; }
.talon-seal{ position:absolute; right:18px; bottom:18px; width:66px; height:66px; }
.talon-print{ margin-top:14px; }
.screen.talon{ padding-bottom:118px; }
.pdx-doc.live{ opacity:1; }
.pdx-doc.live .pdx-doc-ic{ background:var(--plum-mist); color:var(--ink); }

/* Printing sends the card alone to paper: the app chrome, the nav and the
   button itself must not appear on the sheet. */
@media print{
  body{ background:#fff !important; }
  body > *:not(#app){ display:none !important; }
  #app .screen:not(.talon){ display:none !important; }
  .talon-print, .topbar, .tabbar, .fab, #toast-root, #modal-root{ display:none !important; }
  .talon-sheet{ border-radius:0; padding:0; }
  @page{ size:A4; margin:16mm 18mm; }
}

/* --- Sign-out confirmation ------------------------------------------------ */
.lo-ic{ width:44px; height:44px; border-radius:14px; display:grid; place-items:center;
  background:var(--plum-mist); color:var(--ink); margin:2px 0 12px; }
.lo-t{ font-size:19px; font-weight:800; letter-spacing:-.3px; }
.lo-yes{ margin-top:16px; }
.lo-no{ margin-top:10px; }

/* --- Draw: ticket quantity stepper ---------------------------------------- */
.dws-qty{ display:flex; align-items:center; justify-content:space-between;
  margin:16px 0 10px; }
.dws-qty-l{ font-size:14px; font-weight:700; color:var(--ink); }
.dws-step{ display:flex; align-items:center; gap:2px;
  background:var(--surface); border:1px solid var(--line); border-radius:14px;
  padding:4px; }
.dws-sb{ width:40px; height:40px; border:none; border-radius:11px; cursor:pointer;
  background:var(--plum-mist); color:var(--ink); font-size:21px; font-weight:700;
  line-height:1; display:grid; place-items:center; font-family:inherit; }
.dws-sb:disabled{ opacity:.32; cursor:default; }
.dws-sb:active:not(:disabled){ transform:scale(.94); }
.dws-qn{ min-width:44px; text-align:center; font-size:18px; font-weight:800; }
.dws-total{ display:flex; align-items:center; justify-content:space-between;
  font-size:14px; color:var(--muted); margin-bottom:14px; }
.dws-total b{ font-size:16px; color:var(--ink); }

/* A product tile whose image is missing: hide the broken icon and leave the
   plum panel, rather than showing a torn-image glyph and the alt text. The
   same pattern as .chat-av.fallback. */
.ts-img.fallback{ background:var(--plum-mist); }
.pick-item.fallback img, .mrow-ico.fallback{ background:var(--plum-mist); border-radius:8px; }
