/* Vazirmatn, self-hosted variable font (SIL OFL 1.1, see assets/fonts/OFL.txt).
   Deliberately NOT loaded from fonts.googleapis.com: every reseller is inside Iran
   where a Google-hosted font is unreliable, it would be a third-party request on a
   panel that handles money, and self-hosting keeps the CSP at font-src 'self'. */
@font-face{
  font-family:Vazirmatn;
  src:url("/assets/fonts/Vazirmatn.woff2") format("woff2-variations"),
      url("/assets/fonts/Vazirmatn.woff2") format("woff2");
  font-weight:300 700;
  font-style:normal;
  font-display:swap;
}

/* ============================================================
   TOKENS · archetype: High-End Agency (linear-app), RTL / fa
   light on :root · dark under [data-theme] + prefers-color-scheme
   every pair verified with ux-ui-kit/scripts/contrast.py (WCAG AA)
   chart hues verified with dataviz/scripts/validate_palette.js
   ============================================================ */
:root{
  --bg:#f7f8f9; --panel:#ffffff; --card:#ffffff; --sunk:#f1f3f5; --hover:#eef0f3;
  --line:#e3e6ea; --line-2:#d3d8de; --line-3:#c3cad2;
  --ink:#14161a; --ink-2:#4a515c; --ink-3:#6b7280; --ink-4:#6b7280;
  /* decorative icons only: WCAG 1.4.11 asks 3:1 for non-text, and this is 3.14:1
     on white. Never use it for text - --ink-4 is the lowest legal text tier. */
  --ink-icon:#8b929c;
  --brand:#2f5fd9; --brand-solid:#2f5fd9; --brand-weak:#eaf0fe; --on-brand:#ffffff;
  --ok:#14804a; --ok-weak:#e7f5ed; --ok-ink:#0f6b3e; --warn:#8a5a00; --warn-weak:#fdf3e2; --bad:#c02634; --bad-weak:#fdeced;
  --c1:#3f6fe6; --c2:#cf3f78; --c3:#7d3fd1; --c0:#9aa2ad;
  /* --c4 is the vip slot (service tint + chart hue) and --vip-weak the fill
     its LABEL sits on. Measured with ux-ui-kit/scripts/contrast.py:
     #0e7490 on #ffffff 5.36:1, on --vip-weak #e8f3f6 4.74:1 (AA text),
     and the icon on the 16% tint #d8e9ed 4.29:1 (AA non-text needs 3:1).
     A teal-cyan because every other hue here is taken: c1 blue, c2 magenta,
     c3 purple, --warn amber, --ok green. */
  --c4:#0e7490; --c5:#d97706; --vip-weak:#e8f3f6;
  --shadow-sm:0 1px 2px rgba(16,20,28,.06), 0 1px 1px rgba(16,20,28,.04);
  --shadow-md:0 8px 24px -6px rgba(16,20,28,.14), 0 2px 6px rgba(16,20,28,.06);
  --shadow-lg:0 24px 60px -12px rgba(16,20,28,.28);
  --r-sm:7px; --r:10px; --r-lg:14px; --r-xl:20px; --r-full:999px;
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s7:32px; --s8:40px; --s9:56px;
  --t-fast:120ms cubic-bezier(.2,.8,.3,1); --t:180ms cubic-bezier(.2,.8,.3,1);
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --nav-w:250px;
  /* --- liquid glass (docs/DESIGN-GLASS.md) ------------------------------
     The fill opacity is high on purpose: 88% light / 72% dark is the point
     where the backdrop can no longer drag text below AA. Thinner reads
     better in a screenshot and fails in the app.
     --tab-ink is the floating nav's INACTIVE label. Light must resolve to
     --ink-2: at 88% glass over a brand-blue or dark element --ink-3 lands
     at 3.3:1 and fails AA for the 10.5px label, --ink-2 holds >= 6.1:1. */
  --glass:        color-mix(in srgb, var(--panel) 88%, transparent);
  /* the floating bar's own glass: lighter than the page, a rim you can see,
     and a real lift. See .tabs for why it is not just --glass. */
  --tabglass: color-mix(in srgb, var(--panel) 82%, transparent);
  --tabrim:   color-mix(in srgb, #0b1020 14%, transparent);
  --tablift:  0 2px 8px rgba(16,20,28,.10), 0 18px 36px -10px rgba(16,20,28,.22);
  /* 96%, not the spec's 94%: --glass-strong is worn by the popup, and the popup
     sits on the 66% black scrim, which the spec's table never measured. At 94%
     the composite is #f5f5f5 and --ink-3 lands at 4.43:1, below AA. At 96% the
     composite is #f8f8f8 and --ink-3 holds 4.55:1. The rule wins over the
     number; the blur is what reads as glass, not the last 2% of the fill. */
  --glass-strong: color-mix(in srgb, var(--panel) 96%, transparent);
  --glass-blur:   saturate(180%) blur(20px);
  --rim:      color-mix(in srgb, #000 8%, transparent);
  --rim-top:  color-mix(in srgb, #000 5%, transparent);
  --lift-sm: 0 1px 2px rgba(16,20,28,.07), 0 4px 12px -4px rgba(16,20,28,.10);
  --lift:    0 2px 6px rgba(16,20,28,.08), 0 16px 32px -12px rgba(16,20,28,.16);
  --lift-lg: 0 4px 10px rgba(16,20,28,.10), 0 32px 64px -20px rgba(16,20,28,.26);
  --tab-ink: var(--ink-2);
}
:root[data-theme="dark"]{
  --bg:#0a0b0d; --panel:#101214; --card:#16181b; --sunk:#0e1012; --hover:#1e2126;
  --line:rgba(255,255,255,.07); --line-2:rgba(255,255,255,.11); --line-3:rgba(255,255,255,.17);
  --ink:#f2f4f6; --ink-2:#b6bdc7; --ink-3:#8a919c; --ink-4:#8a919c;
  --ink-icon:#666d78;
  --brand:#5b8cff; --brand-solid:#2f5fd9; --brand-weak:#141c2e; --on-brand:#ffffff;
  --ok:#2fbf71; --ok-weak:#0f2119; --ok-ink:#2fbf71; --warn:#e0a33a; --warn-weak:#241c0d; --bad:#f0616d; --bad-weak:#251215;
  --c1:#5b8cff; --c2:#e05a8e; --c3:#9a5ce8; --c0:#5a6270;
  /* #34c9dd on --card #16181b 8.93:1, on --vip-weak #0d2529 8.03:1,
     icon on the 16% tint #1b343a 6.60:1 */
  --c4:#34c9dd; --c5:#f5a524; --vip-weak:#0d2529;
  --shadow-sm:none;
  --shadow-md:0 10px 28px -8px rgba(0,0,0,.7);
  --shadow-lg:0 30px 70px -14px rgba(0,0,0,.85);
  /* glass, dark: thinner fill is safe here because the composited result is
     still near-black (72% panel over the page measures #0e1012, --ink 17.3:1,
     muted 6.0:1). The rim flips to a bright edge. */
  --glass:        color-mix(in srgb, var(--panel) 72%, transparent);
  /* Dark needs the opposite move: the page is nearly black, so the bar is
     mixed toward --card (a step lighter) and its rim is white, or the thing
     has no edge at all. */
  --tabglass: color-mix(in srgb, var(--card) 78%, transparent);
  --tabrim:   color-mix(in srgb, #fff 16%, transparent);
  --tablift:  0 2px 10px rgba(0,0,0,.6), 0 20px 44px -12px rgba(0,0,0,.8);
  --glass-strong: color-mix(in srgb, var(--panel) 86%, transparent);
  --rim:      color-mix(in srgb, #fff 12%, transparent);
  --rim-top:  color-mix(in srgb, #fff 18%, transparent);
  --lift-sm: 0 1px 2px rgba(0,0,0,.5),  0 4px 14px -4px rgba(0,0,0,.55);
  --lift:    0 2px 8px rgba(0,0,0,.55), 0 18px 40px -14px rgba(0,0,0,.7);
  --lift-lg: 0 6px 14px rgba(0,0,0,.6), 0 40px 80px -24px rgba(0,0,0,.85);
  --tab-ink: var(--ink-3);
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#0a0b0d; --panel:#101214; --card:#16181b; --sunk:#0e1012; --hover:#1e2126;
  --line:rgba(255,255,255,.07); --line-2:rgba(255,255,255,.11); --line-3:rgba(255,255,255,.17);
  --ink:#f2f4f6; --ink-2:#b6bdc7; --ink-3:#8a919c; --ink-4:#8a919c;
  --ink-icon:#666d78;
  --brand:#5b8cff; --brand-weak:#141c2e;
  --ok:#2fbf71; --ok-weak:#0f2119; --ok-ink:#2fbf71; --warn:#e0a33a; --warn-weak:#241c0d;
  --bad:#f0616d; --bad-weak:#251215;
  --c1:#5b8cff; --c2:#e05a8e; --c3:#9a5ce8; --c0:#5a6270;
  --c4:#34c9dd; --c5:#f5a524; --vip-weak:#0d2529;
  --shadow-sm:none; --shadow-md:0 10px 28px -8px rgba(0,0,0,.7); --shadow-lg:0 30px 70px -14px rgba(0,0,0,.85);
  --glass:        color-mix(in srgb, var(--panel) 72%, transparent);
  /* Dark needs the opposite move: the page is nearly black, so the bar is
     mixed toward --card (a step lighter) and its rim is white, or the thing
     has no edge at all. */
  --tabglass: color-mix(in srgb, var(--card) 78%, transparent);
  --tabrim:   color-mix(in srgb, #fff 16%, transparent);
  --tablift:  0 2px 10px rgba(0,0,0,.6), 0 20px 44px -12px rgba(0,0,0,.8);
  --glass-strong: color-mix(in srgb, var(--panel) 86%, transparent);
  --rim:      color-mix(in srgb, #fff 12%, transparent);
  --rim-top:  color-mix(in srgb, #fff 18%, transparent);
  --lift-sm: 0 1px 2px rgba(0,0,0,.5),  0 4px 14px -4px rgba(0,0,0,.55);
  --lift:    0 2px 8px rgba(0,0,0,.55), 0 18px 40px -14px rgba(0,0,0,.7);
  --lift-lg: 0 6px 14px rgba(0,0,0,.6), 0 40px 80px -24px rgba(0,0,0,.85);
  --tab-ink: var(--ink-3);
}}

*,*::before,*::after{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
  font-family:Vazirmatn,-apple-system,"Segoe UI",system-ui,sans-serif;
  font-size:14px;line-height:1.65;font-weight:400;
  -webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums}
h1,h2,h3,h4,p,figure{margin:0}
button,input,select,textarea{font:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
/* default icon size: every sized context below out-specifies this, so a bare
   ic() dropped into a flex row can never stretch to fill its container */
svg{display:block;width:16px;height:16px;flex:none}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px}
::selection{background:var(--brand);color:#fff}
@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important}}

.stage{padding:var(--s5) var(--s5) var(--s9)}

/* ---------- app shell ---------- */
.app{position:relative;display:grid;grid-template-columns:var(--nav-w) 1fr;
  border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--bg);min-height:760px}

.side{background:var(--glass);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
  border-inline-end:1px solid var(--rim);
  padding:var(--s5) var(--s3);display:flex;flex-direction:column;gap:2px}
.brandline{display:flex;align-items:center;gap:10px;padding:0 var(--s2) var(--s5)}
.brandmark{width:34px;height:34px;border-radius:9px;display:grid;place-items:center;flex:none;
  background:linear-gradient(155deg,var(--brand) 0%,var(--c3) 115%);color:#fff}
.brandmark svg{width:18px;height:18px}
.brandline b{font-size:14.5px;font-weight:600;letter-spacing:-.01em;display:block;line-height:1.35}
.brandline span{font-size:11.5px;color:var(--ink-4);display:block;line-height:1.3}
.navlabel{font-size:12px;letter-spacing:.08em;color:var(--ink-4);font-weight:500;padding:var(--s4) var(--s2) 6px}
.navitem{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:10px var(--s2);border-radius:var(--r-sm);
  color:var(--ink-2);font-size:13.5px;font-weight:500;transition:background var(--t-fast),color var(--t-fast);text-align:start}
.navitem svg{width:17px;height:17px;flex:none;color:var(--ink-icon);transition:color var(--t-fast)}
.navitem:hover{background:var(--hover);color:var(--ink)}
.navitem:hover svg{color:var(--ink-2)}
.navitem[aria-current="page"]{background:var(--brand-weak);color:var(--brand);font-weight:600}
.navitem[aria-current="page"] svg{color:var(--brand)}
.navitem .pill{margin-inline-start:auto}
.side__foot{margin-top:auto;border-top:1px solid var(--line);padding-top:var(--s3)}

.main{min-width:0;display:flex;flex-direction:column;background:var(--bg)}
/* sticky bar: glass is safe here because the only text on it is the 17px h1 and
   the button labels. The search box keeps its own opaque fill, so no input ever
   sits on a moving blur. */
.topbar{display:flex;align-items:center;gap:var(--s3);padding:var(--s4) var(--s5);
  border-bottom:1px solid var(--rim);background:var(--glass);
  backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
  position:sticky;top:0;z-index:20}
.topbar h1{font-size:17px;font-weight:600;letter-spacing:-.015em;white-space:nowrap}
.topbar .sp{flex:1}
.content{padding:var(--s6) var(--s5) var(--s8);display:flex;flex-direction:column;gap:var(--s6);min-width:0}
.only-m{display:none!important}

/* ---------- floating liquid bottom nav (mobile only) ----------
   Detached from the edge, pill radius, translucent fill over a blur, a rim
   border and a layered shadow. display:grid arrives with the 860px media
   query; everything else is set here so the two rules never disagree. */
.tabs{display:none;position:fixed;z-index:30;
  /* Clear of all three edges, and of the home indicator on a phone that has
     one. 14px rather than 12: at 12 the bar reads as almost-full-width with a
     rounding error, and the whole point is that it is a separate object. */
  inset-inline:14px;bottom:calc(14px + env(safe-area-inset-bottom, 0px));
  margin:0;
  padding:7px 8px;border-radius:24px;
  /* A body of its own. `--glass` alone resolves to nearly the page colour on
     a near-black background, which left the bar edgeless -- floating in
     geometry but not to the eye. --tabglass is mixed toward the surface that
     sits ABOVE the page, so it stays translucent and still has substance. */
  background:var(--tabglass);
  backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
  border:1px solid var(--tabrim);box-shadow:var(--tablift);
  grid-template-columns:repeat(5,1fr);align-items:end;
  isolation:isolate}
/* the specular rim: a 1px line along the top edge, the thing that reads as glass */
/* the specular highlight: brighter than the rim and only along the top, the
   way light catches the near edge of a pane. Without it the bar is a rounded
   rectangle; with it, it is glass. */
.tabs::before{content:"";position:absolute;inset:0 0 auto;height:1px;
  border-radius:24px 24px 0 0;
  background:linear-gradient(90deg,transparent,var(--rim-top) 22%,var(--rim-top) 78%,transparent);
  pointer-events:none}
/* ONE shared capsule that slides between tabs. Geometry comes from app.js
   (offsetLeft/offsetWidth through the CSSOM, since CSP forbids style
   attributes). translateX is physical on purpose: logical properties do not
   animate, and offsetLeft is already a physical coordinate, so RTL lands on
   the right tab without a mirror. */
.tabs__pill{position:absolute;z-index:-1;top:6px;bottom:6px;left:0;right:auto;width:0;
  border-radius:18px;
  background:color-mix(in srgb, var(--brand) 14%, transparent);
  border:1px solid color-mix(in srgb, var(--brand) 26%, transparent);
  transition:transform 420ms cubic-bezier(.34,1.4,.44,1), width 420ms cubic-bezier(.34,1.4,.44,1),
             opacity var(--t)}
.tabs__pill--off{opacity:0}
.tabs__pill--noanim{transition:none}
@media (prefers-reduced-motion:reduce){.tabs__pill{transition:none}}
/* inactive label: --tab-ink is --ink-2 in light, --ink-3 in dark. See :root. */
.tab{display:flex;flex-direction:column;align-items:center;gap:3px;padding:6px 2px;border-radius:var(--r-sm);
  /* 📏 12px floor. 10.5px is below the size a Persian face stays legible at
     on a phone, and these five words are the panel's main navigation. */
  color:var(--tab-ink);font-size:12px;font-weight:500;transition:color var(--t-fast)}
.tab svg{width:20px;height:20px}
.tab[aria-current="page"]{color:var(--brand)}
/* the FAB stays raised but drops the hard glow: one soft brand-tinted ambient
   shadow, so it does not stack a glow on top of the nav's blur */
.tab--fab{transform:translateY(-13px)}
.tab--fab i{width:46px;height:46px;border-radius:15px;display:grid;place-items:center;
  background:var(--brand-solid);color:#fff;box-shadow:0 6px 18px -8px color-mix(in srgb,var(--brand-solid) 55%,transparent)}
.tab--fab i svg{width:22px;height:22px}

/* ---------- primitives ---------- */
/* cards hold numbers, so they take the rim and the contact shadow but stay
   fully opaque: no blur, no translucency. Interior dividers keep --line. */
.card{background:var(--card);border:1px solid var(--rim);border-radius:var(--r-lg);padding:var(--s5);
  box-shadow:var(--lift-sm)}
.card--flush{padding:0;overflow:hidden}
.card__hd{display:flex;align-items:center;gap:var(--s2);padding:var(--s4) var(--s5);border-bottom:1px solid var(--line)}
.card__hd h2{font-size:14px;font-weight:600;letter-spacing:-.01em}
.card__hd .sp{flex:1}

/* 👆 44px is the floor for EVERY button, at every width. The login
   screen's own submit was 40px and its two inputs 38px -- the first screen a
   reseller ever touches, on a phone, with nothing else on it. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:10px 14px;min-height:44px;
  border-radius:var(--r-sm);font-size:13.5px;font-weight:500;border:1px solid var(--line-2);color:var(--ink);
  background:var(--card);transition:background var(--t-fast),border-color var(--t-fast),transform var(--t-fast)}
.btn svg{width:16px;height:16px}
.btn:hover{background:var(--hover);border-color:var(--line-3)}
.btn:active{transform:scale(.985)}
.btn--pri{background:var(--brand-solid);border-color:var(--brand-solid);color:#fff;font-weight:600}
.btn--pri:hover{background:color-mix(in srgb,var(--brand-solid) 86%,#fff);border-color:transparent}
.btn--ghost{background:transparent;border-color:transparent;color:var(--ink-2)}
.btn--ghost:hover{background:var(--hover);border-color:transparent;color:var(--ink)}
.btn--danger{color:var(--bad);border-color:color-mix(in srgb,var(--bad) 35%,transparent)}
.btn--danger:hover{background:var(--bad-weak)}
/* 👆 A two-character label ("رد", "ورود") still needs a finger-sized box. */
.btn--sm{min-height:44px;min-width:44px;padding:6px 12px;font-size:12.5px}
.btn--sm svg{width:14px;height:14px}
/* 👆 A tap target is 44px on every screen, not only under the mobile media
   query: a small phone in landscape is 740px wide and the thumb is the same
   thumb. `width` was the half that kept overriding `min-width`. */
.btn--icon{padding:0;width:44px;min-height:44px}
.btn--icon.btn--sm{width:44px;min-height:44px}
.btn--block{width:100%}
.btn[disabled]{opacity:.45;pointer-events:none}
/* the delivery file and the receipt are real links wearing a button; without
   this they carry the browser's underline */
a.btn{text-decoration:none}
/* a download button whose label IS a filename: it can be long, so it wraps
   instead of pushing the card sideways at 380px */
.btn--file{max-width:100%;white-space:normal;word-break:break-all}

.pill{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:var(--r-full);
  font-size:11.5px;font-weight:500;line-height:1.7;white-space:nowrap;border:1px solid transparent}
.pill svg{width:12px;height:12px}
.pill--ok{background:var(--ok-weak);color:var(--ok)}
.pill--warn{background:var(--warn-weak);color:var(--warn)}
.pill--bad{background:var(--bad-weak);color:var(--bad)}
.pill--mute{background:var(--sunk);color:var(--ink-3);border-color:var(--line)}
.pill--brand{background:var(--brand-weak);color:var(--brand)}
.pill--out{background:transparent;border-color:var(--line-2);color:var(--ink-3)}
/* 👆 A `.pill` that is also a BUTTON is something a finger presses, at every
   width -- the customer-filter row is the same row on a phone and a laptop.
   It used to reach 44px only inside the <=860px query, so on a desktop it was
   32px tall. */
.pill--btn{min-height:44px;padding-block:9px}
/* the vip label on its own tint: --vip-weak is the fill that keeps --c4 above
   4.5:1 in both themes (see the token comment) */
.pill--vip{background:var(--vip-weak);color:var(--c4);
  border-color:color-mix(in srgb,var(--c4) 26%,transparent)}

.field{display:flex;flex-direction:column;gap:6px}
.field>label{font-size:12.5px;font-weight:500;color:var(--ink-2)}
.input{display:flex;align-items:center;gap:8px;background:var(--card);border:1px solid var(--line-2);
  border-radius:var(--r-sm);padding:0 11px;min-height:44px;transition:border-color var(--t-fast),box-shadow var(--t-fast)}
.input:focus-within{border-color:var(--brand);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 18%,transparent)}
.input svg{width:16px;height:16px;color:var(--ink-icon);flex:none}
/* 👆 The BOX is 44px and so is the field inside it. Only the wrapper had a
   floor, so the login screen's two fields -- the first thing a reseller
   touches, on a phone -- measured 38px at both widths. */
.input input,.input select{flex:1;min-width:0;min-height:44px;border:0;background:none;outline:none;font-size:13.5px;padding:8px 0}
input,select,textarea{min-height:44px}
.input input,.input select,.input textarea{min-height:44px}
/* RULE: a <select> paints its own dropdown from the OS, not from the page. On
   a dark theme that meant white rows with near-white text -- the options were
   there and unreadable, and the owner could not see what he was picking.
   `color-scheme` is what tells the browser to draw the native widget dark;
   the explicit option colours are the belt to that braces, because Android
   Chrome ignores color-scheme on the popup in some versions. */
.input select{color-scheme:light dark;cursor:pointer;appearance:none;padding-inline-end:18px}
.input select option{background:var(--panel);color:var(--ink);font-size:13.5px}
:root[data-theme="dark"] .input select,
:root[data-theme="dark"] .input select option{color-scheme:dark}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .input select,
  :root:not([data-theme="light"]) .input select option{color-scheme:dark}
}
/* The caret the appearance:none removed. Drawn with a gradient rather than an
   inline SVG because the page's CSP forbids inline styles and data URIs here. */
.input select{background-image:
    linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),
    linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
  background-position:calc(0% + 6px) calc(50% + 1px),calc(0% + 11px) calc(50% + 1px);
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.input input::placeholder{color:var(--ink-4)}
.hint{font-size:11.5px;color:var(--ink-4);line-height:1.6}

.mono{font-family:var(--mono);font-size:12px;direction:ltr;unicode-bidi:isolate;letter-spacing:-.01em}
.num{font-variant-numeric:tabular-nums}
.eyebrow{font-size:12px;letter-spacing:.06em;color:var(--ink-4);font-weight:500}
.muted{color:var(--ink-3)}
.tiny{font-size:11.5px}
.row{display:flex;align-items:center;gap:var(--s2)}
.wrap{flex-wrap:wrap}
.sp{flex:1}
.sect{display:flex;flex-direction:column;gap:var(--s3)}
.sect__hd{display:flex;align-items:baseline;gap:var(--s2)}
.sect__hd h2{font-size:15px;font-weight:600;letter-spacing:-.015em}

/* service identity.
   data-s carries the API's own service value (app.js BRAND/SVC are keyed the
   same way). The BASE is the neutral tint, so a service this stylesheet has
   never heard of is still a legible bubble instead of an unstyled one - and
   the same base is what the chrome bubbles (a receipt, a nav row) use with no
   data-s at all. `proxy` deliberately has no rule of its own: neutral IS its
   colour, which is how the mockup had it. */
.svc{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;flex:none;
  background:var(--sunk);color:var(--ink-3);border:1px solid var(--line-2)}
.svc svg{width:17px;height:17px}
.svc--sm{width:28px;height:28px;border-radius:8px}
.svc--sm svg{width:15px;height:15px}
.svc--lg{width:44px;height:44px;border-radius:13px}
.svc--lg svg{width:22px;height:22px}
.svc[data-s="v2ray"]{background:color-mix(in srgb,var(--c1) 16%,transparent);color:var(--c1);
  border-color:color-mix(in srgb,var(--c1) 26%,transparent)}
.svc[data-s="wireguard"]{background:color-mix(in srgb,var(--c2) 16%,transparent);color:var(--c2);
  border-color:color-mix(in srgb,var(--c2) 26%,transparent)}
.svc[data-s="openconnect"]{background:color-mix(in srgb,var(--c3) 16%,transparent);color:var(--c3);
  border-color:color-mix(in srgb,var(--c3) 26%,transparent)}
.svc[data-s="vip"]{background:color-mix(in srgb,var(--c4) 16%,transparent);color:var(--c4);
  border-color:color-mix(in srgb,var(--c4) 26%,transparent)}

/* REAL app marks (static/img/apps, see static/img/LICENSES.md).
   Each file is its own plate -- a rounded square in the product's colour with
   the mark in white -- so the chip that used to supply the tint has to get out
   of its way entirely: background, border AND the 17px inner box, or the plate
   sits inside a differently-tinted square with a ring around it. The chip keeps
   its size and its `data-s`, so every layout that positions a .svc still works
   and nothing downstream had to learn about images.
   🪤 `border-radius:inherit` on the img is NOT enough: the plate's own corner
   radius is baked into the SVG at the 48 grid, so it scales with the chip. The
   inherit is for the focus ring and for Safari's edge antialiasing. */
.svc--img{background:none;border:0;overflow:hidden}
.svc--img>img{width:100%;height:100%;display:block;border-radius:inherit}

/* REAL country flags (static/img/flags, circle-flags, MIT).
   Sized in `em` on purpose: these sit inline with text at six different type
   sizes in this panel and a fixed 20px is either a dot or a balloon at two of
   them. The ring is a non-inset shadow, not a border -- a border on a replaced
   element eats into the 512-grid disc and leaves a hairline of the flag's edge
   colour outside it. */
.flagi{width:1.35em;height:1.35em;border-radius:50%;flex:none;object-fit:cover;
  vertical-align:-.28em;background:var(--sunk);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--ink) 14%,transparent)}
/* RTL: the flag leads the country name. The gap is a flex `gap`, never a
   margin -- a `margin-left` here reads correctly on this right-to-left panel
   and backwards the day one of these strings is rendered LTR, and that is the
   kind of bug that survives a review because nobody looks at it in the other
   direction. */
.flagrow{display:inline-flex;align-items:center;gap:6px;vertical-align:middle}
.flagrow>.flagi{vertical-align:baseline}
.flagi--lg{width:28px;height:28px;vertical-align:middle}

/* meters */
.meter{height:6px;border-radius:var(--r-full);background:var(--sunk);overflow:hidden;border:1px solid var(--line)}
.meter>i{display:block;height:100%;border-radius:var(--r-full);background:var(--brand);
  transition:width var(--t)}
.meter[data-tone="ok"]>i{background:var(--ok)}
.meter[data-tone="warn"]>i{background:var(--warn)}
.meter[data-tone="bad"]>i{background:var(--bad)}
.meter--lg{height:9px}

/* table */
.tbl{width:100%;border-collapse:separate;border-spacing:0;font-size:13px}
/* 📏 12px floor, same as the tab bar and the eyebrows. */
.tbl th{text-align:start;font-weight:500;font-size:12px;letter-spacing:.04em;color:var(--ink-4);
  padding:9px var(--s4);border-bottom:1px solid var(--line);background:var(--sunk);white-space:nowrap;position:sticky;top:0}
.tbl td{padding:11px var(--s4);border-bottom:1px solid var(--line);vertical-align:middle}
.tbl tbody tr{cursor:pointer;transition:background var(--t-fast)}
.tbl tbody tr:hover{background:var(--hover)}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl .end{text-align:end}
/* ↔️ 1405/06/29: `.tblwrap` existed but the tables that overflowed were not
   inside one (resellers 759px, the price ladder 636px, both in a 345px card),
   and in RTL a table overflows to the LEFT -- off the side the scroll does not
   start on. `max-width:100%` + `min-width:0` stop the flex/grid parent from
   sizing itself to the table, which is what actually pushed the columns out
   of the card. `.tbl` keeps a floor so the columns stay readable while the
   BOX, not the page, does the scrolling. */
.tblwrap{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;min-width:0}
/* 👉 A scrollbar that is always drawn, because a table that scrolls and
   does not SAY it scrolls is a table whose last three columns do not exist. */
.tblwrap::-webkit-scrollbar{height:7px}
.tblwrap::-webkit-scrollbar-track{background:transparent}
.tblwrap::-webkit-scrollbar-thumb{background:var(--line-3);border-radius:99px}
.tblwrap>.tbl{min-width:560px}
@media (max-width:520px){.tblwrap{margin-inline:calc(-1 * var(--s4));padding-inline:var(--s4)}}

/* ============================================================
   LEDGER ROWS ON A PHONE  ·  «گردش حساب»
   Every other table in the panel already ships a `.rowcard` twin behind
   `hide-m`/`only-m`; the statement was the one that never got one. MEASURED
   1405/06/26: at 375px its four columns ran from -15 to 358 inside a 345px
   card, so the «مانده» column was off the edge, and «شرح» wrapped to four
   lines, making one row 260px tall. Four columns do not fit a phone; a row
   does. Date and label on the first line, the movement and the running
   balance on the second.
   ============================================================ */
.ledg{display:flex;flex-direction:column}
.ledg__r{display:flex;flex-direction:column;gap:5px;padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--line)}
.ledg__r:last-child{border-bottom:0}
.ledg__t{display:flex;align-items:baseline;gap:var(--s3)}
.ledg__t b{font-size:13.5px;font-weight:600;min-width:0;overflow-wrap:anywhere}
.ledg__t .sp{flex:1}
.ledg__d{font-size:11.5px;color:var(--ink-4);white-space:nowrap}
.ledg__n{font-size:11.5px;color:var(--ink-3)}
.ledg__m{display:flex;align-items:baseline;gap:var(--s3);font-size:12.5px}
.ledg__m .sp{flex:1}
.ledg__bal{font-size:11.5px;color:var(--ink-3);white-space:nowrap}

/* mobile row cards */
.rowcard{display:flex;align-items:center;gap:var(--s3);width:100%;text-align:start;padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--line);transition:background var(--t-fast)}
.rowcard:last-child{border-bottom:0}
.rowcard:active{background:var(--hover)}
.rowcard__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}
.rowcard__t{display:flex;align-items:center;gap:6px}
.rowcard__t b{font-size:13.5px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rowcard__m{display:flex;align-items:center;gap:var(--s3);font-size:11.5px;color:var(--ink-3)}
/* 📏 A row's actions live in one box so they can be moved together. Under
   520px they take a line of their own and the name gets the row. */
.rowcard__acts{display:flex;align-items:center;gap:var(--s2);flex:none}
@media (max-width:520px){
  .rowcard{flex-wrap:wrap}
  .rowcard__acts{flex:1 0 100%;justify-content:flex-end;margin-top:var(--s2)}
}
/* 👥 The «دستگاه فعال» column of a customer card: one line, never three. */
.devcol{flex:none;white-space:nowrap}
.rowcard__m span{display:flex;align-items:center;gap:4px}
.rowcard__m svg{width:12px;height:12px;color:var(--ink-icon)}

/* stat tiles · bento (mixed sizes, no dead cells) */
.bento{display:grid;gap:var(--s3);grid-template-columns:repeat(4,1fr)}
.tile{background:var(--card);border:1px solid var(--rim);border-radius:var(--r-lg);padding:var(--s4);
  box-shadow:var(--lift-sm);display:flex;flex-direction:column;gap:6px;min-width:0}
.tile--w2{grid-column:span 2}
.tile__k{font-size:11.5px;color:var(--ink-3);display:flex;align-items:center;gap:6px}
.tile__k svg{width:14px;height:14px;color:var(--ink-icon)}
.tile__v{font-size:25px;font-weight:600;letter-spacing:-.03em;line-height:1.15;display:flex;align-items:baseline;gap:5px}
.tile__v small{font-size:12.5px;font-weight:500;color:var(--ink-3);letter-spacing:0}
.tile__d{font-size:11.5px;color:var(--ink-4)}

/* hero balance · keeps its radial brand wash and takes the rim plus the wider
   lift. Deliberately NO blur: a blur on top of the gradient would be two
   effects stacked on one surface. */
.hero{background:var(--card);border:1px solid var(--rim);border-radius:var(--r-lg);
  box-shadow:var(--lift);
  padding:var(--s5);display:grid;gap:var(--s4);position:relative;overflow:hidden}
.hero::after{content:"";position:absolute;inset-block-start:-70px;inset-inline-start:-40px;width:240px;height:240px;
  border-radius:50%;background:radial-gradient(circle,color-mix(in srgb,var(--brand) 16%,transparent),transparent 68%);pointer-events:none}
.hero__v{font-size:34px;font-weight:600;letter-spacing:-.035em;line-height:1.1;position:relative}
.hero__v small{font-size:14px;font-weight:500;color:var(--ink-3);letter-spacing:0;margin-inline-start:5px}

/* ── locations ────────────────────────────────────────────────────────────
   The picker that replaced the one-row exit dropdown (1405/06/27). Two
   columns on a phone, three from 520px: a nine-country list has to be one
   glance, and a single column pushes the wizard's own button below the fold
   -- which is defect D6 of the 06/26 mobile audit, re-earned.
   🔴 44px minimum height. Every row here is a thumb target on a phone, and
   the audit moved every other target in this panel to 44 for the same
   reason. */
.locgrid{display:grid;gap:var(--s2);grid-template-columns:repeat(2,minmax(0,1fr));margin-top:var(--s3)}
.locrow{display:flex;align-items:center;gap:var(--s2);min-height:44px;width:100%;
  padding:7px 10px;border-radius:var(--r-sm);text-align:start;
  border:1px solid var(--line-2);background:var(--card);
  transition:border-color var(--t-fast),background var(--t-fast)}
.locrow:hover:not([disabled]):not(.locrow--ro){border-color:var(--line-3);background:var(--hover)}
.locrow[aria-pressed="true"]{border-color:var(--brand);background:var(--brand-weak);
  box-shadow:0 0 0 1px var(--brand)}
.locrow[disabled],.locrow.is-off{opacity:.55;cursor:not-allowed}
.locrow--ro{background:var(--sunk)}
.locrow__b{flex:1;min-width:0;font-size:13px;font-weight:500}
.locrow__b .tiny{display:block;font-weight:400}
/* The tick box. A real box and not a ✓ that appears from nowhere: a
   multi-select whose unselected state draws nothing reads as a list of
   buttons, and the reseller does not learn that several are allowed. */
.locrow__box{width:18px;height:18px;flex:none;border-radius:5px;display:grid;place-items:center;
  border:1.5px solid var(--line-3);color:var(--on-brand)}
.locrow[aria-pressed="true"] .locrow__box{background:var(--brand-solid);border-color:var(--brand-solid)}
.locrow__box svg{width:12px;height:12px;stroke-width:3}
/* ⚖️ The coefficient, on the row it applies to. Amber and never red: it is a
   price, not a fault. Absent at ×1 -- see coefBadge(). */
.coefb{flex:none;font-size:11.5px;font-weight:600;line-height:1.7;padding:2px 8px;
  border-radius:var(--r-full);background:var(--warn-weak);color:var(--warn);white-space:nowrap}
.locchips{display:flex;flex-wrap:wrap;gap:6px}
.locchip{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;border-radius:var(--r-full);
  background:var(--sunk);border:1px solid var(--line);font-size:12px;white-space:nowrap}
/* 🪤 One column under 420px. Two columns of (tick + flag + "قزاقستان" + ×۲٫۵)
   measured 178px of content in a 168px cell at 360px wide -- and the overflow
   is the BADGE, i.e. the price, clipped off the end of the row. The sticky
   wizard footer (mobile audit D6) is what makes a taller list safe here. */
@media (max-width:420px){.locgrid{grid-template-columns:1fr}}

/* delivery / QR */
.qrbox{background:#fff;padding:10px;border-radius:var(--r);border:1px solid var(--line-2);flex:none}
.qrbox svg{width:128px;height:128px;shape-rendering:crispEdges}
.qrbox--sm{margin-top:var(--s3);width:max-content}
.qrbox--sm svg{width:104px;height:104px}
/* 🛍 The «لینک ساب» block: the one thing a shop shows a customer's
   phone. 248px because the square is scanned OFF A MONITOR from across a
   counter, and a 128px code at that distance is a code the camera hunts for.
   `max-width:100%` and the `min()` keep it inside a 360px phone, where the
   same reseller reads this card on their own handset. */
.subrow{display:flex;flex-direction:column;align-items:center;gap:var(--s2);
  padding:var(--s3);border:1px solid var(--line);border-radius:var(--r);
  background:var(--sunk);margin-bottom:var(--s3)}
.subrow__t{align-self:flex-start;display:flex;align-items:center;gap:6px}
.subrow .linkbox{min-width:0}
.subrow .row{justify-content:center}
button.qrbox{cursor:pointer;display:block;line-height:0;margin:0}
.qrbox--lg svg{width:min(248px,68vw);height:min(248px,68vw)}
.qrfull{display:flex;justify-content:center}
.qrbox--full svg{width:min(420px,76vw,60vh);height:min(420px,76vw,60vh)}
/* One card per location in a delivery: address, credential, links, QR.
   🔴 `min-width:0` on every level, and it is not decoration. A proxy link is
   ~90 characters on ONE line; a grid item and a flex item both default to
   `min-width:auto`, which is "as wide as my content", so the card grew to
   607px inside a 413px sheet and its left 374px -- the username, the
   password, the start of every link -- sat outside the sheet with nothing to
   scroll. MEASURED at 412px on 1405/06/27: `.locdel__i` box was [-374, 389].
   The page reported no horizontal overflow because the sheet clipped it,
   which is why this has to be measured per element and not with a
   `scrollWidth > innerWidth` check. The `.mono` inside already ellipsises;
   it just needs an ancestor chain that lets it. */
.locdel{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s3);margin-top:var(--s3);min-width:0}
.locdel__i{border:1px solid var(--line);border-radius:var(--r);padding:10px var(--s3);
  background:var(--sunk);min-width:0;overflow:hidden}
.locdel__h{font-size:13px;font-weight:600;display:flex;align-items:center;gap:6px;
  padding-bottom:6px;border-bottom:1px solid var(--line);min-width:0}
.locdel .credrow{min-width:0}
.locdel .credrow span:first-child{width:76px}
.linkbox{display:flex;align-items:center;gap:var(--s2);background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:7px 10px;min-width:0}
.linkbox .mono{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* steps */
.steps{display:flex;align-items:center;gap:var(--s2)}
.step{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-4);font-weight:500;white-space:nowrap}
.step i{width:21px;height:21px;border-radius:50%;display:grid;place-items:center;font-size:11px;
  border:1px solid var(--line-2);color:var(--ink-4);font-style:normal}
.step[data-on="1"]{color:var(--ink)}
.step[data-on="1"] i{background:var(--brand-solid);border-color:var(--brand-solid);color:#fff}
.step[data-done="1"] i{background:var(--ok-weak);border-color:transparent;color:var(--ok)}
.steps .bar{flex:1;height:1px;background:var(--line-2);min-width:14px}
.step i svg{width:11px;height:11px}
.choice>svg{width:16px;height:16px;color:var(--ink-icon)}

/* choice cards */
.choices{display:grid;gap:var(--s3);grid-template-columns:repeat(2,1fr)}
.choice{display:flex;align-items:center;gap:var(--s3);padding:var(--s4);border-radius:var(--r);text-align:start;
  border:1px solid var(--line-2);background:var(--card);transition:border-color var(--t-fast),background var(--t-fast);width:100%}
.choice:hover:not([disabled]){border-color:var(--line-3);background:var(--hover)}
.choice[aria-pressed="true"]{border-color:var(--brand);background:var(--brand-weak);box-shadow:0 0 0 1px var(--brand)}
.choice[disabled]{opacity:.55;cursor:not-allowed}
.choice__b{flex:1;min-width:0}
.choice__b b{display:block;font-size:13.5px;font-weight:600;letter-spacing:-.01em}
.choice__b span{display:block;font-size:11.5px;color:var(--ink-3)}
.choice--sm{padding:10px var(--s3)}
/* A locked or pending service. Not a button and not dimmed either: it carries
   a live request-access button of its own, and dimming the card would dim the
   one control on it. The sunk fill is what says "not available", the dashed edge
   that it is not permanent. */
.choice--lock{flex-wrap:wrap;cursor:default;background:var(--sunk);border-style:dashed}
.choice--lock:hover{background:var(--sunk);border-color:var(--line-2)}
.choice--lock .choice__b b{color:var(--ink-2)}
.choice__act{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none}
.choice__note{flex-basis:100%;display:flex;align-items:flex-start;gap:6px;font-size:11.5px;
  line-height:1.6;padding-top:var(--s2);border-top:1px dashed var(--line-2);margin-top:2px}
.choice__note svg{width:13px;height:13px;flex:none;margin-top:3px}
@media (max-width:400px){
  .choice__act{flex-basis:100%;flex-direction:row;align-items:center;justify-content:flex-end;
    padding-top:var(--s2)}
}

/* sheet / drawer */
/* the scrim carries a stronger blur than the sheet so the page behind reads as
   out of focus; the scrim itself holds no text */
/* 🔴 `position:fixed`, not `absolute`. The scrim used to be absolute inside
   `.app`, which is only as tall as a screen when the page happens to fit one.
   MEASURED 1405/06/26 on the live panel: on a 1280x860 desktop the buy-pack
   dialog is 671px tall and 117 of them were on screen, because it was centred
   in a 1600px frame; on a 375x812 phone the «بیشتر» menu opened at y=814, two
   pixels below the bottom edge, so the screen went dark and showed nothing.
   `render()` used to scroll the document to the top of the frame to chase it,
   and that scroll is what the owner read as "it reloads on every click".
   A popup is anchored to the VIEWPORT. */
.scrim{position:fixed;inset:0;background:rgba(4,6,10,.66);
  backdrop-filter:saturate(140%) blur(8px);-webkit-backdrop-filter:saturate(140%) blur(8px);z-index:90;
  display:flex;align-items:center;justify-content:center;padding:var(--s6) var(--s5);
  animation:fade var(--t) both}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes slideIn{from{transform:translateX(-14px);opacity:0}to{transform:none;opacity:1}}
@keyframes slideUp{from{transform:translateY(18px);opacity:0}to{transform:none;opacity:1}}
/* the sheet floats, so it gets the rounder radius, the strong glass fill and
   the widest lift. Its sticky header and footer stay solid --panel below, so
   no sticky text ever sits on a moving blur. */
.sheet{background:var(--glass-strong);backdrop-filter:var(--glass-blur);-webkit-backdrop-filter:var(--glass-blur);
  width:min(520px,100%);max-height:min(100%,78vh);overflow-y:auto;
  border:1px solid var(--rim);border-radius:var(--r-xl);box-shadow:var(--lift-lg);
  animation:popIn var(--t) both;display:flex;flex-direction:column}
@keyframes popIn{from{transform:scale(.97) translateY(10px);opacity:0}to{transform:none;opacity:1}}
.sheet__hd{display:flex;align-items:center;gap:var(--s3);padding:var(--s5) var(--s6);
  border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--panel);z-index:2}
.sheet__hd h2{font-size:17px;font-weight:600;letter-spacing:-.02em;line-height:1.35}
.sheet__bd{padding:var(--s6);display:flex;flex-direction:column;gap:var(--s5)}
.sheet__ft{margin-top:auto;position:sticky;bottom:0;background:var(--panel);border-top:1px solid var(--line);
  padding:var(--s4) var(--s6);display:flex;gap:var(--s3);align-items:center}
/* One primary action, and it is the obvious target: pushed to the end of the
   row and given a real hit area. Everything before it is secondary by
   position as much as by colour.
   RULE: Keyed on the LAST button, not on .btn--pri: a destructive dialog's main
   action is .btn--danger and has no .btn--pri, so the old rule left the very
   button it was written for sitting in the middle of the row. */
.sheet__ft>.btn:last-child{margin-inline-start:auto;min-height:42px;padding-inline:var(--s6)}

/* --- the dialog variant -------------------------------------------------
   A short, non-scrolling popup: a result, a confirmation, a handover. The
   header rule is dropped so the thing reads as one calm block -- but see
   `.sheet--dialog.is-scroll` below, because a title floating over moving
   content is worse than a line. */
.sheet--dialog{width:min(560px,100%)}
.sheet--dialog .sheet__hd{border-bottom:0;padding:var(--s6) var(--s6) 0;align-items:flex-start}
.sheet--dialog .sheet__hd h2{font-size:21px;letter-spacing:-.025em;padding-block:6px}
.sheet--dialog .sheet__bd{padding-top:var(--s5)}
/* RULE: The footer is sticky, so it needs its own padding even without a border:
   with padding-top:0 the buttons sat directly on top of the last block of the
   body and covered it. Dropping the rule is not the fix -- the separation has
   to come from space when it does not come from a line. */
.sheet--dialog .sheet__ft{border-top:0;padding-top:var(--s4)}
.sheet--dialog.is-scroll .sheet__hd{border-bottom:1px solid var(--line);padding-bottom:var(--s4)}
.sheet--dialog.is-scroll .sheet__ft{border-top:1px solid var(--line);padding-top:var(--s4)}
/* Room to scroll clear of the sticky footer. Without it the last line of a
   long dialog can never be brought fully into view. */
.sheet--dialog .sheet__bd{padding-bottom:var(--s3)}

/* the status disc: colour and icon carry the state before the text does */
.dlgmark{width:44px;height:44px;flex:none;border-radius:var(--r-full);
  display:grid;place-items:center;background:var(--brand-weak);color:var(--brand)}
.dlgmark svg{width:22px;height:22px}
.dlgmark--ok{background:var(--ok-weak);color:var(--ok-ink)}
.dlgmark--warn{background:var(--warn-weak);color:var(--warn)}
.dlgmark--bad{background:var(--bad-weak);color:var(--bad)}
.dlghd{display:flex;align-items:center;gap:var(--s4);flex:1;min-width:0}
.dlghd h2{margin:0}
.dlgsub{display:block;font-size:13px;font-weight:400;color:var(--ink-3);margin-top:2px;line-height:1.6}

/* --- callout: a bold first line, a quieter second ------------------------ */
.callout{display:flex;gap:var(--s3);padding:var(--s4);border-radius:var(--r);
  border:1px solid var(--line);background:var(--sunk);font-size:13px;line-height:1.75}
.callout svg{width:18px;height:18px;flex:none;margin-top:2px}
.callout b{display:block;font-size:13.5px;font-weight:600;margin-bottom:2px}
.callout span{display:block;min-width:0}
.callout--warn{background:var(--warn-weak);border-color:color-mix(in srgb,var(--warn) 30%,transparent);color:var(--warn)}
.callout--bad{background:var(--bad-weak);border-color:color-mix(in srgb,var(--bad) 30%,transparent);color:var(--bad)}
.callout--ok{background:var(--ok-weak);border-color:color-mix(in srgb,var(--ok) 30%,transparent);color:var(--ok-ink)}

/* --- the value you are meant to take away -------------------------------- */
.takeaway{display:flex;flex-direction:column;gap:7px}
.takeaway__lb{font-size:12.5px;font-weight:500;color:var(--ink-2)}
.takeaway__bx{display:flex;align-items:stretch;border:1px solid var(--line-2);
  border-radius:var(--r-sm);background:var(--sunk);overflow:hidden}
.takeaway__v{flex:1;min-width:0;padding:11px var(--s3);font-size:13px;
  font-family:var(--mono,ui-monospace,SFMono-Regular,Menlo,monospace);
  overflow-x:auto;white-space:nowrap;direction:ltr;text-align:left;
  scrollbar-width:none}
.takeaway__v::-webkit-scrollbar{height:0}
/* The action belongs to the field, so it is attached to it rather than
   floating nearby with its own border. */
.takeaway__bx .btn{border:0;border-radius:0;border-inline-start:1px solid var(--line-2);
  min-height:auto;padding-inline:var(--s4);background:var(--card)}
.takeaway__bx .btn:hover{background:var(--hover)}

.kv{display:grid;grid-template-columns:auto 1fr;gap:9px var(--s4);font-size:13px;align-items:center}
.kv dt{color:var(--ink-3);font-size:12.5px}
.kv dd{margin:0;text-align:end;font-weight:500}

.list{display:flex;flex-direction:column}
.li{display:flex;align-items:center;gap:var(--s3);padding:11px var(--s5);border-bottom:1px solid var(--line)}
.li:last-child{border-bottom:0}
.li__b{flex:1;min-width:0}
.li__b b{display:block;font-size:13px;font-weight:500}
.li__b span{display:block;font-size:11.5px;color:var(--ink-4)}
/* A list row that stacks instead of sitting on one line. The server capacity
   card needs it: a server is a title, two measured figures, four inputs and
   two buttons, and forcing that into the one-line .li puts the save button
   off the edge of a phone. */
.li--col{flex-direction:column;align-items:stretch;gap:var(--s2)}
/* "this field takes the rest of the row" -- for a URL next to a key, where
   both should share the width rather than one hugging its content. */
.field--grow{flex:1;min-width:160px}

.note{display:flex;gap:10px;padding:11px var(--s4);border-radius:var(--r);font-size:12.5px;line-height:1.7;
  border:1px solid var(--line-2);background:var(--sunk);color:var(--ink-2)}
.note svg{width:16px;height:16px;flex:none;margin-top:3px}
.note--warn{background:var(--warn-weak);border-color:color-mix(in srgb,var(--warn) 28%,transparent);color:var(--warn)}
.note--bad{background:var(--bad-weak);border-color:color-mix(in srgb,var(--bad) 28%,transparent);color:var(--bad)}
.note--brand{background:var(--brand-weak);border-color:color-mix(in srgb,var(--brand) 28%,transparent);color:var(--brand)}
.note--ok{background:var(--ok-weak);border-color:color-mix(in srgb,var(--ok) 28%,transparent);color:var(--ok)}
/* A list row that is a button (an open deposit claim reopens its sheet). */
.li--btn{width:100%;background:none;border:0;border-bottom:1px solid var(--line);color:inherit;
  font:inherit;text-align:start;cursor:pointer}
.li--btn:hover{background:var(--hover,rgba(127,127,127,.06))}
.li--btn:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
/* 💳 1405/07/03 the exact unique amount on the top-up sheet: the one number
   the shop must type into its banking app, so it is the loudest thing there. */
.payamt{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.payamt b{font-size:22px;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
/* 📝 signup: two short optional fields side by side, stacked on a phone. */
.row.wrap>.flex1{min-width:140px}

.impersonate{display:flex;align-items:center;gap:10px;padding:9px var(--s5);font-size:12.5px;font-weight:500;
  background:var(--bad-weak);color:var(--bad);border-bottom:1px solid color-mix(in srgb,var(--bad) 30%,transparent)}
.impersonate svg{width:15px;height:15px;flex:none}

.app--plain{grid-template-columns:1fr}
.loginwrap{min-height:758px;display:grid;place-items:center;padding:var(--s7) var(--s4)}
/* min-width:0 so the grid item may actually be narrower than its content --
   without it `place-items:center` still hands the box its content width and
   the page scrolls sideways. */
.loginbox{width:min(410px,100%);min-width:0;display:flex;flex-direction:column;gap:var(--s4)}
.loginbox .card{min-width:0}
.dot{width:7px;height:7px;border-radius:50%;background:var(--brand);flex:none}
.gifthero{background:linear-gradient(150deg,color-mix(in srgb,var(--brand) 16%,var(--card)) 0%,var(--card) 62%);
  border:1px solid color-mix(in srgb,var(--brand) 30%,transparent);border-radius:var(--r-lg);padding:var(--s4) var(--s5)}
.plangrid{grid-template-columns:repeat(3,1fr)}
.bcgrid{display:grid;gap:var(--s3);grid-template-columns:1.25fr 1fr}
.prev{border:1px dashed var(--line-3);border-radius:var(--r);padding:var(--s4);background:var(--sunk)}
/* import steps for a file delivery: the numbers ARE the content (do this,
   then this), so they are a real <ol> and not a styled list of divs */
.steps-num{width:100%;margin:0;padding:0;list-style:none;counter-reset:st;
  display:flex;flex-direction:column;gap:8px;text-align:start}
.steps-num li{counter-increment:st;display:flex;align-items:flex-start;gap:9px;
  font-size:12.5px;line-height:1.7;color:var(--ink-2)}
.steps-num li::before{content:counter(st);flex:none;width:20px;height:20px;border-radius:50%;
  display:grid;place-items:center;font-size:11px;font-weight:600;margin-top:2px;
  background:var(--vip-weak);color:var(--c4);border:1px solid color-mix(in srgb,var(--c4) 26%,transparent)}
/* the note under a queued access request */
.reqnote{display:flex;align-items:flex-start;gap:6px;line-height:1.6}
.reqnote svg{width:12px;height:12px;flex:none;margin-top:4px;color:var(--ink-icon)}

.credrow{display:flex;align-items:center;gap:var(--s2);padding:8px 0;border-bottom:1px solid var(--line)}
.credrow:last-child{border-bottom:0}
.credrow span:first-child{font-size:12px;color:var(--ink-3);width:88px;flex:none}
.credrow .mono{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px}
/* 🔢 A row of numbers, each its own LTR chip and its own copy. Never one
   mixed-direction sentence inside `.mono`. */
.credrow--tok{flex-wrap:wrap}
.toks{display:flex;gap:var(--s2);flex-wrap:wrap;flex:1 1 100%;min-width:0}
.tok{min-height:44px;padding:8px 16px;border-radius:var(--r-sm);border:1px solid var(--line);
  background:var(--sunk);color:var(--ink-1);font-family:var(--mono);font-size:15px;
  cursor:pointer;letter-spacing:.5px}
.tok--main{border-color:var(--brand);font-weight:700}
/* 🗂 The optional half of a delivery sheet.
   🪤 `dfold` and not `fold`: a DEAD `.fold` further down this file (a
   `grid-template-rows:0fr` collapser driven by `data-open`, which no template
   emits any more) sits AFTER this block, so a `<details class="fold">` would
   have been collapsed by a rule for a component that no longer exists. */
.dfold{border:1px solid var(--line);border-radius:var(--r-md);margin-top:var(--s3);background:var(--sunk)}
.dfold>summary{cursor:pointer;padding:12px var(--s4);font-size:13px;color:var(--ink-3);
  min-height:44px;display:flex;align-items:center;gap:8px;list-style:none}
.dfold>summary::-webkit-details-marker{display:none}
.dfold>summary::after{content:"\25BE";margin-inline-start:auto;font-size:11px}
.dfold[open]>summary::after{content:"\25B4"}
.dfold[open]>summary{border-block-end:1px solid var(--line)}
.dfold__b{padding:var(--s2) var(--s3) var(--s3)}

/* charts */
.chart-h{display:flex;align-items:baseline;gap:var(--s2);margin-bottom:var(--s3)}
.chart-h h3{font-size:13.5px;font-weight:600;letter-spacing:-.01em}
/* ↔️ MEASURED 1405/06/29 at 375px: thirty columns, each with a 9.5px day
   label, gave the chart a floor width of ~470px, so the whole DOCUMENT went to
   499px -- the top bar and the tab bar slid 101px to the left and every card
   on «گزارش‌ها» moved with them. A chart scrolls inside its own box or it is
   not on a phone at all: `min-width:0` lets the flex item shrink below its
   content, and the columns keep a readable floor inside the scroller. */
.bars{display:flex;align-items:flex-end;gap:3px;height:104px;
  min-width:0;max-width:100%;overflow:hidden}
.bars>div{flex:1 1 0;min-width:0;display:flex;flex-direction:column;justify-content:flex-end;gap:5px;align-items:center;
  border-radius:5px;padding-bottom:2px;transition:background var(--t-fast);cursor:default}
/* A printed label overflows its own 10px column on purpose -- `barChart` only
   prints one every few bars, so there is room beside it and nothing to push. */
.bars b{white-space:nowrap;overflow:visible}
.bars b.bhide{min-height:1em}
.bars>div:hover{background:var(--hover)}
.bars i{display:block;width:100%;max-width:22px;border-radius:4px 4px 2px 2px;background:var(--c1);
  transition:opacity var(--t-fast)}
.bars>div:hover i{opacity:.75}
.bars b{font-size:12px;color:var(--ink-4);font-weight:400}
.compo{display:flex;gap:2px;height:11px;border-radius:var(--r-full);overflow:hidden}
.compo>i{display:block;height:100%}
.legend{display:flex;flex-direction:column;gap:7px;margin-top:var(--s3)}
.legend>div{display:flex;align-items:center;gap:8px;font-size:12.5px}
.legend em{width:9px;height:9px;border-radius:3px;flex:none;font-style:normal}
.legend span{color:var(--ink-3);margin-inline-start:auto;font-size:12px}

/* RULE: a pill with no ceiling is a pill the width of its longest message.
   A real error sentence made this wider than the phone, and because it is
   centred with a transform it then hung off BOTH edges at once. */
/* RULE: centred WITHOUT a transform. The slideUp keyframe ends on
   `transform:none` and is filled `both`, so a centring transform is erased
   for the whole life of the toast -- leaving `inset-inline-start:50%` alone,
   which pins the pill's trailing edge to the middle and hangs the rest of it
   off to one side. That is where it has always landed; widening it to 420px
   only made it visible. inset-inline:0 + margin-inline:auto centres a
   fit-content box and leaves `transform` to the animation. */
.toast{position:absolute;inset-block-end:22px;inset-inline:0;margin-inline:auto;
  width:fit-content;z-index:120;
  background:var(--ink);color:var(--bg);padding:10px 16px;font-size:13px;font-weight:500;
  /* 999px while it is one line, a sane corner once it wraps: a two-line block
     with a 999px radius reads as a mistake, not as a pill. */
  border-radius:var(--r-lg);
  max-width:min(92vw,420px);line-height:1.7;text-align:start;
  display:flex;align-items:flex-start;gap:8px;box-shadow:var(--shadow-lg);
  animation:slideUp var(--t) both}
.toast svg{width:15px;height:15px;flex:none;margin-top:3px}

.empty{display:flex;flex-direction:column;align-items:center;gap:10px;padding:var(--s8) var(--s5);text-align:center}
.empty svg{width:26px;height:26px;color:var(--ink-icon)}
.empty b{font-size:14px;font-weight:600}
.empty p{font-size:12.5px;color:var(--ink-3);max-width:34ch}

/* ============================================================
   BACKDROP-FILTER FALLBACK · mandatory, not a nicety.
   A translucent fill with no blur behind it puts text on top of whatever
   happens to scroll past. So where the browser cannot blur, every glass fill
   goes fully opaque. Must stay AFTER the glass rules to win on order.
   The scrim is exempt from "opaque" (it carries no text and is meant to be
   see-through) but darkens, so the sheet still separates from the page.
   ============================================================ */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .tabs,.topbar,.side,.sheet{background:var(--panel)}
  .scrim{background:rgba(4,6,10,.84)}
}

/* ============================================================
   RESPONSIVE — real media query, same breakpoint behaviour the
   mockup's data-vp="mobile" switch showed. The 390px phone frame
   was review chrome and is gone; the app is full-bleed instead.
   ============================================================ */
@media (max-width:860px){
.stage{padding:0}
/* `overflow:hidden` is what rounds the desktop frame's corners over its
   children. Here the radius is 0, so it buys nothing -- and it costs a lot:
   an ancestor with a non-visible overflow becomes the SCROLLPORT that every
   `position:sticky` descendant sticks to, and `.app` does not scroll. That is
   why the sticky topbar scrolled away on a phone and why a sticky action bar
   sat exactly where it was written. Measured 1405/06/26. */
.app{border-radius:0;border-inline-start:0;border-inline-end:0;border-block-start:0;
  min-height:100dvh;overflow:visible}
.loginwrap{min-height:0}
.app{grid-template-columns:1fr}
.side{display:none}
/* Room for the floating bar. MEASURED 1405/06/26 on a 375x812 phone: the bar
   is 74px tall and sits 14px off the bottom edge, so it owns the bottom 88px.
   At 76px the last 12px of the content -- which on the wizard is the bottom
   edge of the «ادامه» button -- sat underneath it and could not be tapped.
   88 + 16 of breathing room. */
.content{padding:var(--s4) var(--s4) calc(104px + env(safe-area-inset-bottom, 0px));gap:var(--s5)}
.topbar{padding:var(--s3) var(--s4)}
.topbar h1{font-size:16px}
.hide-m{display:none!important}
.only-m{display:flex!important}
.tabs{display:grid}
/* Above the floating bar, not behind it: the bar sits 14px from the bottom and
   is about 56px tall, and a toast at 22px was underneath it. */
.toast{inset-block-end:calc(100px + env(safe-area-inset-bottom, 0px))}
.bento{grid-template-columns:repeat(2,1fr)}
.tile--w2{grid-column:span 2}
.choices{grid-template-columns:1fr}
/* ============================================================
   🔴 A POPUP BELONGS TO THE VIEWPORT, NOT TO THE DOCUMENT.
   `.scrim` is `position:absolute; inset:0` of `.app`, which on a desktop is a
   fixed-height frame -- so centring inside it was centring on screen. On a
   phone `.app` is as tall as the whole page, and the scrim inherited that.
   MEASURED 1405/06/26 at 375x812: tapping «بیشتر» on the home screen (a
   2124px page) put the menu at y=814 -- two pixels BELOW the bottom of the
   screen. The reseller saw the page go dark and nothing else. On the wallet
   (2895px) the buy-pack sheet opened 1130px below the fold, and `render()`
   had to scroll the page to the top to try to catch it, which is the jump
   that reads as "it reloads on every click".
   Fixed positioning + bottom alignment is the phone answer: the sheet comes
   up from the thumb, it is always where it was opened from, and the page
   behind it is locked so it cannot be scrolled away from underneath. */
.scrim{align-items:flex-end;justify-content:center;padding:0}
.sheet{width:100%;max-height:88dvh;
  border-radius:var(--r-xl) var(--r-xl) 0 0;border-inline:0;border-block-end:0}
/* the footer is the last thing a thumb reaches, so it clears the home indicator */
.sheet__ft{padding-block-end:calc(var(--s4) + env(safe-area-inset-bottom, 0px))}
.plangrid{grid-template-columns:repeat(2,1fr)}
.bcgrid{grid-template-columns:1fr}

/* ---- one row of filter chips, not three -------------------------------
   MEASURED: the customers screen has 12 chips at 31px; wrapped, they took
   three rows and ~200px, which pushed the list itself below the fold on
   every phone. A filter strip scrolls sideways; it does not eat the screen.
   The negative margin lets the strip bleed to both edges so the last chip
   does not look clipped by a gutter. */
.chiprow{flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
  margin-inline:calc(-1 * var(--s4));padding-inline:var(--s4);
  scroll-snap-type:x proximity;scrollbar-width:none}
.chiprow::-webkit-scrollbar{display:none}
.chiprow>*{flex:none;scroll-snap-align:start}

/* ---- the step's own action bar, above the floating nav -----------------
   A wizard step's primary button was the last thing in a scrolling page, so
   on every step the reseller had to scroll to the very bottom to find out
   there WAS a next step -- and then it was under the bar. Sticky keeps it
   where the thumb already is. `bottom` is the bar's 88px plus its gap. */
.wizfoot{position:sticky;z-index:15;
  bottom:calc(96px + env(safe-area-inset-bottom, 0px));
  margin-inline:calc(-1 * var(--s4));
  padding:var(--s3) var(--s4);
  background:var(--glass);backdrop-filter:var(--glass-blur);
  -webkit-backdrop-filter:var(--glass-blur);
  border-block-start:1px solid var(--rim)}

/* ---- touch targets ------------------------------------------------------
   MEASURED at 375px: topbar icon buttons 34x34, `.btn--sm` 30px tall, filter
   chips 31px, inputs and selects 38px. Nothing here changes a colour or a
   font -- only the box a finger has to land in. */
/* 👆 44px in BOTH axes. The previous pass raised the width of a small icon
   button to 38px and left `min-height:30px` from `.btn--sm` winning, so every
   copy button in a delivery sheet -- seven to nine of them, and the most
   repeated action a reseller has -- was a 38x30 target. */
.btn--icon{min-width:44px;min-height:44px}
.btn--sm{min-height:44px}
.btn--sm.btn--icon{min-width:44px;min-height:44px}
.pill--btn{min-height:44px;padding-block:9px}
.input,.sel,input,select,textarea,button[type=submit]{min-height:44px}
.tab{min-height:46px;justify-content:center}
}

/* The page behind an open popup must not scroll. `:has()` is the no-JS half;
   app.js also sets `.has-sheet`, because a browser without `:has()` would
   otherwise let the sheet be scrolled off the screen again. */
html:has(.scrim),html.has-sheet,
body:has(.scrim),body.has-sheet{overflow:hidden}

/* ============================================================
   UTILITIES — the mockup carried these as inline style="…"
   attributes. The panel's CSP is `style-src 'self' 'nonce-…'`
   with no unsafe-inline, which blocks style ATTRIBUTES as well as
   inline <style> elements, so every one of them is lifted here
   with its value unchanged. Selectors are doubled (.card.card--x)
   wherever the rule has to out-specify a media-query override.
   Genuinely dynamic values (meter width, bar height) are set
   through the CSSOM in app.js — CSP does not police that.
   ============================================================ */
.w-full{width:100%}
.w-auto{width:auto}
.flex1{flex:1}
.minw0{min-width:0}
.dispblock{display:block}
.jc-center{justify-content:center}
.jc-end{justify-content:flex-end}
.ai-center{align-items:center}
.ai-start{align-items:flex-start}
.as-start{align-self:flex-start}
.fd-col{flex-direction:column}
.stack{display:flex;flex-direction:column;gap:var(--s4)}
.stack3{display:flex;flex-direction:column;gap:var(--s3)}
.stack5{display:flex;flex-direction:column;gap:var(--s5)}
.grid2{display:grid;gap:var(--s3);grid-template-columns:1fr 1fr}
.g-4{gap:4px}
.g-6{gap:6px}
.g-7{gap:7px}
.g-10{gap:10px}
.g-s2{gap:var(--s2)}
.g-s3{gap:var(--s3)}
.g-s6{gap:var(--s6)}
.mis-auto{margin-inline-start:auto}
.mis-s2{margin-inline-start:var(--s2)}
.mis-s3{margin-inline-start:var(--s3)}
.mt-2px{margin-top:2px}
.mt-4px{margin-top:4px}
.mt-5px{margin-top:5px}
.mt-6px{margin-top:6px}
.mt-8px{margin-top:8px}
/* Centre a block inside a column flex/grid parent, where text-align cannot
   reach it -- the status disc on the application-sent screen. */
.mx-auto{margin-inline:auto}
.mt-10px{margin-top:10px}
.mt-s3{margin-top:var(--s3)}
.mt-s4{margin-top:var(--s4)}
.pad4{padding:var(--s4)}
.mw-220{max-width:220px}
.mw-320{max-width:320px}
.mw-34ch{max-width:34ch}
.ta-start{text-align:start}
.ta-end{text-align:end}
.ta-center{text-align:center}
.fs-10{font-size:10px}
.fs-12{font-size:12px}
.fs-13{font-size:13.5px}
.fs-14{font-size:14px}
.fs-15{font-size:15px}
.fs-16{font-size:16px}
.fs-17{font-size:17px}
.fs-19{font-size:19px;letter-spacing:-.02em}
.fw-4{font-weight:400}
.fw-6{font-weight:600}
.c-ok{color:var(--ok)}
.c-warn{color:var(--warn)}
.c-bad{color:var(--bad)}
.c-brand{color:var(--brand)}
.c-ink2{color:var(--ink-2)}
.bg-c1{background:var(--c1)}
.bg-c2{background:var(--c2)}
.bg-c3{background:var(--c3)}
.bg-c0{background:var(--c0)}
.bg-c4{background:var(--c4)}
.bg-c5{background:var(--c5)}
.hr{height:1px;background:var(--line)}
.hr-flex{height:1px;background:var(--line);flex:1}
.dot-sp{width:7px;flex:none}
.card.card--stack{display:flex;flex-direction:column;gap:var(--s4)}
.card.card--stack3{display:flex;flex-direction:column;gap:var(--s3)}
.card.card--center{align-items:center;text-align:center}
.card.card--pad4{padding:var(--s4)}
.card.card--sunk{background:var(--sunk)}
.card.card--block{display:block}
.card.card--col{flex-direction:column}
.brandmark--sm{width:30px;height:30px;border-radius:9px}
.brandmark--md{width:40px;height:40px;border-radius:11px}
.brandmark--lg{width:44px;height:44px;border-radius:13px}
.input.input--search{width:280px}
.input.input--grow{flex:1;max-width:320px}
.input.input--w120{width:120px}
.input.input--drop{min-height:74px;align-items:center;justify-content:center}
.input.input--area{min-height:96px;align-items:flex-start;padding-top:9px}
.input textarea{flex:1;min-width:0;border:0;background:none;outline:none;font-size:13.5px;
  padding:8px 0;font-family:inherit;line-height:1.65;resize:vertical}
.input textarea::placeholder{color:var(--ink-4)}
label.input{cursor:pointer}
.file-hidden{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden;clip-path:inset(50%)}
.pill.pill--btn{cursor:pointer;padding:5px 12px}
.pill.pill--dot{width:9px;height:9px;padding:0;border-radius:50%;flex:none}
.rowcard.rowcard--bare{border:0;padding:0;flex:1}
.tbl tbody tr.row-static{cursor:default}
.tbl tbody tr.row-static:hover{background:none}
.td-w140{min-width:140px}
.td-w150{min-width:150px}
.choices.choices--2{grid-template-columns:repeat(2,1fr)}
.choices.choices--3{grid-template-columns:repeat(3,1fr)}
.choices.choices--4{grid-template-columns:repeat(4,1fr)}
.choices.choices--5{grid-template-columns:repeat(5,1fr)}
.choice.choice--auto{width:auto}
.hero__v.hero__v--26{font-size:26px}
.list.list--boxed{border:1px solid var(--line);border-radius:var(--r)}
.deliver{display:flex;flex-direction:column;gap:var(--s3);align-items:center}
.packmeter{display:block;margin-top:5px;max-width:220px}

/* ---------- loading · skeleton · spinner (new: the mockup had
   no loading state because it had no server) ---------- */
.skel{background:var(--sunk);border:1px solid var(--line);border-radius:var(--r-sm);
  position:relative;overflow:hidden}
/* 1405/07/03 owner: «خیلی تند و بد می‌چرخه». Calmer: 1.8s, eased, and only
   after 300ms -- a response that lands before then never shows a shimmer. */
.skel::after{content:"";position:absolute;inset:0;opacity:0;
  animation:ldin .25s ease .3s forwards,shimmer 1.8s ease-in-out .3s infinite;
  background:linear-gradient(90deg,transparent,var(--hover),transparent)}
@keyframes shimmer{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
.skel--line{height:12px}
.skel--w40{width:40%}
.skel--w60{width:60%}
.skel--w80{width:80%}
.skel--tall{height:44px}
.skel--tile{height:88px;border-radius:var(--r-lg)}
.skel--hero{height:168px;border-radius:var(--r-lg)}
.skelrows{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s5)}
/* 1405/07/03 owner: «این سرعت لودینگ پنل رو کم کن! خیلی تند و بد می‌چرخه».
   1.2s a turn with an ease (slow-fast-slow reads as "working", a hard linear
   whirl read as "frantic"), and invisible for the first 300ms so a quick
   answer never flashes a spinner at all. Both themes use the same tokens. */
.spin{width:18px;height:18px;border-radius:50%;flex:none;opacity:0;
  border:2px solid var(--line-2);border-top-color:var(--brand);
  animation:ldin .25s ease .3s forwards,spin 1.2s cubic-bezier(.55,.15,.45,.85) infinite}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes ldin{to{opacity:1}}
@keyframes ldpulse{0%,100%{opacity:.35}50%{opacity:1}}
/* RULE: inside a filled button the ring must come from the button's own text
   colour. It used to be --brand on --brand: a blue arc on a blue button,
   invisible at exactly the moment the person is asking "did my tap do
   anything?" -- which is the only moment this spinner exists for. */
.btn--pri .spin,.btn--danger .spin,.btn--ok .spin{
  border-color:color-mix(in srgb,currentColor 30%,transparent);
  border-top-color:currentColor}
@media (prefers-reduced-motion:reduce){
  /* No rotation and no sweep: a slow breathing ring says "working" without
     motion across the screen. Still delayed, so a fast answer shows nothing. */
  .spin{animation:ldin .25s ease .3s forwards,ldpulse 2s ease-in-out .3s infinite;
    border-color:var(--brand)}
  .btn--pri .spin,.btn--danger .spin,.btn--ok .spin{border-color:currentColor}
  .skel::after{animation:none;opacity:0}
}
.loadbar{display:flex;align-items:center;gap:var(--s2);padding:var(--s5);color:var(--ink-3);font-size:12.5px}

/* ---------- captcha (server-rendered SVG, inlined) ---------- */
/* RULE: a flex item's default min-width is `auto`, so the input below
   refused to shrink and pushed this row -- and the whole login card -- wider
   than a phone screen. The panel is used standing at a counter, on a phone,
   which is precisely where that defect shows. */
.captcha{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.captcha .input{min-width:0}
/* The artwork is 180x60 -- exactly 3:1 -- so the box is 3:1 and the SVG fills
   it. It used to be a fixed 126px with 4px/8px of padding on a white fill,
   which framed the picture in bare white on both sides, and `max-width:100%`
   then squeezed its width while the height stayed pinned at 38px, stretching
   it. The white itself stays: the code's own background is a translucent grey
   drawn to sit on white, and on a dark theme without it the digits would be
   dark ink on near-black. */
.captchaimg{background:#fff;border:1px solid var(--line-2);border-radius:var(--r-sm);
  padding:0;overflow:hidden;flex:none;display:grid;place-items:center;
  /* 138x46 IS 3:1, stated outright rather than left to `aspect-ratio` to
     resolve. An explicit height cannot collapse: if the aspect ever fails to
     apply the box would have no height at all, and an invisible captcha is an
     unusable login page. */
  width:138px;height:46px;max-width:100%}
.captchaimg svg{display:block;width:100%;height:100%}
/* The spinner that stands in while it loads must not be stretched to 3:1. */
.captchaimg .spin{width:18px;height:18px}
/* Below this the image takes its own line and the field gets the next one,
   rather than three things fighting over 300 pixels. */
@media (max-width:380px){
  .captcha .input{flex:1 1 100%;order:2}
  .captcha .btn--icon{order:3}
}

/* ============================================================
   PACK LADDER  ·  the owner's price list
   Every rung carries three numbers that belong together: the size,
   its per-GB rate and how long the reseller has to spend it. The row
   is one button, because a rung is a single choice.
   ============================================================ */
.ladder{display:flex;flex-direction:column;gap:var(--s2)}
.rung{display:flex;align-items:center;gap:var(--s4);width:100%;text-align:start;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s3) var(--s4);cursor:pointer;color:inherit;font:inherit;
  box-shadow:var(--shadow-sm);
  transition:border-color var(--t-fast),box-shadow var(--t),transform var(--t-fast),background var(--t-fast)}
.rung:hover{border-color:var(--line-3);box-shadow:var(--lift-sm);transform:translateY(-1px)}
.rung:active{transform:translateY(0) scale(.995)}
.rung:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* The cheapest rate on the ladder. A rim, not a fill: the row is already a
   button and a second filled surface inside it fights the price for attention. */
.rung[data-best]{border-color:color-mix(in srgb,var(--ok) 45%,var(--line));
  background:linear-gradient(180deg,color-mix(in srgb,var(--ok-weak) 55%,transparent),transparent)}
.rung__gb{flex:none;min-width:58px;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:1px;background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--r);padding:var(--s2) var(--s2)}
.rung__gb b{font-size:17px;line-height:1;font-variant-numeric:tabular-nums}
.rung__gb small{font-size:12px;color:var(--ink-2)}   /* on --sunk: 7.20:1 */
.rung__b{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.rung__rate{font-size:13.5px;color:var(--ink)}
.rung__rate b{font-size:15px;font-variant-numeric:tabular-nums}
.rung__meta{display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--ink-2)}
.rung__meta svg{width:13px;height:13px;color:var(--ink-icon)}
.rung__end{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:4px}
.rung__end b{font-size:13.5px;white-space:nowrap}
/* Measured with ux-ui-kit/scripts/contrast.py. --ink-3 on --sunk is 4.35:1
   and --ok on --ok-weak is 4.43:1 -- both under AA for 10.5px text, so both
   move one tier: --ink-2 on --sunk is 7.20:1 light / 10.07:1 dark, and
   --ok-ink on --ok-weak is 5.85:1 light / 7.04:1 dark. */
.tag{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--r-full);
  font-size:12px;background:var(--sunk);color:var(--ink-2);border:1px solid var(--line)}
.tag--ok{background:var(--ok-weak);color:var(--ok-ink);border-color:transparent}
@media (min-width:520px){
  /* Three across once there is room: nine locations then fit in three rows
     and the wizard's "ادامه" stays on the first screen. */
  .locgrid{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:520px){
  .rung{gap:var(--s3);padding:var(--s3)}
  .rung__gb{min-width:48px}
  .rung__end b{font-size:12.5px}
}

/* ============================================================
   MOTION  ·  §"انیمیشن های پنل"
   Everything here is additive polish on an interface that already
   works without it. Two rules:
     - motion never moves layout that the user is reading;
     - every animation is `both`-filled so an interrupted render
       cannot leave an element stuck at opacity 0.
   The global prefers-reduced-motion rule at the top of this file
   already flattens all of it to 0.01ms.
   ============================================================ */

/* --- list and card entrance, staggered by --i (set via the CSSOM) --------- */
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.anim-rise{animation:rise 320ms cubic-bezier(.2,.8,.3,1) both;
  animation-delay:calc(var(--i,0) * 45ms)}
@keyframes fadein{from{opacity:0}to{opacity:1}}
.anim-fade{animation:fadein var(--t) both;animation-delay:calc(var(--i,0) * 35ms)}

/* --- counting numbers -----------------------------------------------------
   The digits are written by JS; this only keeps the box from twitching while
   they change width. Tabular figures are the whole trick: without them a
   count-up jitters as ۱ and ۸ swap in and out. */
.cnum{font-variant-numeric:tabular-nums}
.cnum--run{will-change:contents}

/* --- the tiles: a soft lift on hover, so a dashboard feels alive --------- */
.tile{transition:transform var(--t-fast),box-shadow var(--t),border-color var(--t-fast)}
.tile:hover{transform:translateY(-2px);box-shadow:var(--lift-sm)}

/* --- rows: the whole list breathes in on first paint --------------------- */
.list>.li,.list>.rowcard{animation:rise 300ms cubic-bezier(.2,.8,.3,1) both}
.list>.li:nth-child(1),.list>.rowcard:nth-child(1){animation-delay:0ms}
.list>.li:nth-child(2),.list>.rowcard:nth-child(2){animation-delay:35ms}
.list>.li:nth-child(3),.list>.rowcard:nth-child(3){animation-delay:70ms}
.list>.li:nth-child(4),.list>.rowcard:nth-child(4){animation-delay:105ms}
.list>.li:nth-child(5),.list>.rowcard:nth-child(5){animation-delay:140ms}
.list>.li:nth-child(6),.list>.rowcard:nth-child(6){animation-delay:175ms}
.list>.li:nth-child(n+7),.list>.rowcard:nth-child(n+7){animation-delay:200ms}

/* --- the usage bar fills instead of appearing ---------------------------- */
.bar>i,.usagebar>i,.packmeter i{transition:width 620ms cubic-bezier(.2,.8,.3,1)}

/* --- buttons: a real press, and an icon that answers a hover ------------- */
.btn{transition:background var(--t-fast),border-color var(--t-fast),color var(--t-fast),
  box-shadow var(--t),transform var(--t-fast)}
.btn:active:not(:disabled){transform:scale(.97)}
.btn--pri:hover:not(:disabled){box-shadow:var(--lift-sm)}
.btn--icon svg{transition:transform var(--t)}
.btn--icon:hover svg{transform:scale(1.08)}

/* --- popups: the scrim fades, the sheet arrives from where it was opened -
   On a phone the sheet comes up from the bottom edge, which is where a thumb
   is; on a desktop it scales in place. Same element, two entrances. */
.scrim{animation:fade 160ms both}
.sheet{animation:popIn 240ms cubic-bezier(.2,.9,.3,1) both}
@media (max-width:640px){
  @keyframes sheetUp{from{opacity:0;transform:translateY(22px) scale(.985)}
    to{opacity:1;transform:none}}
  .sheet{animation:sheetUp 260ms cubic-bezier(.2,.9,.3,1) both}
}

/* --- the floating nav: icons lift as they become current ----------------- */
.tab{transition:color var(--t-fast),transform var(--t-fast)}
.tab svg{transition:transform var(--t)}
.tab[aria-current="page"] svg{transform:translateY(-1px) scale(1.06)}
.tab:active{transform:scale(.94)}

/* --- the side nav: the current item slides its marker in ----------------- */
.side__a{transition:background var(--t-fast),color var(--t-fast)}
.side__a svg{transition:transform var(--t)}
.side__a:hover svg{transform:translateX(-2px)}

/* --- collapsible blocks: a real open/close, not a jump ------------------
   `grid-template-rows: 0fr -> 1fr` is the one way to transition to a height
   nobody measured. The inner wrapper must be `min-height:0` and `overflow`
   hidden or the content spills while the row is still collapsing. */
.fold{display:grid;grid-template-rows:0fr;transition:grid-template-rows 260ms cubic-bezier(.2,.8,.3,1)}
.fold>*{min-height:0;overflow:hidden}
.fold[data-open="1"]{grid-template-rows:1fr}
.fold__t svg:last-child{transition:transform var(--t)}
.fold[data-open="1"] .fold__t svg:last-child{transform:rotate(180deg)}

/* --- toast: in from the bottom, and it does not shift the page ----------- */
.toast{animation:slideUp 220ms cubic-bezier(.2,.9,.3,1) both}

/* ============================================================
   ارتباط با ما  ·  the chat
   A conversation, not a ticket form. The log scrolls inside its
   own box so the composer stays reachable without scrolling the
   page, and the page itself never scrolls sideways.
   ============================================================ */
.chat{display:flex;flex-direction:column;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow-sm);overflow:hidden}
.chat__note{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--line);background:var(--sunk)}
.chat__note svg{width:14px;height:14px;color:var(--ink-icon)}
.chat__log{display:flex;flex-direction:column;gap:var(--s3);padding:var(--s4);
  /* Tall enough to be a conversation, short enough that the composer is on
     screen on a phone without scrolling. dvh, because a mobile keyboard
     changes the viewport and vh does not notice. */
  min-height:220px;max-height:min(56dvh,560px);overflow-y:auto;overscroll-behavior:contain}
.chat__box{display:flex;align-items:flex-end;gap:var(--s2);padding:var(--s3) var(--s4);
  border-top:1px solid var(--line);background:var(--panel)}
.chat__foot{padding:0 var(--s4) var(--s3);background:var(--panel)}
.ta{flex:1;min-width:0;background:var(--card);border:1px solid var(--line-2);
  border-radius:var(--r);padding:9px var(--s3);font-size:13.5px;resize:vertical;
  outline:none;transition:border-color var(--t-fast),box-shadow var(--t)}
.ta:focus{border-color:var(--brand);box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 18%,transparent)}
.ta::placeholder{color:var(--ink-4)}
.ta--chat{min-height:44px;max-height:180px}
.btn--send{flex:none;width:44px;height:44px;border-radius:var(--r)}

/* --- one message --------------------------------------------------------- */
.bub{max-width:min(78%,560px);display:flex;flex-direction:column;gap:3px}
.bub__b{padding:9px var(--s3);border-radius:var(--r-lg);font-size:13.5px;line-height:1.75;
  /* A pasted config is one very long token. Without this it pushes the bubble
     past the card and the whole page scrolls sideways. */
  overflow-wrap:anywhere;white-space:normal}
/* The stamp sits outside the bubble on --card (4.83:1 with --ink-3) but the
   line is 11px and shares a row with tinted bubbles, so it takes the same
   tier as everything else small here rather than being the one exception. */
.bub__m{color:var(--ink-2)}
/* Sides follow the RTL convention, not the LTR one: in a Persian messenger
   your own messages sit on the LEFT. `flex-end` IS the left under dir="rtl",
   so this is written in logical properties and needs no mirroring. */
.bub--me{align-self:flex-end}
.bub--me .bub__b{background:var(--brand-weak);color:var(--ink);
  border:1px solid color-mix(in srgb,var(--brand) 22%,transparent);
  border-start-end-radius:var(--r-sm)}
.bub--me .bub__m{text-align:end}
.bub--them{align-self:flex-start}
.bub--them .bub__b{background:var(--sunk);color:var(--ink);border:1px solid var(--line);
  border-start-start-radius:var(--r-sm)}
/* Ours, but not a person answering. Reads as a notice. */
.bub--sys{align-self:center;max-width:min(92%,620px)}
.bub--sys .bub__b{background:var(--warn-weak);color:var(--ink);
  border:1px dashed color-mix(in srgb,var(--warn) 40%,transparent);font-size:12.5px}
.bub--sys .bub__m{text-align:center}

/* ============================================================
   the owner's inbox: list + one open thread
   ============================================================ */
.supwrap{display:grid;grid-template-columns:minmax(240px,300px) 1fr;gap:var(--s4);align-items:start}
.suplist{display:flex;flex-direction:column;gap:var(--s2);background:var(--card);
  border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s2);
  box-shadow:var(--shadow-sm);max-height:70dvh;overflow-y:auto}
.supitem{display:flex;flex-direction:column;gap:3px;text-align:start;width:100%;
  background:none;border:1px solid transparent;border-radius:var(--r);padding:var(--s3);
  cursor:pointer;color:inherit;font:inherit;
  animation:rise 280ms cubic-bezier(.2,.8,.3,1) both;animation-delay:calc(var(--i,0) * 35ms);
  transition:background var(--t-fast),border-color var(--t-fast)}
.supitem:hover{background:var(--hover)}
.supitem--on{background:var(--brand-weak);border-color:color-mix(in srgb,var(--brand) 28%,transparent)}
.supitem:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.supitem__t{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
/* --ink-3 on --brand-weak (the selected row) is 4.23:1 -- the lowest pair on
   this screen and under AA. --ink-2 there is 7.01:1 light / 8.98:1 dark. The
   class carries the colour itself so a `tiny muted` in the markup cannot
   quietly put it back. */
.supitem__p,.supitem__d{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  max-width:100%;color:var(--ink-2)}
.suppane{min-width:0}
.supthread{display:flex;flex-direction:column;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow-sm);overflow:hidden}
.supthread__hd{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) var(--s4);
  border-bottom:1px solid var(--line);background:var(--panel)}
.supempty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s2);
  min-height:220px;background:var(--sunk);border:1px dashed var(--line-2);border-radius:var(--r-lg)}
.supempty svg{width:26px;height:26px;color:var(--ink-icon)}
/* The back button belongs to the phone layout only. */
.hide-d{display:none!important}
@media (max-width:860px){
  /* One pane at a time: the list, until a shop is picked. */
  .supwrap{grid-template-columns:1fr}
  .supwrap--open .suplist{display:none}
  .suplist{max-height:none}
  .hide-d{display:inline-flex!important}
  .bub{max-width:88%}
}

/* The bottom bar's "there is something under the menu" dot. Positioned on the
   tab, not in its text flow, so it cannot push the label off centre. */
.tab{position:relative}
.tabdot{position:absolute;top:6px;inset-inline-end:calc(50% - 15px);width:7px;height:7px;
  border-radius:50%;background:var(--bad);box-shadow:0 0 0 2px var(--glass);
  animation:dotpop 320ms cubic-bezier(.2,1.5,.4,1) both}
@keyframes dotpop{from{transform:scale(0)}to{transform:scale(1)}}

/* ============================================================
   SCROLLBARS
   There was no scrollbar styling at all, so Windows drew its
   classic grey slab -- complete with arrow buttons -- along the
   popup's rounded edge, in colours belonging to no theme here.
   One rule set for the whole app rather than per component, so a
   scroll container added later cannot be forgotten.
   ============================================================ */
/* Firefox and the standard property. `thin` is narrower than anything
   ::-webkit-scrollbar can express, so the two never match exactly -- they only
   have to agree on the COLOUR, which is what reads as belonging to the panel. */
*{scrollbar-width:thin;scrollbar-color:var(--line-3) transparent}

/* Chromium/Edge (what the owner is on). Track transparent so the surface
   underneath shows through, which is what keeps the bar inside the popup
   rather than looking bolted to its edge. */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{
  background:var(--line-3);
  border-radius:var(--r-full);
  /* A transparent border makes the thumb read as inset, so it does not touch
     the rounded corner it sits against. `background-clip:padding-box` is what
     makes the border show the track instead of the thumb colour. */
  border:2px solid transparent;
  background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:var(--ink-icon);background-clip:padding-box}
/* The arrow buttons at each end are the loudest part of the native bar and
   nothing in this design has an equivalent. */
::-webkit-scrollbar-button{display:none}
::-webkit-scrollbar-corner{background:transparent}

/* The popup carries its own, one tone quieter: it sits on the glass fill, and
   the app's --line-3 is tuned for the flat card behind it. */
.sheet{scrollbar-color:color-mix(in srgb,var(--ink-3) 45%,transparent) transparent}
.sheet::-webkit-scrollbar-thumb{
  background:color-mix(in srgb,var(--ink-3) 45%,transparent);
  background-clip:padding-box}
.sheet::-webkit-scrollbar-thumb:hover{
  background:color-mix(in srgb,var(--ink-3) 70%,transparent);
  background-clip:padding-box}
/* The scrollable area starts below the sticky header, so the thumb must not
   ride over the header's rounded top corner. */
.sheet{scroll-padding-block-start:56px}

/* A block whose number is being re-read. Dimmed, not replaced: the old figure
   is still the best one we have while the new one is in flight, and blanking
   it would make a 300ms refresh look like a failure. */
.is-loading{position:relative}
.is-loading .num{opacity:.55;transition:opacity var(--t)}

/* 📲 تیترِ دستگاه ("اندروید"، "ویندوز") بالای هر تکه از فهرستِ برنامه‌ها.
   یک ردیفِ کوچکِ چسبیده به فهرستِ زیرش، نه یک کارتِ جدا: در یک کارتِ
   «وی‌تو‌ری» پنج دستگاه پشتِ هم می‌آیند و پنج کارت، همان صفحه را دو برابر
   بلند می‌کرد. خط بالا فقط از دومی به بعد کشیده می‌شود تا زیرِ سرِ کارت
   دو خط روی هم نیفتد. */
.osrow{padding:var(--s3) var(--s4) var(--s2);font-size:11.5px;color:var(--ink-4)}
.osrow+.list{margin-bottom:var(--s2)}
.list+.osrow{border-top:1px solid var(--line)}

/* 1405/07/03 legs audit: a pill or a row placed inside a list body (the
   campaign code on a notification, the bank-SMS hint on a deposit) must not
   inherit `.li__b span{display:block}` and stretch to the full width. */
.li__b span.pill{display:inline-flex;width:auto}
.li__b span.row{display:flex}
/* A copy button beside a long value keeps its one line («کپی نام» broke in two
   at 375px next to a holder's full name). */
.btn.nowrap{white-space:nowrap;flex-shrink:0}

/* ============================================================
   🕵️ OVERSIGHT (1405/07/03 round 2, deploy B)
   «مسیر مغازه‌ها»: a vertical funnel -- one row per step, a centred bar whose
   width is the share of shops that reached it (the silhouette narrows like a
   funnel), and every shop as a chip on the last step it reached. Stuck =
   the warm amber of --warn / --c5; a money alert adds a red dot. Tokens only,
   so both themes follow; widths arrive through data-w (CSP: no inline style).
   ============================================================ */
.jseg{display:flex;gap:4px;padding:4px;background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--r-full);width:max-content;max-width:100%;overflow-x:auto;scrollbar-width:none}
.jseg::-webkit-scrollbar{display:none}
.jseg__b{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border:0;border-radius:var(--r-full);
  background:transparent;color:var(--ink-2);font:inherit;font-size:13px;white-space:nowrap;cursor:pointer;
  transition:background var(--t-fast),color var(--t-fast)}
.jseg__b svg{width:16px;height:16px}
.jseg__b[aria-selected="true"]{background:var(--card);color:var(--ink);font-weight:600;box-shadow:var(--lift-sm)}
.jpath{list-style:none;margin:0;padding:var(--s4) var(--s5) var(--s2);display:flex;flex-direction:column}
.jstep{position:relative;display:grid;grid-template-columns:36px minmax(0,1fr);gap:var(--s3);padding-bottom:var(--s4);
  animation:jin .45s cubic-bezier(.2,.8,.3,1) both;animation-delay:calc(var(--i,0) * 45ms)}
.jstep::before{content:"";position:absolute;inset-inline-start:17px;top:38px;bottom:2px;width:2px;border-radius:2px;
  background:linear-gradient(var(--brand),color-mix(in srgb,var(--brand) 15%,transparent));opacity:.55}
.jstep:last-child::before{display:none}
.jstep__dot{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;font-weight:700;font-size:14px;
  background:var(--brand-weak);color:var(--brand);border:2px solid color-mix(in srgb,var(--brand) 40%,transparent)}
.jstep--hot .jstep__dot{background:var(--warn-weak);color:var(--warn);border-color:color-mix(in srgb,var(--warn) 60%,transparent);
  box-shadow:0 0 0 5px color-mix(in srgb,var(--warn) 14%,transparent)}
.jstep--empty .jstep__dot{opacity:.55}
.jstep__body{min-width:0;display:flex;flex-direction:column;gap:8px;padding-top:5px}
.jstep__hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.jstep__hd b{font-size:14.5px}
.jstep__n{font-weight:700;font-variant-numeric:tabular-nums}
.jstep__n small{font-weight:400;font-size:11.5px;color:var(--ink-3);margin-inline-start:4px}
.jstep__hd .sp{flex:1}
.jbar{height:12px;display:flex;justify-content:center;border-radius:var(--r-full);background:var(--sunk);
  border:1px solid var(--line);overflow:hidden}
.jbar>i{display:block;height:100%;width:0;border-radius:var(--r-full);
  background:linear-gradient(90deg,var(--c1),var(--c3));transition:width .7s cubic-bezier(.2,.8,.3,1)}
.jstep--hot .jbar>i{background:linear-gradient(90deg,var(--c5),var(--warn))}
.jchips{display:flex;flex-wrap:wrap;gap:6px}
.jchip{display:inline-flex;align-items:center;gap:6px;max-width:100%;padding:5px 11px;border-radius:var(--r-full);
  border:1px solid var(--line-2);background:var(--card);color:var(--ink);font:inherit;font-size:12.5px;cursor:pointer;
  transition:transform var(--t-fast),border-color var(--t-fast),box-shadow var(--t-fast)}
.jchip:hover{transform:translateY(-1px);border-color:var(--brand);box-shadow:var(--lift-sm)}
.jchip:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.jchip__t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}
.jchip small{font-size:11px;color:var(--ink-3);white-space:nowrap}
.jchip__dot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--ok)}
.jchip--hot{background:var(--warn-weak);border-color:color-mix(in srgb,var(--warn) 50%,transparent);color:var(--warn)}
.jchip--hot small{color:var(--warn)}
.jchip--hot .jchip__dot{background:var(--c5)}
.jchip--money .jchip__dot{background:var(--bad);box-shadow:0 0 0 3px color-mix(in srgb,var(--bad) 22%,transparent)}
.jchip--off{opacity:.62;border-style:dashed}
.jchip--off .jchip__dot{background:var(--ink-icon)}
.jchip--more{color:var(--brand);border-style:dashed}
.jchip--demo{cursor:default;pointer-events:none;padding:3px 9px;font-size:11.5px}
.jlegend{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:0 var(--s5) var(--s4)}
.jrules{display:flex;flex-wrap:wrap;gap:6px}
.jalerts{display:flex;flex-direction:column}
.jalert{display:flex;align-items:flex-start;gap:12px;padding:var(--s3) var(--s5);border-bottom:1px solid var(--line);
  border-inline-start:3px solid var(--warn)}
.jalert:last-child{border-bottom:0}
.jalert--money,.jalert--hole{border-inline-start-color:var(--bad)}
.jalert__e{font-size:20px;line-height:1.3;flex:none}
.jalert__b{flex:1;min-width:0}
.jalert__b p{margin:5px 0 0;font-size:13px;line-height:1.85;color:var(--ink-2);overflow-wrap:anywhere}
.jalert__b p.jalert__todo{color:var(--ink);font-weight:500}
.jflags{display:flex;flex-direction:column}
.jflag{display:flex;align-items:center;gap:var(--s3);padding:var(--s3) var(--s5);border-bottom:1px solid var(--line)}
.jflag:last-child{border-bottom:0}
.jflag__b{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
.jpre{margin:0;padding:var(--s4);max-height:460px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;
  font:inherit;font-size:13px;line-height:1.9;background:var(--sunk);border:1px solid var(--line);border-radius:var(--r)}
@keyframes jin{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* 📂 the dossier */
.doshead__t{font-size:18px;font-weight:700;margin:0 0 6px;overflow-wrap:anywhere}
.doshead .kv{max-width:560px}
.bento--5{grid-template-columns:repeat(5,minmax(0,1fr))}
.dosgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4);align-items:start}
.dosgrid>.card{margin:0;min-width:0}
.dosstats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);border-bottom:1px solid var(--line)}
.dosstat{min-width:0;display:flex;flex-direction:column;gap:2px;padding:var(--s3) var(--s4);background:var(--card)}
.dosstat b{font-size:18px;font-variant-numeric:tabular-nums}
.dosstat span{font-size:12px;color:var(--ink-2)}
.dosstat small{font-size:11px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dosstat--ok b{color:var(--ok)}
.dosstat--warn b{color:var(--warn)}
.dosstat--bad b{color:var(--bad)}
.dstep{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;row-gap:10px}
.dstep__i{position:relative;flex:1 1 0;min-width:62px;display:flex;flex-direction:column;align-items:center;gap:5px;text-align:center}
.dstep__i::after{content:"";position:absolute;top:13px;inset-inline-start:calc(50% + 16px);width:calc(100% - 32px);height:2px;
  border-radius:2px;background:var(--line-2)}
.dstep__i:last-child::after{display:none}
.dstep__i.is-done::after{background:color-mix(in srgb,var(--ok) 70%,transparent)}
.dstep__d{position:relative;z-index:1;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;
  font-size:12px;font-weight:700;background:var(--sunk);color:var(--ink-3);border:1.5px solid var(--line-2)}
.dstep__d svg{width:14px;height:14px}
.dstep__i.is-done .dstep__d{background:var(--ok-weak);color:var(--ok);border-color:color-mix(in srgb,var(--ok) 55%,transparent)}
.dstep__i.is-here .dstep__d{border-color:var(--brand);box-shadow:0 0 0 4px color-mix(in srgb,var(--brand) 22%,transparent)}
.dstep__l{font-size:11.5px;color:var(--ink-2);line-height:1.4}
.dcheck{list-style:none;margin:0;padding:var(--s3) var(--s5);display:grid;gap:9px}
.dcheck li{display:flex;align-items:center;gap:8px;font-size:13px}
.dcheck svg{width:16px;height:16px;flex:none}
.dcheck .is-ok svg{color:var(--ok)}
.dcheck .is-miss svg{color:var(--bad)}
.dcheck .is-opt{color:var(--ink-3)}
.dcheck small{color:var(--ink-3)}
@media (max-width:900px){
  .dosgrid{grid-template-columns:minmax(0,1fr)}
  .bento--5{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:520px){
  .jpath{padding-inline:var(--s4)}
  .jalert,.jflag,.jlegend{padding-inline:var(--s4)}
  .jflag{flex-wrap:wrap}
  .jchip__t{max-width:140px}
  .dosstats{grid-template-columns:repeat(2,minmax(0,1fr))}
  .dstep__i{flex:0 0 25%;min-width:0}
  .dstep__i::after{display:none}
}
@media (prefers-reduced-motion:reduce){
  .jstep{animation:none}
  .jbar>i,.jchip,.jseg__b{transition:none}
}

/* ============================================================
   ROUND 3 (1405/07/03 evening) · the top-up sheet, the bank card,
   the live channel, must-read notices, the settings editor
   ============================================================ */
/* An already-open popup is redrawn WITHOUT its entrance (the flash per
   keystroke the owner reported), and a render caused by typing replays no
   list entrance either. */
.scrim.is-stay,.scrim.is-stay .sheet,.mr-scrim.is-stay,.mr-scrim.is-stay .sheet{animation:none}
.is-quiet .anim-rise,.is-quiet .anim-fade,.is-quiet .scrim,.is-quiet .sheet{animation:none}

/* the top-up amount: a big LTR number with its unit, then ready amounts */
.input.input--amt input{font-size:20px;font-weight:700;letter-spacing:.01em;text-align:left;
  font-variant-numeric:tabular-nums}
.input__unit{flex:none;font-size:12.5px;color:var(--ink-3)}
.amtchips{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.amtchip{min-height:44px;padding:8px 14px;border-radius:var(--r-full);border:1px solid var(--line-2);
  background:var(--card);color:var(--ink);font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;
  transition:background var(--t-fast),border-color var(--t-fast),transform var(--t-fast)}
.amtchip:hover{background:var(--hover);border-color:var(--line-3)}
.amtchip:active{transform:scale(.97)}
.amtchip[aria-pressed="true"]{background:var(--brand-weak);border-color:var(--brand);color:var(--brand)}
.amtchip:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
@media (max-width:420px){.amtchips{display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}.amtchip{padding-inline:6px}}

/* the amount on its own (no saved card) */
.payamt__row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.payamt__rial{font-size:26px;font-weight:800;letter-spacing:-.01em;font-variant-numeric:tabular-nums;line-height:1.2}
.payamt__toman{font-size:13px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.depchip{display:inline-flex;flex:none}

/* 💳 the bank card. Fixed colours on purpose (a card is a card in both
   themes): white on a deep blue-violet, every text pair >= 7:1. */
.bcard{--bc-a:#10204a;--bc-b:#2f5fd9;--bc-c:#5b2bb5;--bc-ink:#fff;--bc-ink2:rgba(255,255,255,.78);
  position:relative;isolation:isolate;overflow:hidden;display:flex;flex-direction:column;gap:12px;
  width:100%;max-width:440px;margin-inline:auto;padding:18px 18px 16px;border-radius:18px;color:var(--bc-ink);
  background:linear-gradient(135deg,var(--bc-a) 0%,var(--bc-b) 62%,var(--bc-c) 120%);
  box-shadow:0 1px 0 rgba(255,255,255,.18) inset,0 18px 36px -18px rgba(16,32,74,.75),0 2px 6px rgba(16,32,74,.25)}
.bcard::before{content:"";position:absolute;z-index:-1;inset:-40% -20% auto auto;width:70%;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(255,255,255,.22),rgba(255,255,255,0) 65%);pointer-events:none}
.bcard__top{display:flex;align-items:center;justify-content:space-between;gap:10px}
.bcard__bank{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--bc-ink2)}
.bcard__bank svg{width:16px;height:16px}
.bcard__chip{width:40px;height:30px;border-radius:7px;flex:none;
  background:linear-gradient(135deg,#f6d77c,#c99a2e 55%,#f3dc92);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.18),inset 0 9px 0 -8px rgba(0,0,0,.25),inset 0 -9px 0 -8px rgba(0,0,0,.25)}
.bcard__no{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;min-height:48px;
  padding:6px 10px;margin-inline:-10px;width:calc(100% + 20px);border-radius:10px;color:inherit;
  font-family:var(--mono);font-size:21px;font-weight:700;letter-spacing:.04em;direction:ltr;
  font-variant-numeric:tabular-nums;transition:background var(--t-fast)}
.bcard__no>span{flex:none}
.bcard__no:hover{background:rgba(255,255,255,.1)}
.bcard__no:active{background:rgba(255,255,255,.16)}
.bcard__cp{display:grid;place-items:center;margin-inline-start:auto;opacity:.85}
.bcard__cp svg{width:18px;height:18px}
.bcard__who{display:flex;align-items:center;gap:8px;min-width:0}
.bcard__lbl{font-size:12px;color:var(--bc-ink2);flex:none}
.bcard__holder{font-size:16px;font-weight:700;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bcard__mini{width:44px;height:44px;margin-inline-start:auto;flex:none;display:grid;place-items:center;border-radius:10px;color:inherit}
.bcard__mini:hover{background:rgba(255,255,255,.12)}
.bcard__mini svg{width:16px;height:16px}
.bcard__amt{display:flex;flex-direction:column;gap:4px;padding-top:12px;border-top:1px dashed rgba(255,255,255,.35)}
.bcard__sum{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.bcard__rial{font-size:27px;font-weight:800;line-height:1.15;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.bcard__rial small{font-size:13px;font-weight:600;margin-inline-start:6px;color:var(--bc-ink2)}
.bcard__copy{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:8px 14px;margin-inline-start:auto;
  border-radius:var(--r-full);background:#fff;color:#10204a;font-size:13px;font-weight:700;
  box-shadow:0 2px 8px -2px rgba(0,0,0,.35);transition:transform var(--t-fast)}
.bcard__copy:active{transform:scale(.97)}
.bcard__copy svg{width:15px;height:15px}
.bcard__toman{font-size:13px;color:var(--bc-ink2);font-variant-numeric:tabular-nums}
.bcard__foot{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--bc-ink2)}
.bcard__foot svg{width:14px;height:14px}
.bcard :focus-visible{outline:2px solid #fff;outline-offset:2px;border-radius:10px}
.bcard--preview{max-width:400px;margin-inline:0}
@media (max-width:400px){
  .bcard{padding:16px 14px 14px;gap:10px;border-radius:16px}
  .bcard__no{font-size:17px;letter-spacing:.02em}
  .bcard__rial{font-size:22px}
  .bcard__copy{margin-inline-start:0}
}

/* ⚠️ a must-read notice: above every popup, below the toast */
.mr-scrim{position:fixed;inset:0;z-index:110;display:flex;align-items:center;justify-content:center;
  padding:var(--s6) var(--s5);background:rgba(4,6,10,.72);
  backdrop-filter:saturate(140%) blur(8px);-webkit-backdrop-filter:saturate(140%) blur(8px);
  animation:fade var(--t) both}
.mr-scrim .sheet{animation:popIn 240ms cubic-bezier(.2,.9,.3,1) both}
.mr__body{font-size:14.5px;line-height:1.9;white-space:normal;overflow-wrap:anywhere}
@media (max-width:860px){
  .mr-scrim{align-items:flex-end;padding:0}
  .mr-scrim .sheet{width:100%;max-height:88dvh;border-radius:var(--r-xl) var(--r-xl) 0 0}
}
html:has(.mr-scrim),body:has(.mr-scrim){overflow:hidden}

/* ⚙️ the settings editor */
.stgrp{background:var(--sunk);padding-block:8px}
.stgrp b{font-size:12.5px;color:var(--ink-2)}
.tbl tr.is-bad .input{border-color:var(--bad);box-shadow:0 0 0 3px color-mix(in srgb,var(--bad) 16%,transparent)}

/* ============================================================
   🎨 SKINS (round 3) · ported from the owner's artifact «پوسته‌های دخل»
   (claude.ai artifact GXPyQBQYWh48xNuUdocams, m/receipt/family.css and
   m/neo-brutal/family.css): same palettes, fonts, keys, borders, shadows
   and motion, mapped onto the panel's own components. Per account
   (html[data-skin]); both skins are light-only in the artifact, so app.js
   pins data-theme="light" while one is on. Fonts are self-hosted
   (font-src 'self'): Estedad (OFL), Handjet (OFL, variable ELGR/ELSH/wght),
   Lalezar (OFL), and the artifact's two one-glyph decimal fonts. A font is
   only downloaded when a skin actually uses it.
   ============================================================ */
@font-face{font-family:Estedad;src:url("/assets/fonts/Estedad.woff2") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap}
@font-face{font-family:Handjet;src:url("/assets/fonts/Handjet-arabic.woff2") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap;
  unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC}
@font-face{font-family:Handjet;src:url("/assets/fonts/Handjet-latin.woff2") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Lalezar;src:url("/assets/fonts/Lalezar-arabic.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
  unicode-range:U+0600-06FF,U+0750-077F,U+0870-088E,U+0890-0891,U+0897-08E1,U+08E3-08FF,U+200C-200E,U+2010-2011,U+204F,U+2E41,U+FB50-FDFF,U+FE70-FE74,U+FE76-FEFC}
@font-face{font-family:Lalezar;src:url("/assets/fonts/Lalezar-latin.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
/* the receipt family's tall dot-matrix decimal «٫» (so ۰٫۵ never reads ۰٬۵) */
@font-face{font-family:SkDec;src:url("/assets/fonts/SkDec.otf") format("opentype");unicode-range:U+066B;font-weight:100 900;font-display:block}
@font-face{font-family:SkDecPx;src:url("/assets/fonts/SkDecPx.otf") format("opentype");unicode-range:U+066B;font-weight:100 900;font-display:block}

/* ============================================================
   رسید حرارتی (receipt) — a nut-shop counter in stainless steel: thermal
   paper with torn teeth, die-cut labels, keys with a lip, a violet rubber
   stamp, a yellow highlighter. Two inks (black, red). Light only.
   ============================================================ */
:root[data-skin="receipt"]{
  color-scheme:light;
  --bg:#D4D8D6;--panel:#FBFBF8;--card:#FBFBF8;--sunk:#F2F2ED;--hover:#E6E6DE;
  --line:#DCDCD3;--line-2:#C9CBC3;--line-3:#858A86;
  --ink:#1B1D1E;--ink-2:#4D5250;--ink-3:#676C69;--ink-4:#676C69;--ink-icon:#676C69;
  --brand:#1B1D1E;--brand-solid:#23272A;--brand-weak:#FBF4A6;--on-brand:#F7F7F2;
  --ok:#3A3FA5;--ok-weak:#E6E7F6;--ok-ink:#3A3FA5;--warn:#5E5130;--warn-weak:#FBF4A6;--bad:#C21D38;--bad-weak:#FAE3E6;
  --c1:#1B1D1E;--c2:#C21D38;--c3:#3A3FA5;--c0:#858A86;--c4:#3A3FA5;--c5:#8A5D00;--vip-weak:#E6E7F6;
  --glass:#FBFBF8;--glass-strong:#FBFBF8;--tabglass:#25282A;--tabrim:transparent;--tablift:none;
  --rim:rgba(27,29,30,.10);--rim-top:transparent;
  --shadow-sm:none;--shadow-md:none;--shadow-lg:none;--lift-sm:none;--lift:none;--lift-lg:none;
  --r-sm:7px;--r:7px;--r-lg:0px;--r-xl:0px;--tab-ink:#A8AEAA;
  --sk-font:Estedad,Tahoma,sans-serif;
  --sk-dotface:SkDec,Handjet,Estedad,Tahoma,sans-serif;
  --sk-pixface:SkDecPx,Handjet,Estedad,Tahoma,sans-serif;
  --sk-sh-paper:drop-shadow(0 1px 0 rgba(31,36,34,.10)) drop-shadow(0 7px 9px rgba(31,36,34,.13));
  --sk-sh-lift:drop-shadow(0 2px 1px rgba(31,36,34,.10)) drop-shadow(0 18px 18px rgba(31,36,34,.22));
  --sk-sh-float:drop-shadow(0 2px 2px rgba(20,24,22,.12)) drop-shadow(0 26px 28px rgba(20,24,22,.30));
  --sk-sh-label:0 0 0 .5px rgba(27,29,30,.10),0 1px 1.5px rgba(27,29,30,.16),0 3px 6px -3px rgba(27,29,30,.16);
  --sk-sh-label-lift:0 0 0 .5px rgba(27,29,30,.10),0 8px 14px -6px rgba(27,29,30,.30),0 18px 24px -14px rgba(27,29,30,.30);
  --sk-counter-tex:
    radial-gradient(130% 80% at 80% -20%,rgba(255,255,255,.55),rgba(255,255,255,0) 58%),
    radial-gradient(120% 90% at 0% 110%,rgba(150,158,154,.30),rgba(150,158,154,0) 60%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='360' height='360'><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='.0035 .85' numOctaves='2' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 .55 -.18'/></filter><rect width='100%' height='100%' filter='url(%23b)'/></svg>"),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' seed='9' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .18  0 0 0 0 .2  0 0 0 0 .19  0 0 0 .09 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  --sk-ink-grain:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='2' seed='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 -8.5 6.1'/></filter><rect width='100%' height='100%' filter='url(%23g)'/></svg>");
  --sk-ease-out:cubic-bezier(.2,.8,.2,1);--sk-ease-in:cubic-bezier(.55,0,.8,.2);
  --sk-spring:linear(0,.081 3.3%,.263 6.7%,.48 10%,.687 13.3%,.856 16.7%,.978 20%,1.055 23.3%,1.093 26.7%,1.102 30%,1.092 33.3%,1.073 36.7%,1.051 40%,1.03 43.3%,1.013 46.7%,1.001 50%,.994 53.3%,.99 58%,.993 66.7%,.997 73.3%,1 80%,1);
  --sk-spring-soft:linear(0,.105 4.5%,.303 9.1%,.499 13.6%,.662 18.2%,.783 22.7%,.866 27.3%,.921 31.8%,.956 36.4%,.976 40.9%,.988 45.5%,.995 50%,.998 54.5%,1 59.1%,1);
  --sk-ease-feed:linear(0,.267 7.1%,.267 14.3%,.475 21.4%,.475 28.6%,.637 35.7%,.637 42.9%,.764 50%,.764 57.1%,.863 64.3%,.863 71.4%,.94 78.6%,.94 85.7%,1);
}
:root[data-skin="receipt"] body{font-family:var(--sk-font);font-weight:500;color:#2F3634;
  background-color:#D4D8D6;background-image:var(--sk-counter-tex);background-size:auto,auto,360px 360px,200px 200px;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
:root[data-skin="receipt"] ::selection{background:#F6EA4B;color:#1B1D1E}
:root[data-skin="receipt"] :focus-visible{outline:2px solid #1B1D1E;outline-offset:2px}
:root[data-skin="receipt"] .side :focus-visible,:root[data-skin="receipt"] .tabs :focus-visible{outline-color:#F6EA4B}
:root[data-skin="receipt"] .app{border:0;background:transparent;border-radius:0;overflow:visible}
:root[data-skin="receipt"] .main{background:transparent}
/* the rail = the printer's plastic body */
:root[data-skin="receipt"] .side{background:linear-gradient(270deg,rgba(255,255,255,.05) 0,rgba(255,255,255,0) 3px),
  linear-gradient(90deg,#17191B 0,#1F2224 2px,#2A2E31 40%,#25282A 100%);
  backdrop-filter:none;-webkit-backdrop-filter:none;border:0;color:#A8AEAA;
  box-shadow:inset 2px 0 0 #0C0D0E,6px 0 18px -10px rgba(0,0,0,.4)}
:root[data-skin="receipt"] .brandline b{color:#EEEFEB;font-weight:800}
:root[data-skin="receipt"] .brandline span{color:#A8AEAA}
:root[data-skin="receipt"] .brandmark{background:linear-gradient(180deg,#FFFFFF,#F1F1EC);color:#1B1D1E;border-radius:5px;
  box-shadow:0 0 0 1px rgba(0,0,0,.25),0 2px 3px rgba(0,0,0,.35)}
:root[data-skin="receipt"] .navlabel{color:#A8AEAA}
:root[data-skin="receipt"] .navitem{position:relative;isolation:isolate;color:#A8AEAA;font-weight:600;border-radius:9px;
  transition:color 180ms,background-color 180ms}
:root[data-skin="receipt"] .navitem svg{color:currentColor}
:root[data-skin="receipt"] .navitem:hover{color:#EEEFEB;background:rgba(255,255,255,.055)}
:root[data-skin="receipt"] .navitem:active{transform:translateY(1px)}
:root[data-skin="receipt"] .navitem[aria-current="page"]{color:#1B1D1E;background:none;font-weight:800}
:root[data-skin="receipt"] .navitem[aria-current="page"] svg{color:#1B1D1E}
/* the current item: a paper ticket fed out of the rail's slot, torn end on the left */
:root[data-skin="receipt"] .navitem[aria-current="page"]::before{content:"";position:absolute;z-index:-1;
  inset-block:3px;inset-inline-start:2px;inset-inline-end:-26px;border-left:6px solid transparent;
  background:conic-gradient(from 45deg at 0 50%,#FBFBF8 90deg,#0000 0) 0 50%/6px 11px repeat-y border-box,
    linear-gradient(#FBFBF8 0 0) padding-box;
  border-radius:3px 0 0 3px;filter:drop-shadow(0 1px 0 rgba(0,0,0,.25)) drop-shadow(0 4px 6px rgba(0,0,0,.28))}
:root[data-skin="receipt"] .nav-fresh .navitem[aria-current="page"]::before{animation:rc-ticket 620ms var(--sk-ease-feed) 120ms backwards}
:root[data-skin="receipt"] .side__foot{border-top:1px dashed rgba(255,255,255,.18)}
:root[data-skin="receipt"] .topbar{background:rgba(212,216,214,.94);backdrop-filter:none;-webkit-backdrop-filter:none;
  border-bottom:0;box-shadow:0 1px 0 rgba(255,255,255,.55),0 2px 0 rgba(47,54,52,.08)}
:root[data-skin="receipt"] .topbar h1{font-weight:800;font-size:19px;color:#1B1D1E;letter-spacing:0}
:root[data-skin="receipt"] .sect__hd h2{font-weight:800;color:#1B1D1E}
/* PAPER: flat thermal paper with torn teeth at the bottom; the shadow follows the teeth */
:root[data-skin="receipt"] .card,:root[data-skin="receipt"] .tile,:root[data-skin="receipt"] .hero{
  --pc:#FBFBF8;color:#1B1D1E;border:0 solid transparent;border-bottom-width:6px;border-radius:0;box-shadow:none;
  background:conic-gradient(from -45deg at 50% 100%,var(--pc) 90deg,#0000 0) 50% 100%/12px 6px repeat-x border-box,
    linear-gradient(var(--pc) 0 0) padding-box;
  filter:var(--sk-sh-paper)}
:root[data-skin="receipt"] .card.card--sunk{--pc:#F2F2ED}
:root[data-skin="receipt"] .tile:hover{transform:none;filter:var(--sk-sh-lift)}
:root[data-skin="receipt"] .hero::after{display:none}
:root[data-skin="receipt"] .card__hd{border-bottom:0;
  background:repeating-linear-gradient(to left,#4D5250 0 4px,#0000 4px 7px) bottom/100% 1px no-repeat}
:root[data-skin="receipt"] .card__hd h2{font-weight:800;font-size:15.5px;color:#1B1D1E}
:root[data-skin="receipt"] .card__hd>svg{color:#4D5250}
/* machine figures ≥ 20 px in Handjet dot-print; one marker swipe on the focal number */
:root[data-skin="receipt"] .tile__v,:root[data-skin="receipt"] .hero__v,:root[data-skin="receipt"] .bcard__rial,
:root[data-skin="receipt"] .payamt__rial{font-family:var(--sk-dotface);font-variation-settings:'ELSH' 12,'ELGR' 1;
  font-weight:700;letter-spacing:.01em;font-variant-numeric:tabular-nums}
:root[data-skin="receipt"] .tile__v{font-size:34px;line-height:1}
:root[data-skin="receipt"] .tile__v small,:root[data-skin="receipt"] .hero__v small{font-family:var(--sk-font);font-variation-settings:normal;font-weight:600}
:root[data-skin="receipt"] .hero__v{font-size:52px;line-height:.95;position:relative;isolation:isolate;
  width:max-content;max-width:100%;padding-inline:.16em}
:root[data-skin="receipt"] .hero__v::before{content:"";position:absolute;z-index:-1;inset:.2em 0 .04em -.02em;background:#F6EA4B;
  border-radius:.3em .12em .36em .1em/.18em .42em .14em .46em;transform:rotate(-1.1deg) skewX(-6deg);transform-origin:100% 50%}
:root[data-skin="receipt"] .nav-fresh .hero__v::before{animation:rc-marker 560ms var(--sk-ease-out) .75s backwards}
/* KEYS: what you press has a lip; press = the key goes down into it */
:root[data-skin="receipt"] .btn{--face:#F1F1EC;--face-top:#FFFFFF;--lip:#B9BCB4;--edge:rgba(27,29,30,.16);--fg:#1B1D1E;--lipw:3px;
  border:0;border-radius:7px;color:var(--fg);font-weight:700;margin-bottom:var(--lipw);
  background:linear-gradient(180deg,var(--face-top),var(--face) 58%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 0 0 1px var(--edge),0 var(--lipw) 0 var(--lip),0 calc(var(--lipw) + 2px) 5px -1px rgba(20,24,22,.30);
  transform:translateY(0);transition:transform 90ms var(--sk-ease-out),box-shadow 90ms var(--sk-ease-out),filter 180ms}
:root[data-skin="receipt"] .btn:hover:not(:disabled){background:linear-gradient(180deg,var(--face-top),var(--face) 58%);
  border-color:transparent;filter:brightness(1.035);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 0 0 1px var(--edge),0 var(--lipw) 0 var(--lip),0 calc(var(--lipw) + 2px) 5px -1px rgba(20,24,22,.30)}
:root[data-skin="receipt"] .btn:active:not(:disabled){transform:translateY(var(--lipw));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 0 0 1px var(--edge),0 0 0 var(--lip),0 1px 2px rgba(20,24,22,.28)}
:root[data-skin="receipt"] .btn--pri{--face:#23272A;--face-top:#3A3F43;--lip:#0A0B0C;--edge:rgba(0,0,0,.55);--fg:#F7F7F2}
:root[data-skin="receipt"] .btn--pri:hover:not(:disabled){filter:brightness(1.12)}
:root[data-skin="receipt"] .btn--danger{--face:#B81A34;--face-top:#D4344F;--lip:#6E0C1D;--edge:rgba(90,0,14,.5);--fg:#FFFFFF}
:root[data-skin="receipt"] .btn--ghost,:root[data-skin="receipt"] .btn--ghost:hover:not(:disabled){--lipw:0px;margin-bottom:0;background:transparent;box-shadow:none;color:#1B1D1E;filter:none}
:root[data-skin="receipt"] .btn--ghost:hover:not(:disabled){background:rgba(27,29,30,.06)}
:root[data-skin="receipt"] .btn--ghost:active:not(:disabled){transform:scale(.97);background:rgba(27,29,30,.11);box-shadow:none}
:root[data-skin="receipt"] .topbar .btn--ghost{color:#2F3634}
:root[data-skin="receipt"] .btn--sm{--lipw:2px;border-radius:6px}
:root[data-skin="receipt"] .btn[disabled]{opacity:.45}
/* INK marks: printed tags; success = violet stamp ink, attention = the marker */
:root[data-skin="receipt"] .pill{border:0;border-radius:3px;background:transparent;color:#1B1D1E;font-weight:700;
  box-shadow:inset 0 0 0 1.25px currentColor}
:root[data-skin="receipt"] .pill--ok{color:#3A3FA5}
:root[data-skin="receipt"] .pill--vip{color:#3A3FA5;background:transparent}
:root[data-skin="receipt"] .pill--bad{background:#C21D38;color:#FFFFFF;box-shadow:none}
:root[data-skin="receipt"] .pill--warn{background:#F6EA4B;color:#1B1D1E;box-shadow:none}
:root[data-skin="receipt"] .pill--brand{background:#1B1D1E;color:#FBFBF8;box-shadow:none}
:root[data-skin="receipt"] .pill--mute{background:#E6E6DE;color:#4D5250;box-shadow:none}
:root[data-skin="receipt"] .pill--out{color:#4D5250;box-shadow:inset 0 0 0 1px #DCDCD3}
:root[data-skin="receipt"] .tag,:root[data-skin="receipt"] .locchip,:root[data-skin="receipt"] .coefb{border-radius:3px}
/* the scan field */
:root[data-skin="receipt"] .input{background:#FFFFFF;border:0;border-radius:7px;
  box-shadow:inset 0 0 0 1.5px #858A86,inset 0 2px 3px rgba(27,29,30,.08),0 1px 0 rgba(255,255,255,.6);transition:box-shadow 180ms}
:root[data-skin="receipt"] .input:focus-within{border:0;box-shadow:inset 0 0 0 2px #1B1D1E,0 0 0 3px rgba(246,234,75,.9)}
:root[data-skin="receipt"] .input input::placeholder,:root[data-skin="receipt"] .input textarea::placeholder{color:#676C69}
:root[data-skin="receipt"] .field>label{color:#4D5250;font-weight:700}
/* alerts by severity: an ink bar on the start edge */
:root[data-skin="receipt"] .note,:root[data-skin="receipt"] .callout{border:0;border-radius:0;background:#F2F2ED;color:#1B1D1E;
  border-inline-start:3px solid #858A86}
:root[data-skin="receipt"] .note--warn,:root[data-skin="receipt"] .callout--warn{background:#FBF4A6;border-inline-start-color:#F6EA4B;color:#1B1D1E}
:root[data-skin="receipt"] .note--bad,:root[data-skin="receipt"] .callout--bad{background:#FAE3E6;border-inline-start-color:#C21D38;color:#8E1428}
:root[data-skin="receipt"] .note--ok,:root[data-skin="receipt"] .callout--ok{background:#E6E7F6;border-inline-start-color:#3A3FA5;color:#2B2F82}
:root[data-skin="receipt"] .note--brand{background:#F2F2ED;border-inline-start-color:#1B1D1E;color:#1B1D1E}
/* printed rules instead of lines */
:root[data-skin="receipt"] .tbl th{background:transparent;color:#4D5250;font-weight:700;letter-spacing:0;border-bottom:1.25px solid #1B1D1E}
:root[data-skin="receipt"] .tbl td{border-bottom:1px dashed #DCDCD3}
:root[data-skin="receipt"] .tbl tbody tr:hover{background:#F2F2ED}
:root[data-skin="receipt"] .li,:root[data-skin="receipt"] .rowcard,:root[data-skin="receipt"] .ledg__r,
:root[data-skin="receipt"] .credrow,:root[data-skin="receipt"] .li--btn{border-bottom:1px dashed #DCDCD3}
:root[data-skin="receipt"] .list.list--boxed{border:1px dashed #C9CBC3;border-radius:0}
:root[data-skin="receipt"] .hr,:root[data-skin="receipt"] .hr-flex{background:repeating-linear-gradient(to left,#4D5250 0 4px,#0000 4px 7px)}
/* LABELS: die-cut label stock; hover peels it up a little */
:root[data-skin="receipt"] .choice,:root[data-skin="receipt"] .locrow,:root[data-skin="receipt"] .rung,:root[data-skin="receipt"] .skinopt{
  background:#FFFFFF;border:0;border-radius:7px;box-shadow:var(--sk-sh-label);
  transition:transform 260ms var(--sk-spring),box-shadow 220ms var(--sk-ease-out)}
:root[data-skin="receipt"] .choice:hover:not([disabled]),:root[data-skin="receipt"] .locrow:hover:not([disabled]):not(.locrow--ro),
:root[data-skin="receipt"] .rung:hover,:root[data-skin="receipt"] .skinopt:hover{background:#FFFFFF;transform:translateY(-2px) rotate(-.35deg);box-shadow:var(--sk-sh-label-lift)}
:root[data-skin="receipt"] .choice[aria-pressed="true"],:root[data-skin="receipt"] .locrow[aria-pressed="true"],
:root[data-skin="receipt"] .skinopt[aria-checked="true"]{background:#FBF4A6;box-shadow:inset 0 0 0 2px #1B1D1E,var(--sk-sh-label)}
:root[data-skin="receipt"] .choice--lock{background:#F2F2ED;box-shadow:0 0 0 1px rgba(27,29,30,.08)}
:root[data-skin="receipt"] .locrow[aria-pressed="true"] .locrow__box{background:#1B1D1E;border-color:#1B1D1E}
:root[data-skin="receipt"] .rung__gb{background:#1B1D1E;color:#FBFBF8;border:0;border-radius:7px 0 6px 0}
:root[data-skin="receipt"] .rung__gb b{font-family:var(--sk-pixface);font-variation-settings:'ELSH' 2,'ELGR' 1;font-size:24px}
:root[data-skin="receipt"] .rung__gb small{color:#C9CCC6}
:root[data-skin="receipt"] .takeaway__bx,:root[data-skin="receipt"] .linkbox{background:#FFFFFF;border:0;border-radius:7px;box-shadow:inset 0 0 0 1.5px #858A86}
:root[data-skin="receipt"] .svc{border-radius:7px}
/* chips = selections printed in reverse */
:root[data-skin="receipt"] .amtchip{background:#FBFBF8;color:#4D5250;border:0;border-radius:5px;font-weight:700;
  box-shadow:inset 0 0 0 1.25px #858A86;transition:background-color 180ms,color 180ms,transform 90ms}
:root[data-skin="receipt"] .amtchip:hover{background:#FFFFFF;color:#1B1D1E}
:root[data-skin="receipt"] .amtchip:active{transform:scale(.96)}
:root[data-skin="receipt"] .amtchip[aria-pressed="true"]{background:#1B1D1E;color:#FBFBF8;box-shadow:none}
/* meters print a hatch that grows from the right, with a red head */
:root[data-skin="receipt"] .meter{height:10px;border:0;border-radius:2px;background:#E6E6DE;box-shadow:inset 0 0 0 1px rgba(27,29,30,.08)}
:root[data-skin="receipt"] .meter>i{position:relative;border-radius:0;background:repeating-linear-gradient(to left,#1B1D1E 0 3px,#0000 3px 4.5px)}
:root[data-skin="receipt"] .meter>i::after{content:"";position:absolute;left:-2px;top:0;bottom:0;width:4px;background:#C21D38}
:root[data-skin="receipt"] .meter[data-tone="bad"]>i{background:repeating-linear-gradient(to left,#C21D38 0 3px,#0000 3px 4.5px)}
:root[data-skin="receipt"] .bars i{border-radius:0;background:radial-gradient(circle,#1B1D1E 1.1px,#0000 1.3px) 0 0/3px 3px;
  transform-origin:50% 100%;animation:rc-bar 1100ms var(--sk-spring-soft) backwards}
:root[data-skin="receipt"] .bars>div:hover{background:rgba(246,234,75,.45)}
:root[data-skin="receipt"] .compo{border-radius:2px}
/* floating layers: a sheet feeds out of the slot, a dialog lands on a spring */
:root[data-skin="receipt"] .scrim,:root[data-skin="receipt"] .mr-scrim{background:rgba(34,39,37,.40);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);animation:rc-fade 240ms var(--sk-ease-out) backwards}
:root[data-skin="receipt"] .sheet{--pc:#FBFBF8;border:0 solid transparent;border-top-width:6px;border-bottom-width:6px;border-radius:0;
  background:conic-gradient(from 135deg at 50% 0,var(--pc) 90deg,#0000 0) 50% 0/12px 6px repeat-x border-box,
    conic-gradient(from -45deg at 50% 100%,var(--pc) 90deg,#0000 0) 50% 100%/12px 6px repeat-x border-box,
    linear-gradient(var(--pc) 0 0) padding-box;
  box-shadow:none;filter:var(--sk-sh-float);backdrop-filter:none;-webkit-backdrop-filter:none;
  animation:rc-dialog-in 620ms var(--sk-spring) backwards}
:root[data-skin="receipt"] .sheet__hd,:root[data-skin="receipt"] .sheet__ft{background:#FBFBF8}
:root[data-skin="receipt"] .sheet__hd{border-bottom:0;background:repeating-linear-gradient(to left,#676C69 0 3px,#0000 3px 6px) bottom/100% 1px no-repeat,#FBFBF8}
:root[data-skin="receipt"] .sheet__hd h2{font-weight:800}
:root[data-skin="receipt"] .sheet__ft{border-top:1px dashed #C9CBC3}
:root[data-skin="receipt"] .dlgmark{background:transparent;border:2.5px solid currentColor;transform:rotate(-8deg);
  animation:rc-stamp 560ms var(--sk-ease-out) backwards}
:root[data-skin="receipt"] .dlgmark--ok{color:#3A3FA5}
:root[data-skin="receipt"] .dlgmark--warn{color:#1B1D1E;background:#F6EA4B;border-color:#1B1D1E}
:root[data-skin="receipt"] .dlgmark--bad{color:#C21D38}
:root[data-skin="receipt"] .toast{--pc:#FBFBF8;color:#1B1D1E;border:0 solid transparent;border-bottom-width:5px;border-radius:0;box-shadow:none;
  background:conic-gradient(from -45deg at 50% 100%,var(--pc) 90deg,#0000 0) 50% 100%/10px 5px repeat-x border-box,linear-gradient(var(--pc) 0 0) padding-box;
  filter:var(--sk-sh-float);font-weight:600;animation:rc-feed 760ms var(--sk-ease-feed) backwards}
:root[data-skin="receipt"] .skel{background:#F2F2ED;border-color:#DCDCD3}
:root[data-skin="receipt"] .spin{border-color:#DCDCD3;border-top-color:#1B1D1E}
:root[data-skin="receipt"] .qrbox{border:0;box-shadow:var(--sk-sh-label)}
:root[data-skin="receipt"] .stgrp{background:#F2F2ED}
/* list entrance: each row prints top to bottom and develops */
:root[data-skin="receipt"] .anim-rise{animation:rc-print 420ms steps(7,end) backwards,rc-develop 800ms var(--sk-ease-out) backwards;
  animation-delay:calc(var(--i,0) * 70ms)}
/* 💳 the card = heavy member cardstock with a gold foil band */
:root[data-skin="receipt"] .bcard{--bc-ink:#1B1D1E;--bc-ink2:#4D5250;color:#1B1D1E;background:#FFFFFF;border-radius:14px;
  box-shadow:0 0 0 1px rgba(27,29,30,.08),0 2px 3px rgba(27,29,30,.12),0 22px 30px -18px rgba(20,24,22,.45)}
:root[data-skin="receipt"] .bcard::before{inset:0 0 auto 0;width:auto;height:58px;aspect-ratio:auto;border-radius:0;
  background:conic-gradient(from -45deg at 50% 100%,#FFFFFF 90deg,#0000 0) 50% 100%/12px 6px repeat-x,
    linear-gradient(118deg,#FFF1B8 0%,#E3BE56 30%,#FFF6D2 48%,#C9A23A 72%,#F2D77F 100%);
  background-size:12px 6px,220% 100%;animation:rc-sheen 1.3s var(--sk-ease-out) .9s backwards}
:root[data-skin="receipt"] .bcard__bank{color:#3A2A00;font-weight:800}
:root[data-skin="receipt"] .bcard__chip{background:linear-gradient(180deg,#3B4044,#1D2022);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}
:root[data-skin="receipt"] .bcard__no{margin-top:8px}
:root[data-skin="receipt"] .bcard__no:hover,:root[data-skin="receipt"] .bcard__mini:hover{background:rgba(27,29,30,.06)}
:root[data-skin="receipt"] .bcard__amt{border-top:0;background:repeating-linear-gradient(to left,#4D5250 0 4px,#0000 4px 7px) top/100% 1px no-repeat}
:root[data-skin="receipt"] .bcard__rial{font-size:38px;line-height:.95}
:root[data-skin="receipt"] .bcard__rial small{font-family:var(--sk-font);font-variation-settings:normal}
:root[data-skin="receipt"] .bcard__copy{--lipw:3px;border-radius:7px;color:#F7F7F2;background:linear-gradient(180deg,#3A3F43,#23272A 58%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 0 0 1px rgba(0,0,0,.55),0 3px 0 #0A0B0C,0 5px 5px -1px rgba(20,24,22,.30);margin-bottom:3px;
  transition:transform 90ms var(--sk-ease-out),box-shadow 90ms var(--sk-ease-out)}
:root[data-skin="receipt"] .bcard__copy:active{transform:translateY(3px);box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 0 0 1px rgba(0,0,0,.55),0 0 0 #0A0B0C}
:root[data-skin="receipt"] .bcard :focus-visible{outline-color:#1B1D1E}
/* 📱 the bottom bar = the plastic rail; the current slot is a paper ticket fed up out of it */
@media (max-width:860px){
  :root[data-skin="receipt"] .tabs{background:linear-gradient(180deg,#17191B 0,#2A2E31 3px,#25282A 100%);
    box-shadow:inset 0 2px 0 #0C0D0E,0 -6px 18px -10px rgba(0,0,0,.45);border:0}
  :root[data-skin="receipt"] .tab{color:#A8AEAA;position:relative;isolation:isolate}
  :root[data-skin="receipt"] .tab[aria-current="page"]{color:#1B1D1E;font-weight:800}
  :root[data-skin="receipt"] .tab[aria-current="page"] .tab__ic{background:none}
  :root[data-skin="receipt"] .tab[aria-current="page"]::before{content:"";position:absolute;z-index:-1;inset-inline:2px;
    inset-block-start:-12px;inset-block-end:2px;border-top:6px solid transparent;
    background:conic-gradient(from 135deg at 50% 0,#FBFBF8 90deg,#0000 0) 50% 0/11px 6px repeat-x border-box,
      linear-gradient(#FBFBF8 0 0) padding-box;border-radius:0 0 3px 3px;
    filter:drop-shadow(0 1px 0 rgba(0,0,0,.25)) drop-shadow(0 4px 6px rgba(0,0,0,.28));
    --rc-tk-from:translateY(16px);--rc-tk-clip:inset(100% 0 0 0)}
  :root[data-skin="receipt"] .nav-fresh .tab[aria-current="page"]::before{animation:rc-ticket 620ms var(--sk-ease-feed) 120ms backwards}
  :root[data-skin="receipt"] .tab--new .tab__ic{background:linear-gradient(180deg,#FFFFFF,#F1F1EC 58%);color:#1B1D1E;
    box-shadow:0 0 0 1px rgba(27,29,30,.16),0 2px 0 #B9BCB4}
  :root[data-skin="receipt"] .tab__badge{background:#C21D38;box-shadow:0 0 0 2px #25282A}
}
@keyframes rc-feed{from{transform:translateY(-100%);clip-path:inset(100% -40px -60px -40px)}to{transform:translateY(0);clip-path:inset(0 -40px -60px -40px)}}
@keyframes rc-print{from{clip-path:inset(0 0 100% 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes rc-develop{from{opacity:.35}}
@keyframes rc-fade{from{opacity:0}}
@keyframes rc-stamp{0%{opacity:0;transform:translateY(-10px) scale(1.9) rotate(-18deg);filter:blur(2px)}
  55%{opacity:.95;transform:scale(.93) rotate(-8deg);filter:blur(0)}75%{transform:scale(1.03) rotate(-8.6deg)}100%{transform:scale(1) rotate(-8deg)}}
@keyframes rc-marker{from{transform:rotate(-1.1deg) skewX(-6deg) scaleX(0)}}
@keyframes rc-ticket{from{transform:var(--rc-tk-from,translateX(28px));clip-path:var(--rc-tk-clip,inset(0 0 0 100%))}to{transform:none;clip-path:inset(0)}}
@keyframes rc-sheet-in{from{transform:translateY(100%)}}
@keyframes rc-dialog-in{from{opacity:0;transform:translateY(-24px) scale(.97)}}
@keyframes rc-bar{from{transform:scaleY(0)}}
@keyframes rc-sheen{from{background-position:50% 100%,120% 0}to{background-position:50% 100%,-20% 0}}
@media (max-width:860px){
  :root[data-skin="receipt"] .sheet{border-bottom-width:0;
    background:conic-gradient(from 135deg at 50% 0,var(--pc) 90deg,#0000 0) 50% 0/14px 7px repeat-x border-box,linear-gradient(var(--pc) 0 0) padding-box;
    border-top-width:7px;animation:rc-sheet-in 700ms var(--sk-ease-feed) backwards}
  :root[data-skin="receipt"] .hero__v{font-size:46px}
}

/* ============================================================
   نئو بروتال (neo-brutal) — screen-printed menu board: flat colour slabs,
   3 px ink outlines, HARD shadows falling bottom-left (−x,+y, zero blur);
   pressing pushes a thing into its shadow. Lalezar only for signage ≥ 18 px,
   Estedad 800–900 for every number. The focal element stands on a DOUBLE
   slab (mustard + tomato). Light only.
   ============================================================ */
:root[data-skin="brutal"]{
  color-scheme:light;
  --bg:#F2EFE6;--panel:#FFFFFF;--card:#FFFFFF;--sunk:#E7E2D4;--hover:#FFF0C4;
  --line:rgba(22,20,15,.28);--line-2:#16140F;--line-3:#16140F;
  --ink:#16140F;--ink-2:#3B372F;--ink-3:#5C574C;--ink-4:#5C574C;--ink-icon:#3B372F;
  --brand:#16140F;--brand-solid:#FFC53D;--brand-weak:#FFF0C4;--on-brand:#16140F;
  --ok:#2E7417;--ok-weak:#E2F2D4;--ok-ink:#2E7417;--warn:#8A5A00;--warn-weak:#FFF0C4;--bad:#C22E12;--bad-weak:#FFE1D8;
  --c1:#1E56D6;--c2:#C22E12;--c3:#8A5A00;--c0:#5C574C;--c4:#2E7417;--c5:#8A5A00;--vip-weak:#DDF0FF;
  --glass:#FFFFFF;--glass-strong:#FFFFFF;--tabglass:#FFFFFF;--tabrim:#16140F;--tablift:none;
  --rim:#16140F;--rim-top:transparent;
  --shadow-sm:none;--shadow-md:none;--shadow-lg:none;--lift-sm:none;--lift:none;--lift-lg:none;
  --r-sm:10px;--r:12px;--r-lg:16px;--r-xl:22px;--tab-ink:#3B372F;
  --nb-font:Estedad,Tahoma,sans-serif;--nb-display:Lalezar,Estedad,Tahoma,sans-serif;
  --nb-ease-out:cubic-bezier(.22,1,.36,1);--nb-ease-in:cubic-bezier(.55,0,.8,.2);
  --nb-spring:linear(0,0.0036,0.0142 1.5%,0.0564 3.1%,0.1273 4.8%,0.2385 6.8%,0.5176 11%,0.6395 13%,0.7474 15%,0.8398,0.9158 19.2%,0.9757 21.4%,1.0199 23.6%,1.0522 26%,1.0717 28.5%,1.0799 31.2%,1.0785 33.9%,1.0688 37%,1.0217 46.5%,1.0022 52.3%,0.9927 58%,0.9897 62.9%,0.9934 73.3%,1.0002 88.8%,1);
  --nb-pop:linear(0,0.013 1.4%,0.054 2.9%,0.206 6.2%,0.44 10%,0.899 17.2%,1.064 20.7%,1.18 24.4%,1.216 27%,1.226 29.8%,1.201 33.5%,1.128 39%,0.989 50%,0.961 55.5%,0.957 60%,0.974 68.5%,1.004 83%,1);
  --nb-settle:linear(0,0.2 8%,0.55 18%,0.9 30%,1.045 38%,1.06 44%,1.02 56%,0.995 70%,1);
  --nb-hazard:repeating-linear-gradient(-45deg,#16140F 0 2.5px,transparent 2.5px 7px);
  --nb-double:-7px 7px 0 -3px #FFC53D,-7px 7px 0 0 #16140F,-14px 14px 0 -3px #FF5A36,-14px 14px 0 0 #16140F;
}
:root[data-skin="brutal"] body{font-family:var(--nb-font);font-weight:500;color:#16140F;background-color:#F2EFE6;
  background-image:radial-gradient(rgba(22,20,15,.15) 1.2px,transparent 1.7px);background-size:24px 24px;background-position:-12px 0;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
:root[data-skin="brutal"] ::selection{background:#FFC53D;color:#16140F}
:root[data-skin="brutal"] :focus-visible{outline:3px solid #1E56D6;outline-offset:3px}
:root[data-skin="brutal"] .side :focus-visible{outline-color:#8ECFFF}
:root[data-skin="brutal"] .app{border:3px solid #16140F;border-radius:16px;background:transparent;box-shadow:-8px 8px 0 0 #16140F}
:root[data-skin="brutal"] .main{background:transparent}
/* the rail: an ink strip; the current item is a mustard slab on a tomato shadow */
:root[data-skin="brutal"] .side{background:#16140F;color:#F2EFE6;border:0;backdrop-filter:none;-webkit-backdrop-filter:none}
:root[data-skin="brutal"] .brandline{border-bottom:2px dashed rgba(242,239,230,.28);margin-bottom:6px}
:root[data-skin="brutal"] .brandline b{color:#F2EFE6;font-weight:900}
:root[data-skin="brutal"] .brandline span{color:rgba(242,239,230,.74)}
:root[data-skin="brutal"] .brandmark{background:#FFC53D;color:#16140F;border-radius:10px;box-shadow:0 0 0 2px #F2EFE6}
:root[data-skin="brutal"] .navlabel{color:rgba(242,239,230,.74);font-weight:700}
:root[data-skin="brutal"] .navitem{color:rgba(242,239,230,.74);font-weight:700;border:2px solid transparent;border-radius:10px;
  transition:background-color 160ms var(--nb-ease-out),color 160ms var(--nb-ease-out),transform 260ms var(--nb-spring),box-shadow 260ms var(--nb-spring)}
:root[data-skin="brutal"] .navitem svg{color:currentColor}
:root[data-skin="brutal"] .navitem:hover{background:rgba(242,239,230,.09);color:#F2EFE6}
:root[data-skin="brutal"] .navitem:active{transform:translate(-2px,2px)}
:root[data-skin="brutal"] .navitem[aria-current="page"]{background:#FFC53D;color:#16140F;border-color:#16140F;box-shadow:-4px 4px 0 0 #FF5A36}
:root[data-skin="brutal"] .navitem[aria-current="page"] svg{color:#16140F}
:root[data-skin="brutal"] .navitem[aria-current="page"]:active{box-shadow:0 0 0 0 #FF5A36;transform:translate(-4px,4px)}
:root[data-skin="brutal"] .side__foot{border-top:2px dashed rgba(242,239,230,.28)}
:root[data-skin="brutal"] .topbar{background:#F2EFE6;border-bottom:3px solid #16140F;backdrop-filter:none;-webkit-backdrop-filter:none}
:root[data-skin="brutal"] .topbar h1{font:400 26px/1.3 var(--nb-display);letter-spacing:0}
:root[data-skin="brutal"] .sect__hd h2{font:400 24px/1.3 var(--nb-display);letter-spacing:0}
/* panels, tiles: white card, ink edge, hard shadow */
:root[data-skin="brutal"] .card,:root[data-skin="brutal"] .tile{background:#FFFFFF;border:3px solid #16140F;border-radius:16px;box-shadow:-5px 5px 0 0 #16140F}
:root[data-skin="brutal"] .card.card--sunk{background:#E7E2D4;box-shadow:none;border-width:2px}
:root[data-skin="brutal"] .card .card{box-shadow:none;border-width:2px}
:root[data-skin="brutal"] .tile{transition:transform 320ms var(--nb-spring),box-shadow 320ms var(--nb-spring)}
@media (hover:hover) and (pointer:fine){:root[data-skin="brutal"] .tile:hover{transform:translate(2px,-2px);box-shadow:-7px 7px 0 0 #16140F}}
:root[data-skin="brutal"] .card__hd{border-bottom:3px solid #16140F}
:root[data-skin="brutal"] .card__hd h2{font:400 20px/1.35 var(--nb-display);letter-spacing:0}
:root[data-skin="brutal"] .tile__v{font-weight:900;letter-spacing:0}
/* the focal number of a screen stands on the DOUBLE slab */
:root[data-skin="brutal"] .hero{background:#FFC53D;border:3px solid #16140F;border-radius:16px;box-shadow:var(--nb-double);margin:0 0 14px 14px}
:root[data-skin="brutal"] .hero::after{display:none}
:root[data-skin="brutal"] .hero__v{font-weight:900;font-size:44px;letter-spacing:0}
:root[data-skin="brutal"] .hero__v small,:root[data-skin="brutal"] .hero .muted,:root[data-skin="brutal"] .hero .tiny{color:#3B372F}
/* keys: press = into the shadow, release = spring */
:root[data-skin="brutal"] .btn{--o:3px;--bg:#FFFFFF;--fg:#16140F;--sc:#16140F;border:3px solid #16140F;border-radius:10px;
  background:var(--bg);color:var(--fg);font-weight:800;box-shadow:calc(var(--o) * -1) var(--o) 0 0 var(--sc);
  transition:transform 260ms var(--nb-spring),box-shadow 260ms var(--nb-spring),background-color 160ms var(--nb-ease-out)}
:root[data-skin="brutal"] .btn:hover:not(:disabled){background:var(--bg);border-color:#16140F}
@media (hover:hover) and (pointer:fine){:root[data-skin="brutal"] .btn:hover:not(:disabled){transform:translate(1.5px,-1.5px);
  box-shadow:calc((var(--o) + 1.5px) * -1) calc(var(--o) + 1.5px) 0 0 var(--sc)}}
:root[data-skin="brutal"] .btn:active:not(:disabled){transform:translate(calc(var(--o) * -1),var(--o));box-shadow:0 0 0 0 var(--sc);
  transition-duration:70ms;transition-timing-function:linear}
:root[data-skin="brutal"] .btn--pri{--bg:#FFC53D;--fg:#16140F}
:root[data-skin="brutal"] .btn--danger{--bg:#FF5A36;--fg:#16140F}
:root[data-skin="brutal"] .btn--ghost,:root[data-skin="brutal"] .btn--ghost:hover:not(:disabled){--bg:transparent;border-color:transparent;box-shadow:none;transform:none}
:root[data-skin="brutal"] .btn--ghost:hover:not(:disabled){background:rgba(22,20,15,.07)}
:root[data-skin="brutal"] .btn--ghost:active:not(:disabled){transform:translate(0,1px);box-shadow:none;background:rgba(22,20,15,.12)}
:root[data-skin="brutal"] .btn--sm{--o:2px;border-width:2px;border-radius:8px}
:root[data-skin="brutal"] .btn[disabled]{--bg:#E7E2D4;--fg:#5C574C;opacity:1;border-color:#5C574C;box-shadow:none;
  background-image:repeating-linear-gradient(-45deg,rgba(22,20,15,.12) 0 2px,transparent 2px 8px)}
/* stickers & chips: ink text on colour, always */
:root[data-skin="brutal"] .pill{border:2px solid #16140F;border-radius:999px;background:#FFFFFF;color:#16140F;font-weight:800}
:root[data-skin="brutal"] .pill--ok{background:#7CC45A;color:#16140F}
:root[data-skin="brutal"] .pill--warn{background:#FFC53D;color:#16140F}
:root[data-skin="brutal"] .pill--bad{background:#FF5A36;color:#16140F}
:root[data-skin="brutal"] .pill--brand,:root[data-skin="brutal"] .pill--vip{background:#8ECFFF;color:#16140F;border-color:#16140F}
:root[data-skin="brutal"] .pill--mute{background:#E7E2D4;color:#16140F}
:root[data-skin="brutal"] .pill--out{background:#FFFFFF;color:#3B372F}
:root[data-skin="brutal"] .tag,:root[data-skin="brutal"] .locchip,:root[data-skin="brutal"] .coefb{border:2px solid #16140F;color:#16140F}
:root[data-skin="brutal"] .coefb{background:#FFF0C4}
/* fields lift off the page when they take focus */
:root[data-skin="brutal"] .input{background:#FFFFFF;border:3px solid #16140F;border-radius:10px;box-shadow:0 0 0 0 #16140F;
  transition:transform 260ms var(--nb-spring),box-shadow 260ms var(--nb-spring)}
:root[data-skin="brutal"] .input:focus-within{border-color:#16140F;transform:translate(2px,-2px);box-shadow:-5px 5px 0 0 #16140F;
  outline:none;background:#FFF0C4}
:root[data-skin="brutal"] .input input,:root[data-skin="brutal"] .input textarea{font-weight:600}
:root[data-skin="brutal"] .input input::placeholder{color:#5C574C}
:root[data-skin="brutal"] .input svg{color:#16140F}
:root[data-skin="brutal"] .field>label{color:#3B372F;font-weight:700}
/* notes; danger gets the hazard stripe (and its icon), nothing else does */
:root[data-skin="brutal"] .note,:root[data-skin="brutal"] .callout{border:2px solid #16140F;border-radius:12px;background:#FFFFFF;color:#16140F}
:root[data-skin="brutal"] .note--warn,:root[data-skin="brutal"] .callout--warn{background:#FFF0C4;color:#16140F}
:root[data-skin="brutal"] .note--ok,:root[data-skin="brutal"] .callout--ok{background:#E2F2D4;color:#16140F}
:root[data-skin="brutal"] .note--brand{background:#DDF0FF;color:#16140F}
:root[data-skin="brutal"] .note--bad,:root[data-skin="brutal"] .callout--bad{color:#16140F;border-width:3px;box-shadow:-3px 3px 0 0 #16140F;
  padding-inline-start:26px;background-color:#FFE1D8;
  background-image:linear-gradient(#16140F,#16140F),var(--nb-hazard),linear-gradient(#FF5A36,#FF5A36);
  background-size:3px 100%,12px 100%,12px 100%;background-position:right 12px top,right top,right top;background-repeat:no-repeat}
/* rows: dashed hair, never a solid line */
:root[data-skin="brutal"] .tbl th{background:#FFFFFF;color:#16140F;font-weight:800;letter-spacing:0;border-bottom:3px solid #16140F}
:root[data-skin="brutal"] .tbl td{border-bottom:2px dashed rgba(22,20,15,.28)}
:root[data-skin="brutal"] .tbl tbody tr:hover{background:#FFF0C4}
:root[data-skin="brutal"] .li,:root[data-skin="brutal"] .rowcard,:root[data-skin="brutal"] .ledg__r,
:root[data-skin="brutal"] .credrow,:root[data-skin="brutal"] .li--btn{border-bottom:2px dashed rgba(22,20,15,.28)}
:root[data-skin="brutal"] .li--btn:hover,:root[data-skin="brutal"] .rowcard:active{background:#FFF0C4}
:root[data-skin="brutal"] .list.list--boxed{border:2px solid #16140F;border-radius:12px}
:root[data-skin="brutal"] .hr,:root[data-skin="brutal"] .hr-flex{height:0;background:none;border-top:2px dashed rgba(22,20,15,.28)}
/* pressable cards: tiles on the counter */
:root[data-skin="brutal"] .choice,:root[data-skin="brutal"] .locrow,:root[data-skin="brutal"] .rung,:root[data-skin="brutal"] .skinopt{
  background:#FFFFFF;border:3px solid #16140F;border-radius:12px;box-shadow:-3px 3px 0 0 #16140F;
  transition:transform 260ms var(--nb-spring),box-shadow 260ms var(--nb-spring),background-color 160ms var(--nb-ease-out)}
@media (hover:hover) and (pointer:fine){
  :root[data-skin="brutal"] .choice:hover:not([disabled]),:root[data-skin="brutal"] .locrow:hover:not([disabled]):not(.locrow--ro),
  :root[data-skin="brutal"] .rung:hover,:root[data-skin="brutal"] .skinopt:hover{background:#FFFFFF;transform:translate(1.5px,-1.5px);box-shadow:-4.5px 4.5px 0 0 #16140F}
}
:root[data-skin="brutal"] .choice:active:not([disabled]),:root[data-skin="brutal"] .locrow:active:not([disabled]),
:root[data-skin="brutal"] .rung:active,:root[data-skin="brutal"] .skinopt:active{transform:translate(-3px,3px);box-shadow:0 0 0 0 #16140F;transition-duration:70ms;transition-timing-function:linear}
:root[data-skin="brutal"] .choice[aria-pressed="true"],:root[data-skin="brutal"] .locrow[aria-pressed="true"],
:root[data-skin="brutal"] .skinopt[aria-checked="true"]{background:#FFF0C4;border-color:#16140F;box-shadow:-3px 3px 0 0 #16140F}
:root[data-skin="brutal"] .choice--lock{background:#E7E2D4;border-style:dashed;box-shadow:none}
:root[data-skin="brutal"] .locrow__box{border:2px solid #16140F;border-radius:6px}
:root[data-skin="brutal"] .locrow[aria-pressed="true"] .locrow__box{background:#16140F;border-color:#16140F}
:root[data-skin="brutal"] .rung[data-best]{background:#E2F2D4}
:root[data-skin="brutal"] .rung__gb{background:#FFC53D;border:2px solid #16140F;border-radius:10px}
:root[data-skin="brutal"] .rung__gb b{font-weight:900}
:root[data-skin="brutal"] .takeaway__bx,:root[data-skin="brutal"] .linkbox{background:#FFFFFF;border:2px solid #16140F;border-radius:10px}
:root[data-skin="brutal"] .takeaway__bx .btn{border:0;border-inline-start:2px solid #16140F;border-radius:0;box-shadow:none;transform:none}
:root[data-skin="brutal"] .svc{border:2px solid #16140F;border-radius:10px}
:root[data-skin="brutal"] .amtchip{background:#FFFFFF;color:#16140F;border:2px solid #16140F;border-radius:999px;font-weight:800;
  box-shadow:-2px 2px 0 0 #16140F;transition:transform 260ms var(--nb-spring),box-shadow 260ms var(--nb-spring),background-color 160ms}
@media (hover:hover) and (pointer:fine){:root[data-skin="brutal"] .amtchip:hover{background:#FFFFFF;border-color:#16140F;transform:translate(1px,-1px);box-shadow:-3px 3px 0 0 #16140F}}
:root[data-skin="brutal"] .amtchip:active{transform:translate(-2px,2px);box-shadow:0 0 0 0 #16140F;transition-duration:70ms}
:root[data-skin="brutal"] .amtchip[aria-pressed="true"]{background:#FFC53D;color:#16140F;border-color:#16140F}
:root[data-skin="brutal"] .meter{height:14px;border:2px solid #16140F;border-radius:999px;background:#FFFFFF}
:root[data-skin="brutal"] .meter>i{background:#FFC53D;border-radius:0;border-inline-end:2px solid #16140F}
:root[data-skin="brutal"] .meter[data-tone="ok"]>i{background:#7CC45A}
:root[data-skin="brutal"] .meter[data-tone="bad"]>i{background:#FF5A36}
:root[data-skin="brutal"] .bars i{background:#FFC53D;border:2px solid #16140F;border-bottom:0;border-radius:4px 4px 0 0;
  transform-origin:50% 100%;animation:nb-grow-y 700ms var(--nb-settle) backwards}
:root[data-skin="brutal"] .bars>div:hover{background:#FFF0C4}
:root[data-skin="brutal"] .compo{border:2px solid #16140F}
/* popups */
:root[data-skin="brutal"] .scrim,:root[data-skin="brutal"] .mr-scrim{background-color:rgba(22,20,15,.52);
  background-image:radial-gradient(rgba(22,20,15,.35) 1.2px,transparent 1.7px);background-size:8px 8px;
  backdrop-filter:none;-webkit-backdrop-filter:none;animation:nb-fade 180ms linear}
:root[data-skin="brutal"] .sheet{background:#FFFFFF;border:3px solid #16140F;border-radius:22px;box-shadow:-8px 8px 0 0 #16140F;
  backdrop-filter:none;-webkit-backdrop-filter:none;animation:nb-dialog-in 520ms var(--nb-spring)}
:root[data-skin="brutal"] .sheet__hd{background:#FFC53D;border-bottom:3px solid #16140F;border-radius:19px 19px 0 0}
:root[data-skin="brutal"] .sheet--dialog .sheet__hd,:root[data-skin="brutal"] .sheet--dialog.is-scroll .sheet__hd{border-bottom:3px solid #16140F;padding-bottom:var(--s4)}
:root[data-skin="brutal"] .sheet__hd h2,:root[data-skin="brutal"] .sheet--dialog .sheet__hd h2{font:400 24px/1.35 var(--nb-display);letter-spacing:0}
:root[data-skin="brutal"] .sheet__hd .dlgsub{color:#3B372F}
:root[data-skin="brutal"] .sheet__ft{background:#FFFFFF;border-top:3px solid #16140F;border-radius:0 0 19px 19px}
:root[data-skin="brutal"] .dlgmark{border:2px solid #16140F;color:#16140F;background:#8ECFFF}
:root[data-skin="brutal"] .dlgmark--ok{background:#7CC45A;animation:nb-stamp 620ms var(--nb-pop) backwards}
:root[data-skin="brutal"] .dlgmark--warn{background:#FFC53D}
:root[data-skin="brutal"] .dlgmark--bad{background:#FF5A36}
:root[data-skin="brutal"] .toast{background:#16140F;color:#F2EFE6;border:3px solid #16140F;border-radius:14px;font-weight:800;
  box-shadow:-6px 6px 0 -3px #7CC45A,-6px 6px 0 0 #16140F;animation:nb-toast-in 560ms var(--nb-pop)}
:root[data-skin="brutal"] .skel{background:#E7E2D4;border:2px dashed rgba(22,20,15,.28)}
:root[data-skin="brutal"] .spin{border-color:rgba(22,20,15,.25);border-top-color:#16140F;border-width:3px}
:root[data-skin="brutal"] .qrbox{border:3px solid #16140F;box-shadow:-3px 3px 0 0 #16140F}
:root[data-skin="brutal"] .stgrp{background:#FFF0C4}
:root[data-skin="brutal"] .impersonate{background:#FF5A36;color:#16140F;border-bottom:3px solid #16140F}
/* entrances drop in and settle, staggered */
:root[data-skin="brutal"] .anim-rise{animation:nb-drop 480ms var(--nb-spring) backwards;animation-delay:calc(var(--i,0) * 45ms)}
/* 💳 the card = the club member card: mustard, halftone, ink edge, a double slab */
:root[data-skin="brutal"] .bcard{--bc-ink:#16140F;--bc-ink2:#3B372F;color:#16140F;background-color:#FFC53D;
  background-image:radial-gradient(rgba(22,20,15,.16) 1.3px,transparent 1.8px);background-size:9px 9px;
  border:3px solid #16140F;border-radius:20px;margin:0 0 16px 14px;width:calc(100% - 14px);
  box-shadow:-7px 7px 0 -3px #FF5A36,-7px 7px 0 0 #16140F,-14px 14px 0 -3px #8ECFFF,-14px 14px 0 0 #16140F}
:root[data-skin="brutal"] .bcard::before{display:none}
:root[data-skin="brutal"] .bcard__bank{color:#16140F;font:400 20px/1.3 var(--nb-display)}
:root[data-skin="brutal"] .bcard__chip{background:#16140F;box-shadow:none;border-radius:6px}
:root[data-skin="brutal"] .bcard__no{background:#FFFFFF;border:2px solid #16140F;margin-inline:0;width:100%;letter-spacing:.06em;font-weight:800}
:root[data-skin="brutal"] .bcard__no:hover{background:#FFF0C4}
:root[data-skin="brutal"] .bcard__mini:hover{background:rgba(22,20,15,.1)}
:root[data-skin="brutal"] .bcard__holder{font-weight:900}
:root[data-skin="brutal"] .bcard__amt{border-top:3px dashed #16140F}
:root[data-skin="brutal"] .bcard__rial{font-weight:900;font-size:30px}
:root[data-skin="brutal"] .bcard__copy{background:#16140F;color:#FFC53D;border:3px solid #16140F;border-radius:10px;box-shadow:-3px 3px 0 0 #FFFFFF;
  transition:transform 260ms var(--nb-spring),box-shadow 260ms var(--nb-spring)}
:root[data-skin="brutal"] .bcard__copy:active{transform:translate(-3px,3px);box-shadow:0 0 0 0 #FFFFFF;transition-duration:70ms}
:root[data-skin="brutal"] .bcard :focus-visible{outline:3px solid #1E56D6;outline-offset:3px}
@media (max-width:860px){
  :root[data-skin="brutal"] .app{border:0;border-radius:0;box-shadow:none}
  /* 🔴 Round 4 (owner's screenshot, 390 px): the two stacked shadows drew a
     SECOND rounded top edge 8 px above the sheet's own border (a yellow sliver
     and a black arc over the yellow header). One edge: the sheet's border. */
  :root[data-skin="brutal"] .sheet{border-bottom:0;border-radius:22px 22px 0 0;
    box-shadow:none;animation:nb-sheet-up 560ms var(--nb-spring)}
  :root[data-skin="brutal"] .sheet__ft{border-radius:0}
  :root[data-skin="brutal"] .tabs{background:#FFFFFF;border:0;border-top:3px solid #16140F;box-shadow:none}
  :root[data-skin="brutal"] .tab{color:#3B372F;font-weight:700}
  :root[data-skin="brutal"] .tab[aria-current="page"]{color:#16140F;font-weight:800}
  :root[data-skin="brutal"] .tab[aria-current="page"] .tab__ic{background:#FFC53D;box-shadow:inset 0 0 0 2px #16140F,-3px 3px 0 0 #16140F}
  :root[data-skin="brutal"] .tab--new .tab__ic{background:#16140F;color:#FFC53D}
  :root[data-skin="brutal"] .tab:active .tab__ic{transform:translate(-2px,2px)}
  :root[data-skin="brutal"] .tab__badge{background:#FF5A36;color:#16140F;border:2px solid #16140F;box-shadow:none;line-height:14px}
  :root[data-skin="brutal"] .hero__v{font-size:38px}
  :root[data-skin="brutal"] .topbar h1{font-size:22px}
}
@keyframes nb-drop{from{opacity:0;transform:translate(4px,-22px) rotate(-1.5deg)}35%{opacity:1}to{opacity:1;transform:none}}
@keyframes nb-stamp{0%{opacity:0;transform:scale(1.9) rotate(-20deg)}40%{opacity:1}100%{opacity:1;transform:scale(1) rotate(-4deg)}}
@keyframes nb-dialog-in{from{opacity:0;transform:translateY(-36px) rotate(2deg) scale(.96)}30%{opacity:1}to{opacity:1;transform:none}}
@keyframes nb-sheet-up{from{transform:translateY(105%)}to{transform:none}}
@keyframes nb-toast-in{from{opacity:0;transform:translateY(34px) rotate(-5deg) scale(.9)}30%{opacity:1}to{opacity:1;transform:none}}
@keyframes nb-grow-y{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes nb-fade{from{opacity:0}to{opacity:1}}

/* the picker on «مشخصات من» (all skins) */
.skinpick{display:grid;gap:var(--s3);grid-template-columns:repeat(3,minmax(0,1fr))}
.skinopt{display:flex;flex-direction:column;align-items:flex-start;gap:8px;padding:var(--s3);border-radius:var(--r);text-align:start;
  border:1px solid var(--line-2);background:var(--card);min-height:44px;transition:border-color var(--t-fast),background var(--t-fast)}
.skinopt:hover{border-color:var(--line-3)}
.skinopt[aria-checked="true"]{border-color:var(--brand);box-shadow:0 0 0 1px var(--brand)}
.skinopt__b b{display:block;font-size:14px}
.skinopt__b span{display:block;font-size:11.5px;color:var(--ink-3);line-height:1.6}
.skinopt__sw{display:flex;gap:4px}
.skinopt__sw i{width:22px;height:22px;border-radius:6px;display:block}
.skinopt--default .skinopt__sw i:nth-child(1){background:#0a0b0d}.skinopt--default .skinopt__sw i:nth-child(2){background:#2f5fd9}.skinopt--default .skinopt__sw i:nth-child(3){background:#f7f8f9;box-shadow:inset 0 0 0 1px #d3d8de}
.skinopt--receipt .skinopt__sw i:nth-child(1){background:#D4D8D6;box-shadow:inset 0 0 0 1px #858A86}.skinopt--receipt .skinopt__sw i:nth-child(2){background:#FBFBF8;box-shadow:inset 0 0 0 1px #DCDCD3}.skinopt--receipt .skinopt__sw i:nth-child(3){background:#3A3FA5}
.skinopt--brutal .skinopt__sw i:nth-child(1){background:#FFC53D;box-shadow:inset 0 0 0 2px #16140F}.skinopt--brutal .skinopt__sw i:nth-child(2){background:#FF5A36;box-shadow:inset 0 0 0 2px #16140F}.skinopt--brutal .skinopt__sw i:nth-child(3){background:#8ECFFF;box-shadow:inset 0 0 0 2px #16140F}
/* 💳 round 4: the claim's own actions + the lock line */
.depacts{align-items:center}
.note--lock{border-style:dashed}
.skinpick--4{grid-template-columns:repeat(2,minmax(0,1fr))}
.skinopt--inherit .skinopt__sw i{background:transparent;box-shadow:inset 0 0 0 1.5px var(--line-3);border-radius:50%}
@media (max-width:560px){.skinpick,.skinpick--4{grid-template-columns:1fr}.skinopt{flex-direction:row;align-items:center}.skinopt .pill{margin-inline-start:auto}}

/* ============================================================
   📱 the bottom bar (round 3, all skins): docked, five equal slots,
   icon + label, the current one on a filled pill, count badges.
   ============================================================ */
@media (max-width:860px){
  .tabs{inset-inline:0;bottom:0;margin:0;border-radius:0;padding:6px 4px calc(6px + env(safe-area-inset-bottom,0px));
    background:var(--panel);border:0;border-top:1px solid var(--line-2);
    box-shadow:0 -8px 20px -14px rgba(0,0,0,.45);backdrop-filter:none;-webkit-backdrop-filter:none;
    grid-template-columns:repeat(5,minmax(0,1fr));align-items:stretch}
  .tabs::before{display:none}
  .tab{min-height:56px;padding:4px 2px;gap:4px;justify-content:flex-start;font-size:11.5px;font-weight:600;color:var(--ink-3);
    min-width:0;border-radius:12px}
  .tab>span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .tab__ic{position:relative;display:grid;place-items:center;width:52px;height:30px;border-radius:15px;font-style:normal;
    transition:background var(--t),transform var(--t-fast)}
  .tab__ic svg{width:22px;height:22px}
  .tab[aria-current="page"]{color:var(--brand)}
  .tab[aria-current="page"] svg{transform:none}
  .tab[aria-current="page"] .tab__ic{background:var(--brand-weak)}
  .tab--new .tab__ic{background:var(--brand-solid);color:#fff}
  .tab:active .tab__ic{transform:scale(.94)}
  .tab__badge{position:absolute;top:-5px;inset-inline-end:4px;min-width:18px;height:18px;padding:0 4px;border-radius:9px;
    background:var(--bad);color:#fff;font-size:10.5px;font-weight:800;line-height:18px;text-align:center;font-style:normal;
    box-shadow:0 0 0 2px var(--panel)}
  .content{padding-bottom:calc(92px + env(safe-area-inset-bottom,0px))}
  .wizfoot{bottom:calc(70px + env(safe-area-inset-bottom,0px))}
  .toast{inset-block-end:calc(84px + env(safe-area-inset-bottom,0px))}
}
@media (prefers-reduced-motion:reduce){
  :root[data-skin] .anim-rise,:root[data-skin] .bars i,:root[data-skin] .dlgmark,:root[data-skin] .hero__v::before,
  :root[data-skin] .navitem::before,:root[data-skin] .tab::before,:root[data-skin] .bcard::before{animation:none}
}
/* Estedad's tabular «٬» is a full digit wide (the artifact's own note: «money
   looks gappy»); running text and display figures take its proportional
   figures, number COLUMNS stay tabular so units line up. */
:root[data-skin] body{font-variant-numeric:proportional-nums}
:root[data-skin] .num,:root[data-skin] .cnum,:root[data-skin] .bcard__toman,:root[data-skin] .payamt__toman,
:root[data-skin] .bcard__rial,:root[data-skin] .payamt__rial,:root[data-skin] .input.input--amt input{font-variant-numeric:proportional-nums}
:root[data-skin] .tbl td{font-variant-numeric:tabular-nums}
:root[data-skin="brutal"] .hero__v .cnum,:root[data-skin="brutal"] .tile__v .cnum,:root[data-skin="brutal"] .bcard__rial{font-variant-numeric:proportional-nums}
:root[data-skin="receipt"] .gifthero{background:#FBF4A6;border:0;border-radius:0;border-inline-start:3px solid #F6EA4B}
:root[data-skin="brutal"] .gifthero{background:#DDF0FF;border:3px solid #16140F;border-radius:16px;box-shadow:-5px 5px 0 0 #16140F}

/* ============================================================
   🎞 ROUND 4 (1405/07/04) · MOTION, brought up to the artifact.
   The owner: «انیمیشن‌ها خیلی کمه! توی تم‌های ساخته‌شده همشون انیمیشن
   دارن! مثلاً تغییر اعداد! اسپینرهای مناسب!». Ported from the artifact's
   m/receipt + m/neo-brutal family.css/js (durations, easings, signatures):
     receipt   press 90 · print 420 steps(7) · enter 620 · roll 900 spring ·
               draw 1100 · stagger 50 · toast feeds in (staircase) and tears
               off · sheet tears off and drops
     brutal    press 70 linear · base 260 spring · slow 480 · stamp 620 pop ·
               odometer 780 settle, 28 ms a digit · ka-chunk thunk ·
               toast pops in, flicks out · sheet falls out of its shadow
     default   the panel's own: rise 360, count-up 1000 ease-out-cubic
   RULES (the .nav-fresh lesson of round 3): every entrance here is gated on
   a one-render class -- .nav-fresh (route changed), .data-fresh (a list's
   first answer this session), a sheet that is not .is-stay, or a JS one-shot
   class (.is-picked, .is-bumped, .is-out) -- so a redraw never replays it.
   Transform and opacity only; the page at rest is always complete
   (backwards fill); prefers-reduced-motion flattens all of it (the global
   rule at the top of this file) and the counters check it in JS.
   ============================================================ */

/* --- rows enter ONCE ---------------------------------------------------- */
.list>.li,.list>.rowcard{animation:none}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(2){--st:1}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(3){--st:2}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(4){--st:3}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(5){--st:4}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(6){--st:5}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(7){--st:6}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(8){--st:7}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(9){--st:8}
:is(.list,tbody,.bento,.choices,.ladder,.skinpick,.amtchips,.locchips,.skelrows)>:nth-child(n+10){--st:9}
:is(.nav-fresh,.data-fresh) :is(.list>.li,.list>.rowcard,.list>.stgrp,tbody>tr,.bento>.tile,.choices>.choice,.skinpick>.skinopt,.amtchips>.amtchip,.locchips>.locchip),
.scrim:not(.is-stay):not(.is-closing) :is(.list>.li,.list>.rowcard,tbody>tr,.choices>.choice,.skinpick>.skinopt,.amtchips>.amtchip,.locchips>.locchip){
  animation:r4-rise 450ms cubic-bezier(.2,.8,.2,1) backwards;animation-delay:calc(var(--st,0) * 56ms)}
@keyframes r4-rise{from{opacity:0;transform:translateY(10px)}}
/* the ladder's rungs carried .anim-rise and replayed on every redraw */
.app:not(.nav-fresh):not(.data-fresh) .ladder>.rung.anim-rise{animation:none}

/* --- meters fill from zero, once --------------------------------------- */
:is(.nav-fresh,.data-fresh) .meter>i,.scrim:not(.is-stay):not(.is-closing) .meter>i{
  transform-origin:100% 50%;animation:r4-fill 1125ms cubic-bezier(.2,.8,.2,1) 150ms backwards}
@keyframes r4-fill{from{transform:scaleX(0)}}

/* --- press feedback on everything you tap ------------------------------ */
.amtchip,.pill--btn,.choice,.rowcard,.locrow,.skinopt,.li--btn,.tok{transition:transform 175ms cubic-bezier(.2,.8,.2,1)}
.amtchip:active,.pill--btn:active,.choice:active:not(:disabled),.rowcard:active,.locrow:active:not(:disabled),
.skinopt:active,.li--btn:active,.tok:active{transform:scale(.97)}

/* --- a chip / choice just picked: one pop ------------------------------ */
.is-picked{animation:r4-pick 475ms cubic-bezier(.3,1.6,.5,1)}
@keyframes r4-pick{40%{transform:scale(1.06)}}

/* --- a figure that changed knocks once it lands ------------------------ */
.cnum.is-bumped{display:inline-block;animation:r4-bump 650ms cubic-bezier(.3,1.6,.5,1)}
@keyframes r4-bump{35%{transform:scale(1.07)}}

/* --- the odometer (app.js odoRoll; skins only) ------------------------- */
.odo{display:inline-flex;direction:ltr;unicode-bidi:isolate;white-space:nowrap;vertical-align:bottom;line-height:1.15}
.odo__d{display:inline-block;height:1.15em;overflow:hidden}
.odo__s{display:inline-block;line-height:1.15}
.odo__reel{display:flex;flex-direction:column;transform:translateY(calc(var(--n,0) * -1.15em))}
.odo__reel>span{display:block;height:1.15em;line-height:1.15em;text-align:center}
.odo--go .odo__reel{transition:transform 1125ms cubic-bezier(.2,.8,.2,1);transition-delay:calc(var(--k,0) * 44ms)}

/* --- toasts: in once, and they LEAVE ----------------------------------- */
.toast.is-shown{animation:none}
.toast.is-out{animation:r4-toast-out 275ms cubic-bezier(.55,0,.8,.2) forwards}
@keyframes r4-toast-out{to{opacity:0;transform:translateY(14px)}}

/* --- sheets leave the way they came (app.js closeAnimated) -------------- */
#app>.scrim.is-closing{animation:r4-fade-out 300ms ease-in forwards}
#app>.scrim.is-closing .sheet{animation:r4-pop-out 275ms cubic-bezier(.55,0,.8,.2) forwards}
@keyframes r4-fade-out{to{opacity:0}}
@keyframes r4-pop-out{to{opacity:0;transform:scale(.97) translateY(10px)}}
@media (max-width:640px){#app>.scrim.is-closing .sheet{animation:r4-sheet-down 325ms cubic-bezier(.55,0,.8,.2) forwards}}
@keyframes r4-sheet-down{to{transform:translateY(100%)}}

/* --- the live poll: a spinner only while a (slow) read is out ---------- */
.livespin{display:none;margin-inline-start:6px;vertical-align:middle}
.is-polling .livespin{display:inline-block}
.skelrows>.skel{animation:r4-rise 450ms cubic-bezier(.2,.8,.2,1) backwards;animation-delay:calc(var(--st,0) * 75ms)}

/* ============== رسید حرارتی: the thermal head ========================= */
:root[data-skin="receipt"] :is(.nav-fresh,.data-fresh) :is(.list>.li,.list>.rowcard,.list>.stgrp,tbody>tr,.bento>.tile,.choices>.choice,.skinpick>.skinopt,.amtchips>.amtchip,.locchips>.locchip),
:root[data-skin="receipt"] .scrim:not(.is-stay):not(.is-closing) :is(.list>.li,.list>.rowcard,tbody>tr,.choices>.choice,.skinpick>.skinopt,.amtchips>.amtchip,.locchips>.locchip){
  animation:r4-rc-print 525ms steps(7,end) backwards,r4-rc-develop 1000ms var(--sk-ease-out) backwards;
  animation-delay:calc(var(--st,0) * 62ms)}
@keyframes r4-rc-print{from{transform:translateY(-7px);opacity:.15}}
@keyframes r4-rc-develop{from{opacity:.35}}
:root[data-skin="receipt"] :is(.nav-fresh,.data-fresh) .meter>i,:root[data-skin="receipt"] .scrim:not(.is-stay):not(.is-closing) .meter>i{
  animation:r4-fill 1375ms steps(16,end) 188ms backwards}
/* a key has a lip: tapping pushes it down (press 90 ms) */
:root[data-skin="receipt"] :is(.amtchip,.pill--btn,.rowcard,.locrow,.skinopt,.li--btn,.tok):active{transform:translateY(2px);transition-duration:112ms}
:root[data-skin="receipt"] .choice:active:not(:disabled){transform:translateY(2px) rotate(-.25deg);transition-duration:112ms}
:root[data-skin="receipt"] .is-picked{animation:r4-rc-stamp 650ms var(--sk-spring)}
@keyframes r4-rc-stamp{0%{transform:scale(1.05) rotate(-.8deg)}55%{transform:scale(.985) rotate(.2deg)}}
/* the figure lands under the yellow highlighter */
:root[data-skin="receipt"] .cnum.is-bumped{position:relative;animation:none}
:root[data-skin="receipt"] .cnum.is-bumped::after{content:"";position:absolute;inset:-1px -5px;background:#F6EA4B;
  mix-blend-mode:multiply;border-radius:3px;pointer-events:none;transform-origin:100% 50%;
  animation:r4-rc-mark 1125ms var(--sk-ease-out) forwards}
@keyframes r4-rc-mark{0%{transform:scaleX(0);opacity:1}35%{transform:scaleX(1);opacity:1}100%{transform:scaleX(1);opacity:0}}
:root[data-skin="receipt"] .odo--go .odo__reel{transition:transform 1125ms var(--sk-spring);transition-delay:calc(var(--k,0) * 44ms)}
/* the spinner is a print line: dots printed right to left, the red head moving */
:root[data-skin="receipt"] .spin{width:30px;height:8px;border:0;border-radius:0;background:none;position:relative;overflow:hidden;
  box-shadow:none;animation:ldin .25s ease .3s forwards}
:root[data-skin="receipt"] .spin::before{content:"";position:absolute;inset:0;
  background:radial-gradient(circle,currentColor 1.25px,transparent 1.7px) 100% 50%/5px 8px repeat-x;
  transform-origin:100% 50%;animation:r4-rc-dots 1.5s steps(6,end) infinite}
:root[data-skin="receipt"] .spin::after{content:"";position:absolute;top:0;bottom:0;right:0;width:3px;background:#C21D38;
  animation:r4-rc-head 1.5s steps(6,end) infinite}
@keyframes r4-rc-dots{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes r4-rc-head{from{transform:translateX(0)}to{transform:translateX(-30px)}}
/* skeleton = a dot-matrix line being fed, the head sweeping in steps */
:root[data-skin="receipt"] .skel{background:radial-gradient(circle,#C9CBC3 1.2px,transparent 1.6px) 100% 50%/6px 6px repeat-x,#F2F2ED;border:0;border-radius:0}
:root[data-skin="receipt"] .skel::after{background:linear-gradient(90deg,transparent,rgba(246,234,75,.55),transparent);
  animation:ldin .25s ease .3s forwards,shimmer 2s steps(10,end) .3s infinite}
:root[data-skin="receipt"] .skelrows>.skel{animation:r4-rc-print 525ms steps(7,end) backwards;animation-delay:calc(var(--st,0) * 88ms)}
/* toast: fed out of the slot on a stepper motor, torn off when it goes */
:root[data-skin="receipt"] .toast{animation:r4-rc-toast-in 950ms var(--sk-ease-feed) both}
:root[data-skin="receipt"] .toast.is-shown{animation:none}
:root[data-skin="receipt"] .toast.is-out{animation:r4-rc-tear-up 525ms var(--sk-ease-in) forwards}
@keyframes r4-rc-toast-in{from{transform:translateY(34px);opacity:0}}
@keyframes r4-rc-tear-up{to{transform:translateY(-120%) rotate(2deg);opacity:0}}
/* a sheet is torn off: a tug, then it drops away */
:root[data-skin="receipt"] #app>.scrim.is-closing .sheet{animation:r4-rc-tear 650ms var(--sk-ease-in) forwards}
@keyframes r4-rc-tear{0%{transform:none}22%{transform:translateY(5px) rotate(-1.2deg)}100%{transform:translate(-40px,110%) rotate(-9deg);opacity:0}}

/* ============== نئو بروتال: cardboard and a hard shadow =============== */
:root[data-skin="brutal"] :is(.nav-fresh,.data-fresh) :is(.list>.li,.list>.rowcard,.list>.stgrp,tbody>tr,.bento>.tile,.choices>.choice,.skinpick>.skinopt,.amtchips>.amtchip,.locchips>.locchip),
:root[data-skin="brutal"] .scrim:not(.is-stay):not(.is-closing) :is(.list>.li,.list>.rowcard,tbody>tr,.choices>.choice,.skinpick>.skinopt,.amtchips>.amtchip,.locchips>.locchip){
  animation:nb-drop 600ms var(--nb-spring) backwards;animation-delay:calc(var(--st,0) * 56ms)}
:root[data-skin="brutal"] :is(.nav-fresh,.data-fresh) .meter>i,:root[data-skin="brutal"] .scrim:not(.is-stay):not(.is-closing) .meter>i{
  animation:r4-fill 975ms var(--nb-settle) 188ms backwards}
/* press INTO the shadow (70 ms, linear), spring back (260 ms) */
:root[data-skin="brutal"] :is(.amtchip,.pill--btn,.rowcard,.locrow,.skinopt,.li--btn,.tok){transition:transform 325ms var(--nb-spring)}
:root[data-skin="brutal"] :is(.amtchip,.pill--btn,.rowcard,.locrow,.skinopt,.li--btn,.tok):active{transform:translate(-2px,2px);transition:transform 88ms linear}
:root[data-skin="brutal"] .is-picked{animation:r4-nb-pop 650ms var(--nb-pop)}
@keyframes r4-nb-pop{45%{transform:scale(1.08) rotate(-1deg)}}
/* ka-chunk: the figure drops into its shadow once it lands */
:root[data-skin="brutal"] .cnum.is-bumped{animation:r4-nb-thunk 575ms var(--nb-spring)}
@keyframes r4-nb-thunk{28%{transform:translate(-3px,3px)}}

:root[data-skin="brutal"] .odo--go .odo__reel{transition:transform 975ms var(--nb-settle);transition-delay:calc(var(--k,0) * 35ms)}
/* the spinner is a chunky block tumbling over its own shadow */
:root[data-skin="brutal"] .spin{width:13px;height:13px;border:2.5px solid #16140F;border-radius:3px;background:#FFC53D;
  box-shadow:-3px 3px 0 0 #16140F;animation:ldin .25s ease .3s forwards,r4-nb-tumble 1125ms var(--nb-spring) infinite}
:root[data-skin="brutal"] .btn--pri .spin{background:#FFFFFF}
@keyframes r4-nb-tumble{0%{transform:rotate(0)}30%{transform:translate(-2px,2px) rotate(0)}70%,100%{transform:rotate(90deg)}}
/* skeleton = hazard tape crawling under the dashed card */
:root[data-skin="brutal"] .skel::after{inset:0 0 0 -24px;background:repeating-linear-gradient(-45deg,rgba(22,20,15,.12) 0 6px,transparent 6px 12px);
  animation:ldin .25s ease .3s forwards,r4-nb-crawl 1.375s linear .3s infinite}
@keyframes r4-nb-crawl{from{transform:translateX(0)}to{transform:translateX(17px)}}
:root[data-skin="brutal"] .skelrows>.skel{animation:nb-drop 600ms var(--nb-spring) backwards;animation-delay:calc(var(--st,0) * 75ms)}
/* toast: pops in tilted, flicks out */
:root[data-skin="brutal"] .toast{animation:r4-nb-toast-in 700ms var(--nb-pop) both}
:root[data-skin="brutal"] .toast.is-shown{animation:none}
:root[data-skin="brutal"] .toast.is-out{animation:r4-nb-toast-out 300ms var(--nb-ease-in) forwards}
@keyframes r4-nb-toast-in{from{opacity:0;transform:translateY(34px) rotate(-5deg) scale(.9)}30%{opacity:1}to{opacity:1;transform:none}}
@keyframes r4-nb-toast-out{to{opacity:0;transform:translate(-30px,10px) rotate(-4deg)}}
/* a sheet falls out of its shadow */
:root[data-skin="brutal"] #app>.scrim.is-closing .sheet{animation:r4-nb-out 375ms var(--nb-ease-in) forwards}
@keyframes r4-nb-out{to{opacity:0;transform:translate(-14px,48px) rotate(3deg)}}
@media (max-width:860px){
  :root[data-skin="brutal"] #app>.scrim.is-closing .sheet{animation:r4-nb-sheet-down 400ms var(--nb-ease-in) forwards}
  :root[data-skin="receipt"] #app>.scrim.is-closing .sheet{animation:r4-rc-tear 700ms var(--sk-ease-in) forwards}
}
@keyframes r4-nb-sheet-down{to{transform:translateY(105%)}}

@media (prefers-reduced-motion:reduce){
  .odo--go .odo__reel{transition:none}
  .cnum.is-bumped,.cnum.is-bumped::after,.is-picked{animation:none}
}

/* 🔐 round 4: the TOTP setup's two inline style= attributes (dropped by the
   nonce CSP, so the backup-code grid and the QR box rendered unstyled) */
.totpcodes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
.qrbox.qrbox--totp{max-width:232px;margin:0 auto;background:#fff;border-radius:12px;padding:8px}

/* ============================================================
   📊 ROUND 4 · D3 — the owner's dashboard charts (1405/07/04).
   «۴ تا ۵ نمودار دیگه … حواست تم بخورن». Plain boxes sized through the
   CSSOM (data-w / data-h), coloured from the skin tokens (--c0..--c5,
   --ok/--warn/--bad), entering ONCE (the round-4 gate).
   ============================================================ */
.dgrid{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr))}
.grid2--m1{gap:0 var(--s3)}
@media (max-width:560px){.grid2.grid2--m1{grid-template-columns:1fr}}
.linkish{background:none;border:0;padding:0;font:inherit;color:inherit;cursor:pointer;text-align:start;display:inline-flex;align-items:center;gap:6px;min-width:0}
.linkish:hover{text-decoration:underline}
.svc--xs{width:20px;height:20px;border-radius:6px;margin-inline-end:6px}
.svc--xs svg,.svc--xs img{width:12px;height:12px}
.legend--row{flex-direction:row;flex-wrap:wrap;gap:6px 14px;margin:0 0 var(--s3)}
.legend--row>div{font-size:12px;color:var(--ink-3)}
.st-ok{background:var(--ok)}.st-warn{background:var(--warn)}.st-bad{background:var(--bad)}
/* the donut */
.donutwrap{display:grid;grid-template-columns:150px 1fr;gap:var(--s4);align-items:center}
@media (max-width:420px){.donutwrap{grid-template-columns:1fr;justify-items:center}.donutwrap .legend{width:100%}}
.donut{width:150px;height:150px;overflow:visible}
.donut__track{fill:none;stroke:var(--sunk);stroke-width:16}
.donut__s{fill:none;stroke-width:16;stroke-linecap:butt;transform-box:view-box;transform-origin:60px 60px}
.donut__s.s-c1{stroke:var(--c1)}.donut__s.s-c2{stroke:var(--c2)}.donut__s.s-c3{stroke:var(--c3)}
.donut__s.s-c0{stroke:var(--c0)}.donut__s.s-c4{stroke:var(--c4)}.donut__s.s-c5{stroke:var(--c5)}
.donut__v{font-size:19px;font-weight:800;fill:var(--ink)}
.donut__u{font-size:11px;fill:var(--ink-3)}
.legend--donut>div.is-zero{opacity:.55}
.legend--donut b{color:var(--ink);font-weight:700}
/* twin columns (money in) */
.bars--twin .tw{display:flex;align-items:flex-end;justify-content:center;gap:1px;width:100%;max-width:22px}
.bars--twin .tw>i{flex:1 1 0;display:block;border-radius:3px 3px 1px 1px;min-width:2px}
.k-dep{background:var(--c4)}.k-sale{background:var(--c1)}
/* horizontal bars */
.hbars{display:flex;flex-direction:column;gap:10px}
.hb{display:grid;grid-template-columns:minmax(0,9.5em) minmax(0,1fr) auto;align-items:center;gap:4px 10px;font-size:13px}
.hb__l{display:inline-flex;align-items:center;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.hb__t{display:flex;height:10px;border-radius:999px;background:var(--sunk);overflow:hidden}
.hb__t--stack{gap:1px}
.hb__t--thin{height:6px}
.hb__f{display:block;height:100%;border-radius:999px}
.hb__t--stack .hb__f{border-radius:0}
.hb__v{font-weight:700;white-space:nowrap}
.hb__v--sub{font-weight:500;color:var(--ink-3);font-size:12px}
.hb__s{grid-column:2/-1;font-size:11.5px;color:var(--ink-3);margin-top:-4px}
.hb__rank{display:inline-grid;place-items:center;min-width:1.6em;height:1.6em;border-radius:6px;background:var(--sunk);font-size:11px;font-weight:700}
.hb--pair{row-gap:5px}
.hb--pair .hb__t--thin{grid-column:2}
@media (max-width:420px){.hb{grid-template-columns:minmax(0,7em) minmax(0,1fr) auto}}
/* the funnel */
.funnelgrid{display:grid;gap:var(--s5);grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}
@media (max-width:760px){.funnelgrid{grid-template-columns:1fr}}
.funnel{display:flex;flex-direction:column;gap:8px}
.funnel__s{display:grid;grid-template-columns:minmax(0,11em) minmax(0,1fr) auto;align-items:center;gap:10px;font-size:13px}
.funnel__t{display:flex;height:22px;border-radius:6px;background:var(--sunk);overflow:hidden}
.funnel__f{display:block;height:100%;background:var(--brand);border-radius:6px;opacity:.85}
.funnel__s:nth-child(2) .funnel__f{opacity:.75}.funnel__s:nth-child(3) .funnel__f{opacity:.65}
.funnel__s:nth-child(4) .funnel__f{opacity:.55;background:var(--ok)}.funnel__s:nth-child(5) .funnel__f{background:var(--ok)}
@media (max-width:420px){.funnel__s{grid-template-columns:minmax(0,8em) minmax(0,1fr) auto}}

/* entering once: columns grow up, bars fill from the start, arcs land in turn */
.bars i,.bars--twin .tw>i{transform-origin:50% 100%}
:root[data-skin="receipt"] .bars i,:root[data-skin="brutal"] .bars i{animation:none}
:is(.nav-fresh,.data-fresh) .bars i,:is(.nav-fresh,.data-fresh) .bars--twin .tw>i{animation:r4-grow-y 900ms cubic-bezier(.2,.8,.2,1) backwards;
  animation-delay:calc(var(--st,0) * 22ms + 100ms)}
:is(.nav-fresh,.data-fresh) :is(.hb__f,.funnel__f){transform-origin:100% 50%;animation:r4-fill 1025ms cubic-bezier(.2,.8,.2,1) backwards;
  animation-delay:calc(var(--st,0) * 69ms + 150ms)}
:is(.nav-fresh,.data-fresh) .donut__s{animation:r4-arc 800ms cubic-bezier(.2,.8,.2,1) backwards}
:is(.nav-fresh,.data-fresh) .donut__s:nth-child(2){animation-delay:112ms}
:is(.nav-fresh,.data-fresh) .donut__s:nth-child(3){animation-delay:225ms}
:is(.nav-fresh,.data-fresh) .donut__s:nth-child(4){animation-delay:338ms}
:is(.nav-fresh,.data-fresh) .donut__s:nth-child(5){animation-delay:450ms}
:is(.nav-fresh,.data-fresh) .donut__s:nth-child(6){animation-delay:562ms}
:is(.bars,.hbars,.funnel)>:nth-child(2){--st:1}:is(.bars,.hbars,.funnel)>:nth-child(3){--st:2}
:is(.bars,.hbars,.funnel)>:nth-child(4){--st:3}:is(.bars,.hbars,.funnel)>:nth-child(5){--st:4}
:is(.bars,.hbars,.funnel)>:nth-child(6){--st:5}:is(.bars,.hbars,.funnel)>:nth-child(7){--st:6}
:is(.bars,.hbars,.funnel)>:nth-child(8){--st:7}:is(.bars,.hbars,.funnel)>:nth-child(n+9){--st:8}
@keyframes r4-grow-y{from{transform:scaleY(0)}}
@keyframes r4-arc{from{opacity:0;transform:rotate(-24deg) scale(.92)}}

/* ============== receipt: dot-matrix bars, dashed rulings ============== */
:root[data-skin="receipt"] .hb__t,:root[data-skin="receipt"] .funnel__t{border-radius:0;background:#F2F2ED;box-shadow:inset 0 0 0 1px #DCDCD3}
:root[data-skin="receipt"] .hb__f,:root[data-skin="receipt"] .funnel__f,:root[data-skin="receipt"] .bars--twin .tw>i{border-radius:0}
:root[data-skin="receipt"] .hb__f.bg-c1,:root[data-skin="receipt"] .funnel__f{background:repeating-linear-gradient(to left,#1B1D1E 0 3px,#0000 3px 4.5px)}
:root[data-skin="receipt"] .hb__f.bg-c4{background:repeating-linear-gradient(to left,#3A3FA5 0 3px,#0000 3px 4.5px)}
:root[data-skin="receipt"] .k-dep{background:radial-gradient(circle,#3A3FA5 1.1px,#0000 1.3px) 0 0/3px 3px}
:root[data-skin="receipt"] .k-sale{background:radial-gradient(circle,#1B1D1E 1.1px,#0000 1.3px) 0 0/3px 3px}
:root[data-skin="receipt"] .hb{border-bottom:1px dashed #DCDCD3;padding-bottom:8px}
:root[data-skin="receipt"] .hb__rank{border-radius:0;background:#FBF4A6}
:root[data-skin="receipt"] .donut__track{stroke:#E6E6DE;stroke-dasharray:2 2}
:root[data-skin="receipt"] .donut__s{stroke-width:14}
:root[data-skin="receipt"] .donut__v{font-family:var(--sk-dotface);font-weight:700}
:root[data-skin="receipt"] :is(.nav-fresh,.data-fresh) :is(.hb__f,.funnel__f){animation:r4-fill 1375ms steps(16,end) 188ms backwards}
:root[data-skin="receipt"] :is(.nav-fresh,.data-fresh) .bars i,:root[data-skin="receipt"] :is(.nav-fresh,.data-fresh) .bars--twin .tw>i{
  animation:rc-bar 1375ms var(--sk-spring-soft) backwards;animation-delay:calc(var(--st,0) * 56ms + 250ms)}

/* ============== neo-brutal: thick ink, hard offsets =================== */
:root[data-skin="brutal"] .hb__t,:root[data-skin="brutal"] .funnel__t{height:16px;border:2px solid #16140F;background:#FFFFFF;border-radius:999px}
:root[data-skin="brutal"] .hb__t--thin{height:10px}
:root[data-skin="brutal"] .hb__f,:root[data-skin="brutal"] .funnel__f{border-radius:0;border-inline-end:2px solid #16140F;opacity:1}
:root[data-skin="brutal"] .funnel__t{height:24px;border-radius:8px;box-shadow:-3px 3px 0 0 #16140F}
:root[data-skin="brutal"] .funnel__f{background:#FFC53D}
:root[data-skin="brutal"] .funnel__s:nth-child(n+4) .funnel__f{background:#7CC45A}
:root[data-skin="brutal"] .bars--twin .tw>i{border:2px solid #16140F;border-bottom:0;border-radius:3px 3px 0 0}
:root[data-skin="brutal"] .k-dep{background:#8ECFFF}
:root[data-skin="brutal"] .k-sale{background:#FFC53D}
:root[data-skin="brutal"] .legend em.k-dep,:root[data-skin="brutal"] .legend em.k-sale{box-shadow:inset 0 0 0 1.5px #16140F}
:root[data-skin="brutal"] .hb__rank{border:2px solid #16140F;background:#FFC53D;border-radius:6px}
:root[data-skin="brutal"] .donut{filter:drop-shadow(-4px 4px 0 #16140F)}
:root[data-skin="brutal"] .donut__track{stroke:#FFFFFF}
:root[data-skin="brutal"] .donut__s{stroke-width:18}
:root[data-skin="brutal"] .donut__v{font-family:var(--nb-display);font-weight:400;font-size:19px}
:root[data-skin="brutal"] .st-ok{background:#7CC45A}
:root[data-skin="brutal"] .st-warn{background:#FFC53D}
:root[data-skin="brutal"] .st-bad{background:#FF5A36}
:root[data-skin="brutal"] :is(.nav-fresh,.data-fresh) :is(.hb__f,.funnel__f){animation:r4-fill 975ms var(--nb-settle) 188ms backwards}
:root[data-skin="brutal"] :is(.nav-fresh,.data-fresh) .bars i,:root[data-skin="brutal"] :is(.nav-fresh,.data-fresh) .bars--twin .tw>i{
  animation:nb-grow-y 875ms var(--nb-settle) backwards;animation-delay:calc(var(--st,0) * 35ms + 150ms)}
:root[data-skin="brutal"] :is(.nav-fresh,.data-fresh) .donut__s{animation:r4-nb-pop 700ms var(--nb-pop) backwards}
@media (prefers-reduced-motion:reduce){.bars i,.bars--twin .tw>i,.hb__f,.funnel__f,.donut__s{animation:none!important}}


/* ============================================================
   ADDENDUM 2 (1405/07/04) · calm renders + the skins' own focus
   ============================================================ */
/* A render that is not an entrance replays nothing (app.js sets .calm). */
#app.calm :not(.scrim:not(.is-stay),.scrim:not(.is-stay) *,.mr-scrim:not(.is-stay),.mr-scrim:not(.is-stay) *,
  .is-closing,.is-closing *,.toast,.spin,.livespin,.is-picked,.is-bumped){animation:none!important}
/* an open sheet redrawn stays put in every skin (the skins' own sheet
   animation used to out-rank .is-stay by coming later in the file) */
#app .scrim.is-stay:not(.is-closing),#app .scrim.is-stay:not(.is-closing) .sheet,
#app .mr-scrim.is-stay,#app .mr-scrim.is-stay .sheet{animation:none}

/* «روی اسم که کلیک می‌کنم دورش یه کادر آبی زشت از گذشته میاد»: a text box
   is :focus-visible even on a tap, so the browser-style outline came back on
   every field. The field's own box (.input:focus-within) is the focus now;
   mouse/touch focus never draws an outline; the keyboard ring is the skin's. */
:focus:not(:focus-visible){outline:none}
.input :is(input,select,textarea),.input :is(input,select,textarea):focus,.input :is(input,select,textarea):focus-visible,
.ta:focus-visible,.search input:focus-visible{outline:none!important}
:root[data-skin="receipt"] :is(.btn,.amtchip,.pill--btn,.choice,.locrow,.skinopt,.rowcard,.li--btn,.tok,.tab,.navitem):focus-visible{
  outline:2px dashed #1B1D1E;outline-offset:3px;box-shadow:0 0 0 4px rgba(246,234,75,.85)}
:root[data-skin="brutal"] :focus-visible{outline:3px solid #16140F;outline-offset:3px}
:root[data-skin="brutal"] :is(.btn,.amtchip,.pill--btn,.choice,.locrow,.skinopt,.rowcard,.li--btn,.tok):focus-visible{
  outline:3px solid #16140F;outline-offset:3px;background-color:#FFF0C4}
:root[data-skin="brutal"] .btn--pri:focus-visible{background-color:#FFC53D}
:root[data-skin="brutal"] .side :focus-visible,:root[data-skin="brutal"] .bcard :focus-visible{outline-color:#FFC53D}
:root:not([data-skin]) :is(.amtchip,.choice,.locrow,.skinopt,.rowcard,.tok):focus-visible{outline:2px solid var(--brand);outline-offset:2px}


/* ============================================================
   🧮 ADDENDUM 3 (1405/07/04): wizard presets + builder, the ladder's
   «نامحدود» and «ویژه»
   ============================================================ */
.plangroup{display:flex;flex-direction:column;gap:6px;margin-bottom:var(--s3)}
.plangroup__t{font-size:12px;font-weight:700;color:var(--ink-3)}
.wzb__row{display:grid;grid-template-columns:3.2em minmax(0,1fr);grid-template-areas:"k v" "r r";align-items:center;gap:4px 10px}
.wzb__k{grid-area:k;font-size:13px;color:var(--ink-3)}
.wzb__v{grid-area:v;font-weight:800;font-size:16px;justify-self:end;font-variant-numeric:tabular-nums}
.wzb__row .range{grid-area:r}
.range{-webkit-appearance:none;appearance:none;width:100%;height:32px;background:transparent;touch-action:pan-y;cursor:pointer}
.range::-webkit-slider-runnable-track{height:8px;border-radius:999px;background:var(--sunk);border:1px solid var(--line)}
.range::-moz-range-track{height:8px;border-radius:999px;background:var(--sunk);border:1px solid var(--line)}
.range::-webkit-slider-thumb{-webkit-appearance:none;width:26px;height:26px;margin-top:-10px;border-radius:50%;background:var(--brand);
  border:3px solid var(--card);box-shadow:0 1px 4px rgba(0,0,0,.3)}
.range::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:var(--brand);border:3px solid var(--card)}
.range:focus-visible{outline:2px solid var(--brand);outline-offset:3px}
.wzb.is-on{border-color:var(--brand)}
:root[data-skin="receipt"] .range::-webkit-slider-runnable-track{border-radius:0;background:repeating-linear-gradient(to left,#1B1D1E 0 2px,#0000 2px 5px) center/100% 2px no-repeat,#F2F2ED;border:1px dashed #C9CBC3}
:root[data-skin="receipt"] .range::-webkit-slider-thumb{border-radius:4px;background:#1B1D1E;border:3px solid #F6EA4B;box-shadow:0 2px 0 #676C69}
:root[data-skin="receipt"] .wzb.is-on{box-shadow:inset 0 0 0 2px #1B1D1E}
:root[data-skin="brutal"] .range::-webkit-slider-runnable-track{height:12px;border:2.5px solid #16140F;background:#FFFFFF}
:root[data-skin="brutal"] .range::-webkit-slider-thumb{width:30px;height:30px;margin-top:-11px;border-radius:8px;background:#FFC53D;
  border:3px solid #16140F;box-shadow:-3px 3px 0 0 #16140F}
:root[data-skin="brutal"] .wzb.is-on{box-shadow:-6px 6px 0 0 #FF5A36}
.chk{display:inline-flex;align-items:center;gap:5px;white-space:nowrap;cursor:pointer;margin-top:4px}
/* the special rung */
.rung--special{position:relative;border-width:2px;border-color:var(--warn);
  background:linear-gradient(135deg,color-mix(in srgb,var(--warn) 16%,var(--card)),var(--card) 70%)}
.rung__ribbon{position:absolute;top:-10px;inset-inline-start:14px;font-size:11px;font-weight:800;padding:2px 10px;border-radius:999px;
  background:var(--warn);color:#fff;letter-spacing:.02em}
.tag--special{background:color-mix(in srgb,var(--warn) 22%,transparent);color:var(--warn);font-weight:800}
:root[data-skin="receipt"] .rung--special{background:#FBF4A6;border:2px dashed #1B1D1E;border-radius:0}
:root[data-skin="receipt"] .rung__ribbon{background:#C21D38;color:#FBFBF8;border-radius:0;transform:rotate(-2deg)}
:root[data-skin="brutal"] .rung--special{background:#FF5A36;border:3px solid #16140F;box-shadow:-8px 8px 0 0 #16140F}
:root[data-skin="brutal"] .rung--special .rung__rate,:root[data-skin="brutal"] .rung--special .rung__meta,:root[data-skin="brutal"] .rung--special .num{color:#16140F}
:root[data-skin="brutal"] .rung__ribbon{background:#FFC53D;color:#16140F;border:2.5px solid #16140F;border-radius:8px;transform:rotate(-3deg)}
:root[data-skin="brutal"] .tag--special{background:#FFFFFF;color:#16140F;border:2px solid #16140F}

/* ===================== PA5 · login / signup polish ======================== */
/* The brand line of the one header every signed-out page shares. */
.brandhead__name{letter-spacing:.01em;unicode-bidi:isolate}
/* The «حداقل ۱۰ کاراکتر» box: a light yellow/orange highlight, from the warn
   tokens, so it follows light, dark and both skins. */
.note--tip{background:var(--warn-weak);border-color:color-mix(in srgb,var(--warn) 45%,transparent);color:var(--ink)}
.note--tip svg{color:var(--warn)}
:root[data-skin="receipt"] .note--tip{background:#FBF4A6;border-inline-start-color:#F6EA4B;color:#1B1D1E}
:root[data-skin="brutal"] .note--tip{background:#FFE08A;color:#16140F}
/* «وصل کردن تلگرام»: the primary action of every waiting surface. */
.tgconnect{display:flex;flex-direction:column;gap:8px}
.tgconnect>b{line-height:1.7}

/* ===================== 📋 reminders («یادآورها», 1405/07/11) ================= */
/* Built from the existing card / pill / chiprow pieces, so light, dark and both
   skins come along for free; only the few lines below are new. */
.rmd + .rmd{margin-top:var(--s3)}
.rmd__who{min-width:0}
.rmd__who>b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rmd__line{margin:0;font-size:14px;line-height:1.85;color:var(--ink)}
.rmd__note{overflow-wrap:anywhere}
/* the four follow-ups always fit side by side, even at 360 px: equal columns, two-line labels allowed */
.rmd__fu{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}
.rmd__fu>.pill{justify-content:center;text-align:center;white-space:normal;line-height:1.35;padding-inline:4px;font-size:12px}
.rmd__ed{display:flex;flex-direction:column;gap:var(--s2)}
.rmd--done{cursor:default}
.rmd--done .rowcard__m>span{white-space:normal}
