/* ──────────────────────────────────────────────────────────────────────────
   NarniaPay design language for the VPN panel.

   Both panels already style everything through CSS custom properties, so the
   whole surface can be re-skinned by redefining the tokens instead of touching
   any markup. Values are lifted from narniapay-vite/src/styles/global.css and
   src/ui/tokens.js so the two products read as one family.

   Deliberately dark-only, like the panel is today: NarniaPay's own default is
   light, but flipping this panel to light for anyone whose OS prefers it would
   be a surprise nobody asked for. The light block is written and ready — it is
   opt-in via <html data-theme="light">.
   ────────────────────────────────────────────────────────────────────────── */

:root{
  /* ground + surfaces (NarniaPay dark) */
  --bg:#0c0f14;
  --bg2:#161a22;
  --card:#151a23;
  --line:rgba(255,255,255,.07);
  --line2:rgba(255,255,255,.11);

  /* text ramp */
  --txt:#e8ecf4;
  --muted:#a0acc2;
  --faint:#6f7d93;

  /* NarniaPay's green replaces the old indigo. #1a7a42 is tuned for a light
     ground; on this dark one it drops under 3:1, so the accent is lifted into
     the same family and the deep tone is kept for fills. */
  --acc:#2ea55c;
  --acc2:#34c759;
  --acc-deep:#1a7a42;

  /* semantic — iOS system colors */
  --ok:#34c759;
  --warn:#ff9500;
  --bad:#ff453a;
  --info:#32ade6;
  --violet:#af52de;

  --shadow:0 2px 20px rgba(0,0,0,.3),0 0 1px rgba(0,0,0,.4);
  --shadow2:0 8px 40px rgba(0,0,0,.4),0 0 1px rgba(0,0,0,.5);

  /* iOS corner scale */
  --r-xs:8px; --r-sm:10px; --r-md:14px; --r-lg:18px; --r-xl:22px; --r-pill:999px;

  /* UIView spring */
  --ease:cubic-bezier(.32,.72,0,1);
  --spring:cubic-bezier(.34,1.56,.64,1);
}

:root[data-theme="light"]{
  --bg:#ecebed; --bg2:#e3e2e8; --card:rgba(255,255,255,.62);
  --line:rgba(0,0,0,.06); --line2:rgba(0,0,0,.1);
  --txt:#1c1c1e; --muted:#3a3a3c; --faint:#6e6e73;
  --acc:#1a7a42; --acc2:#1a8a4d; --acc-deep:#146235;
  --ok:#1a8a4d; --warn:#ff9500; --bad:#ff3b30;
  --shadow:0 2px 20px rgba(0,0,0,.06),0 0 1px rgba(0,0,0,.08);
  --shadow2:0 8px 40px rgba(0,0,0,.08),0 0 1px rgba(0,0,0,.1);
}

/* Vazirmatn is already self-hosted by base.html; just make it win over Inter,
   which has no Persian coverage and was forcing a fallback mid-sentence. */
body,button,input,select,textarea{
  font-family:'Vazirmatn',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
}

/* iOS type scale: tighter tracking as size grows */
h1{font-size:28px;font-weight:800;letter-spacing:-.4px}
h2{font-size:24px;font-weight:800;letter-spacing:-.3px}
h3{font-size:20px;font-weight:800;letter-spacing:-.2px}

/* rounder, softer surfaces */
.card,.acct,.fnode,.locrow{border-radius:var(--r-lg)}
.btn,.tab,.fbtn,.fsort,input,select{border-radius:var(--r-sm)}
.chip,.fpill,.locpill,.badge,.tw-tab{border-radius:var(--r-pill)}

/* accent surfaces follow the green */
.btn.primary,.btn.green,.tab.on,.tw-tab.on,.fbtn.on{
  background:var(--acc);border-color:var(--acc);color:#fff;
}
.adm-nav.active{
  background:linear-gradient(135deg,var(--acc),var(--acc2));
  box-shadow:0 5px 16px -5px rgba(46,165,92,.55);
}

/* the tap spring that makes the iOS app feel native */
@media (prefers-reduced-motion:no-preference){
  button,.btn,[role="button"],.tab,.tw-tab,.fbtn,.adm-nav,.tab-btn{
    transition:transform .28s var(--spring),background .18s var(--ease),
               border-color .18s var(--ease),color .18s var(--ease);
    touch-action:manipulation;
  }
  button:active,.btn:active,[role="button"]:active,.tab:active,
  .tw-tab:active,.fbtn:active,.adm-nav:active,.tab-btn:active{
    transform:scale(.95);transition:transform .09s ease-out;
  }
  button:disabled:active,.btn:disabled:active{transform:none}
}

/* keyboard users get the same affordance as pointer users */
:focus-visible{outline:2px solid var(--acc2);outline-offset:2px}

/* ══════════════════════════════════════════════════════════════════════════
   Design system, applied across both apps (2026-08-18).

   The panel styles everything through a small class vocabulary — .card, .btn,
   .field, .badge, details/summary — so restyling it here reaches every view of
   both apps without touching 2,500 lines of template. The shapes come from the
   Clients/Create mockup: one card instead of many, folds that state what they
   hide, chips for choices, and an action bar that stays reachable.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── surfaces ──────────────────────────────────────────────────────────── */
.card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);
  box-shadow:var(--shadow);padding:16px;margin-bottom:14px;
}
.card h3{font-size:15px;font-weight:800;letter-spacing:-.2px;margin:0 0 10px}
.card > p{font-size:12.5px;color:var(--faint);margin:0 0 12px}

/* ── controls: one resting style, one accent style ─────────────────────── */
.btn{
  border:1px solid var(--line2);background:var(--bg2);color:var(--txt);
  font-weight:700;font-size:13.5px;padding:10px 16px;border-radius:var(--r-md);
  min-height:40px;display:inline-flex;align-items:center;justify-content:center;
  gap:7px;cursor:pointer;
}
.btn:hover{border-color:var(--line2);background:var(--card)}
.btn.sm{font-size:12.5px;padding:7px 12px;min-height:34px;border-radius:var(--r-sm)}
.btn.primary,.btn.green{background:var(--acc);border-color:transparent;color:#fff}
.btn.red,.btn.b-bad{background:var(--bad);border-color:transparent;color:#fff}
.btn:disabled{opacity:.45;cursor:not-allowed}

/* ── inputs ────────────────────────────────────────────────────────────── */
input:not([type=checkbox]):not([type=radio]),select,textarea{
  background:var(--bg2);border:1px solid var(--line2);color:var(--txt);
  border-radius:var(--r-md);padding:10px 12px;font-size:14px;min-height:42px;
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease);
}
input:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(46,165,92,.18);
}
.field label{font-size:11.5px;font-weight:700;color:var(--muted);margin-bottom:5px;display:block}

/* ── folds: a summary must say what opening it would reveal ────────────── */
details.card,details.create{border-radius:var(--r-lg);overflow:hidden}
summary{
  cursor:pointer;list-style:none;min-height:44px;display:flex;align-items:center;
  gap:9px;padding:10px 12px;user-select:none;font-weight:700;font-size:13.5px;
}
summary::-webkit-details-marker{display:none}
summary:hover{background:var(--bg2)}
details[open] > summary{border-bottom:1px solid var(--line)}

/* ── badges + chips ────────────────────────────────────────────────────── */
.badge{font-size:10.5px;padding:3px 9px;font-weight:700}
.chip{
  border:1px solid var(--line2);background:var(--bg2);color:var(--muted);
  font-weight:700;font-size:12.5px;padding:7px 13px;border-radius:var(--r-pill);
  cursor:pointer;min-height:34px;display:inline-flex;align-items:center;
}
.chip.on{background:var(--acc);border-color:transparent;color:#fff}

/* ── numbers line up; a Persian ۰ is a dot, so never separate with "·" ──── */
.num,.mono,.k,td.n{font-variant-numeric:tabular-nums}
.sep{display:inline-block;margin:0 7px;color:var(--faint);opacity:.45;font-weight:400}

/* ══ mobile ════════════════════════════════════════════════════════════════
   The audit found 124 controls under 30px tall — unhittable with a thumb.
   Apple's floor is 44pt; 34 is the smallest that still works for a dense
   secondary control, so nothing lands under it. */
@media (max-width:700px){
  .wrap{padding:12px}
  .card{padding:13px;border-radius:var(--r-lg);margin-bottom:11px}
  .btn{min-height:44px;font-size:14px}
  .btn.sm{min-height:36px;padding:8px 13px}
  .fbtn,.tab-btn,.tw-tab,.vtb,.tab{min-height:38px;padding-top:8px;padding-bottom:8px}
  summary{min-height:48px}
  input:not([type=checkbox]):not([type=radio]),select{min-height:46px;font-size:16px}
  /* 16px stops iOS Safari zooming the whole page when a field takes focus */
  .topbar a,.topbar button,a.muted,.who a{
    min-height:36px;display:inline-flex;align-items:center;
  }
  .mrow{gap:8px}
  .mrow .btn{flex:1}
}

/* ══ desktop ═══════════════════════════════════════════════════════════════
   A fold is a small-screen affordance. With room on a laptop the choices sit
   open, so the common edit costs no clicks. */
@media (min-width:701px){
  .adm-view[data-view="create"] form{max-width:none}
  details.create[open] > summary{position:sticky;top:0;background:var(--card);z-index:2}
  .field-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}
}

/* the usage-card unit toggle: styling moved off inline attributes so it can be
   sized for a thumb like every other control */
.uglb{
  border:0;background:transparent;color:var(--muted);font-weight:700;font-size:12px;
  padding:5px 11px;border-radius:6px;cursor:pointer;min-height:30px;
}
@media (max-width:700px){ .uglb{min-height:34px;padding:7px 13px} }

/* ══════════════════════════════════════════════════════════════════════════
   nk-* — the components from the Clients/Create mockup, prefixed so they can
   sit beside the panel's existing vocabulary without either one bleeding into
   the other. Shapes and behaviour match the approved prototype exactly.
   ══════════════════════════════════════════════════════════════════════════ */

.nk-card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);
  padding:13px 14px;display:grid;gap:11px;max-width:640px;margin:0 auto;
}
.nk-lbl{font-size:11px;font-weight:700;color:var(--faint);margin-bottom:5px}
.nk-2col{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.nk-mono{font-family:var(--mono,ui-monospace,Menlo,monospace);font-size:13px}

.nk-inp{
  display:flex;align-items:center;gap:7px;background:var(--bg2);
  border:1px solid var(--line2);border-radius:var(--r-md);padding:0 10px;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease);
}
.nk-inp:focus-within{border-color:var(--acc);box-shadow:0 0 0 3px rgba(46,165,92,.18)}
.nk-inp.bad{border-color:var(--bad);box-shadow:0 0 0 3px rgba(255,69,58,.15)}
.nk-inp input:not([type=checkbox]):not([type=radio]){
  flex:1;min-width:0;background:none;border:0;outline:none;color:var(--txt);
  font-family:inherit;font-size:14px;padding:9px 0;min-height:0;box-shadow:none;
  border-radius:0;
}
.nk-inp input:not([type=checkbox]):not([type=radio]):focus{box-shadow:none;border:0}
.nk-ico{
  border:0;background:none;color:var(--faint);cursor:pointer;padding:4px;
  border-radius:7px;flex:none;display:grid;place-items:center;min-height:30px;
}
.nk-ico:hover{color:var(--txt);background:var(--card)}
.nk-ico svg{width:15px;height:15px}
.nk-err{font-size:11px;color:var(--bad);margin-top:4px;display:none}
.nk-err.on{display:block}

.nk-chips{display:flex;gap:6px;flex-wrap:wrap}
.nk-chip{
  border:1px solid var(--line2);background:var(--bg2);color:var(--muted);
  border-radius:var(--r-pill);font-family:inherit;font-size:12px;font-weight:700;
  padding:6px 12px;cursor:pointer;min-height:32px;display:inline-flex;align-items:center;
  transition:transform .25s var(--spring),background .18s var(--ease);
}
.nk-chip:active{transform:scale(.94)}
.nk-chip.on{background:var(--acc);border-color:transparent;color:#fff}

/* a fold whose closed state states everything the open state would show */
.nk-fold{border:1px solid var(--line);border-radius:13px;overflow:hidden;background:var(--bg2)}
.nk-fold > summary{
  list-style:none;cursor:pointer;padding:9px 11px;display:flex;align-items:center;
  gap:9px;font-size:12.5px;user-select:none;min-height:40px;font-weight:400;
}
.nk-fold > summary::-webkit-details-marker{display:none}
.nk-fold > summary:hover{background:transparent}
.nk-fold > summary .k{color:var(--faint);flex:none;font-size:11px;font-weight:700}
.nk-fold > summary .v{flex:1;min-width:0;font-weight:700;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.nk-caret{flex:none;color:var(--faint);transition:transform .25s var(--ease)}
.nk-fold[open] > summary .nk-caret{transform:rotate(90deg)}
.nk-fold[open] > summary{border-bottom:1px solid var(--line)}
.nk-foldbody{padding:11px;display:grid;gap:11px}

.nk-step{
  display:flex;align-items:center;background:var(--card);border:1px solid var(--line2);
  border-radius:11px;overflow:hidden;width:max-content;
}
.nk-step button{
  border:0;background:none;color:var(--txt);font-family:var(--mono,monospace);
  font-size:16px;width:36px;height:36px;cursor:pointer;line-height:1;min-height:0;
}
.nk-step button:disabled{color:var(--faint);cursor:not-allowed}
.nk-step button:hover:not(:disabled){background:var(--bg2)}
.nk-step .val{min-width:38px;text-align:center;font-family:var(--mono,monospace);
  font-weight:800;font-size:14px;font-variant-numeric:tabular-nums}

/* four locations as one line of flags, not four rows */
.nk-locline{
  display:flex;align-items:center;gap:9px;padding:8px 11px;border-radius:13px;
  background:var(--bg2);border:1px solid var(--line);font-size:12px;
}
.nk-locline.hot{border-color:rgba(255,159,10,.35);background:rgba(255,159,10,.08)}
.nk-flags{display:flex;gap:5px;flex:none}
.nk-flags span{position:relative;font-size:15px;line-height:1}
.nk-flags span i{
  position:absolute;inset-block-end:-1px;inset-inline-end:-2px;width:6px;height:6px;
  border-radius:99px;border:1.5px solid var(--card);
}
.nk-flags i.ok{background:var(--ok)}
.nk-flags i.warn{background:var(--warn)}
.nk-flags i.idle{background:var(--faint)}
.nk-locline .nk-ltxt{flex:1;min-width:0;color:var(--muted)}
.nk-locline.hot .nk-ltxt{color:var(--warn)}

#nk-warn{
  font-size:11.5px;line-height:1.65;padding:8px 11px;border-radius:11px;
  background:rgba(255,159,10,.13);color:var(--warn);border:1px solid rgba(255,159,10,.25);
}
.nk-sep{display:inline-block;margin:0 7px;color:var(--faint);opacity:.45;font-weight:400}

/* the action bar carries the whole summary */
.nk-actbar{
  display:flex;align-items:center;gap:11px;padding:9px 9px 9px 14px;border-radius:17px;
  margin:11px auto 0;max-width:640px;position:sticky;bottom:8px;z-index:6;
  background:var(--card);border:1px solid var(--line2);box-shadow:var(--shadow2);
}
.nk-count{flex:1;min-width:0;font-size:11.5px;color:var(--muted);line-height:1.45}
.nk-count b{display:block;font-family:var(--mono,monospace);font-size:16px;font-weight:800;color:var(--txt)}
.nk-count span{display:block}
.nk-cta{
  border:0;border-radius:13px;background:var(--acc);color:#fff;flex:none;
  font-family:inherit;font-weight:800;font-size:14px;padding:12px 20px;cursor:pointer;
  min-height:44px;transition:transform .25s var(--spring),opacity .2s;
}
.nk-cta:active{transform:scale(.975)}
.nk-cta:disabled{opacity:.45;cursor:not-allowed}

/* ── desktop: spend the width instead of the height ────────────────────── */
@media (min-width:701px){
  .nk-create{display:grid;grid-template-columns:1fr 268px;gap:12px;align-items:stretch}
  .nk-card{max-width:none;margin:0;gap:10px}
  #nk-fold-lim{background:none;border:0}
  #nk-fold-lim > summary{display:none}
  #nk-fold-lim .nk-foldbody{padding:0;gap:8px}
  #nk-fold-lim .nk-foldbody > div{display:grid;grid-template-columns:78px 1fr;
    align-items:center;gap:10px}
  #nk-fold-lim .nk-foldbody .nk-lbl{margin:0;text-align:end}
  .nk-actbar{position:static;flex-direction:column;align-items:stretch;gap:0;
    padding:15px;border-radius:var(--r-lg);margin:0}
  .nk-count{flex:1;font-size:12px}
  .nk-count b{font-size:30px;letter-spacing:-1.5px;margin-bottom:3px}
  .nk-cta{width:100%;padding:13px;margin-top:14px}
}
@media (max-width:700px){
  .nk-2col{grid-template-columns:1fr}
  .nk-inp input{min-height:0;font-size:16px;padding:11px 0}
  .nk-chip{min-height:34px}
}

/* shared toast */
.nk-toast{
  position:fixed;inset-inline:0;bottom:calc(22px + var(--nk-sab));
  margin:0 auto;width:max-content;max-width:90vw;background:var(--card);
  border:1px solid var(--line2);color:var(--txt);padding:11px 20px;border-radius:999px;
  font-size:13.5px;font-weight:700;box-shadow:var(--shadow2);opacity:0;
  transform:translateY(14px);transition:opacity .3s,transform .3s var(--spring);
  pointer-events:none;z-index:200;
}
.nk-toast.on{opacity:1;transform:translateY(0)}
@media (max-width:700px){ .nk-ico{min-width:38px;min-height:38px} }

/* ══ Clients view ══════════════════════════════════════════════════════════
   Restyled to the mockup's chrome — a search bar and one segmented row of
   filters — without touching the markup, so search, the nine filters, sort,
   bulk-select and CSV all keep working off their existing hooks. */
.adm-view[data-view="clients"] > .card{
  background:transparent;border:0;box-shadow:none;padding:0;
}
.accts-head{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);
  padding:10px 12px;margin-bottom:10px;box-shadow:var(--shadow);
}
.accts-head h3{font-size:14px;margin:0}
.acct-search{
  flex-basis:100%;background:var(--bg2);border:1px solid var(--line2);
  border-radius:var(--r-pill);padding:10px 16px;font-size:14px;
}
.acct-search:focus{border-color:var(--acc);box-shadow:0 0 0 3px rgba(46,165,92,.18)}

/* the filter row becomes one scrollable strip of pills, like the mockup */
.filter-row{
  display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);
  padding:9px 11px;margin-bottom:12px;box-shadow:var(--shadow);
}
.fbtn{
  background:var(--bg2);border:1px solid var(--line2);color:var(--muted);
  border-radius:var(--r-pill);padding:7px 13px;font-size:12.5px;font-weight:700;
  min-height:34px;display:inline-flex;align-items:center;gap:5px;
}
.fbtn.on{background:var(--acc);border-color:transparent;color:#fff}
.fsort{
  background:var(--bg2);border:1px solid var(--line2);border-radius:var(--r-pill);
  padding:7px 13px;font-size:12.5px;font-weight:700;min-height:34px;
}
.view-toggle{display:flex;gap:3px;padding:3px;border-radius:var(--r-pill);
  background:var(--bg2);border:1px solid var(--line2)}
.vtb{border:0;background:none;color:var(--muted);border-radius:var(--r-pill);
  padding:6px 11px;cursor:pointer;min-height:32px}
.vtb.on{background:var(--acc);color:#fff}
.vtb svg{width:15px;height:15px;display:block}

/* account cards pick up the mockup's card language */
.accts{display:grid;gap:10px}
.acct{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow);overflow:hidden;
}
.acct:hover{border-color:var(--line2)}

@media (max-width:700px){
  .filter-row{
    flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;
    /* fade the trailing edge so a clipped pill reads as "more this way"
       rather than as a broken layout */
    -webkit-mask-image:linear-gradient(to left,transparent 0,#000 26px);
    mask-image:linear-gradient(to left,transparent 0,#000 26px);
  }
  html[dir="ltr"] .filter-row{
    -webkit-mask-image:linear-gradient(to right,transparent 0,#000 26px);
    mask-image:linear-gradient(to right,transparent 0,#000 26px);
  }
  .filter-row::-webkit-scrollbar{display:none}
  .filter-row .fbtn,.filter-row .fsort{flex:none}
  .view-toggle{flex:none}
  .acct-search{font-size:16px}
}

/* ══ app chrome, matched to the mockup ═════════════════════════════════════
   base.html's shell predates the mockup: an opaque bar, square-ish cards and
   an indigo-tinted ground. These bring it onto the mockup's glass + green. */
.topbar{
  background:var(--glass);
  backdrop-filter:blur(24px) saturate(180%);
  -webkit-backdrop-filter:blur(24px) saturate(180%);
  border-bottom:.5px solid var(--glass-edge);
}
.brand .dot{background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 0 12px var(--acc)}

.adm-nav{border-radius:var(--r-md)}
.adm-nav.active{
  background:var(--acc)!important;color:#fff!important;
  box-shadow:0 5px 16px -6px rgba(46,165,92,.6)!important;
}
.adm-nav .cnt{background:rgba(255,255,255,.14);border-radius:var(--r-pill)}

.msg{border-radius:var(--r-md);border:1px solid var(--line2)}
.msg.ok{background:rgba(52,199,89,.13);color:var(--ok);border-color:rgba(52,199,89,.3)}
.msg.err{background:rgba(255,69,58,.13);color:var(--bad);border-color:rgba(255,69,58,.3)}

.scard{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow);
}
.scard .v{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:-.5px}
.scard .ic{border-radius:var(--r-md)}

/* the customer app's tab bars.
   Two different things share the .tab-btn class: .cust-tabs is an inline pill
   group (a fill reads correctly there) while .tabbar is the fixed full-width
   bar at the bottom of the phone. Giving the bar a pill radius and the active
   tab a solid fill — with !important, over the app's own
   `.tabbar .tab-btn.active{background:transparent}` — left a green rectangle
   hanging out of the bar's rounded ends. Each gets its own treatment now. */
.tabbar,.cust-tabs{
  background:var(--glass);
  backdrop-filter:blur(24px) saturate(180%);
  -webkit-backdrop-filter:blur(24px) saturate(180%);
  border:.5px solid var(--glass-edge);
}
.cust-tabs{border-radius:var(--r-pill)}
.tabbar{border-radius:0}
.tab-btn{min-height:38px}
.cust-tabs .tab-btn,.sidebar .tab-btn{border-radius:var(--r-pill)}
.cust-tabs .tab-btn.active,.sidebar .tab-btn.active{background:var(--acc);color:#fff}
/* the bottom bar marks the active tab with colour, not a block */
.tabbar .tab-btn{border-radius:var(--r-md)}
.tabbar .tab-btn.active{background:transparent;color:var(--acc)}
.badge{border-radius:var(--r-pill)}
.progress{border-radius:var(--r-pill);overflow:hidden}


/* ══ account card ══════════════════════════════════════════════════════════
   Was ~550px tall per customer with a rainbow of buttons. The mockup spends
   colour once: green for the affirmative action, red for the destructive one,
   and everything else quiet — so the eye lands on state, not on chrome. */
.acct-top{padding:11px 13px;gap:8px}
.acct-name{font-size:14px;font-weight:800;letter-spacing:-.2px}
.acct-sub{font-size:11.5px}
.acct-body{padding:0 13px 11px}
.acct-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
  gap:8px 14px;margin:0 0 8px;
}
.acct-grid > div{min-width:0}
.acct-grid .k{font-size:10.5px;color:var(--faint);font-weight:700;display:block;margin-bottom:1px}
.acct-grid .v,.acct-grid b{font-size:13px;font-variant-numeric:tabular-nums}
.acct-usebar{min-width:0}
.acct-usebar .progress{height:4px;background:var(--line2);margin-top:6px;max-width:none}
.acct-usebar .progress > span{display:block;height:100%;background:var(--acc)}

.acct-acts{
  display:flex;flex-wrap:wrap;gap:6px;padding:10px 13px;
  border-top:1px solid var(--line);
}
.acct-acts .btn.sm{
  background:var(--bg2);border:1px solid var(--line2);color:var(--muted);font-weight:700;
}
.acct-acts .btn.sm:hover{color:var(--txt);border-color:var(--line2);background:var(--raised)}
/* the two that keep their meaning */
.acct-acts .btn.sm.green{background:var(--acc);border-color:transparent;color:#fff}
.acct-acts .btn.sm.red{background:transparent;border-color:rgba(255,69,58,.4);color:var(--bad)}
.acct-acts .btn.sm.red:hover{background:var(--bad);border-color:transparent;color:#fff}
.acct-acts .btn.sm.warn{background:transparent;border-color:rgba(255,159,10,.4);color:var(--warn)}
.acct-acts .btn.sm.warn:hover{background:var(--warn);border-color:transparent;color:#fff}

.acct .manage > summary{
  background:var(--bg2)!important;border:1px solid var(--line2);border-radius:var(--r-md);
  justify-content:center;font-size:12.5px;margin:0 13px 10px;width:auto!important;
}
.acct .badge{font-size:10.5px;font-weight:700}

/* ══ Clients deck ══════════════════════════════════════════════════════════
   The mockup's list, built on the expand/collapse the panel already had:
   a dense grid row on a laptop, a big-number card on a phone, and the old
   verbose card as the expanded detail. Every filter/sort/bulk hook is
   untouched because .acct keeps its data attributes. */
.accts.list-mode{gap:0}
.accts.list-mode .acct{
  border-radius:0;border-inline:0;border-top:0;box-shadow:none;margin:0;
  background:var(--card);
}
.accts.list-mode .acct:first-child{border-radius:var(--r-xl) var(--r-xl) 0 0;border-top:1px solid var(--line)}
.accts.list-mode .acct:last-child{border-radius:0 0 var(--r-xl) var(--r-xl)}

.accts.list-mode .acct-top{
  display:grid;align-items:center;gap:12px;
  padding:9px 14px;padding-inline-end:44px;
  grid-template-columns:auto 1.75fr 1fr;
  border-inline-start:3px solid transparent;
}
.accts.list-mode .acct-top > div:nth-child(3){min-width:0}

.nk-big{display:none}
.nk-av{
  width:30px;height:30px;border-radius:10px;flex:none;display:grid;place-items:center;
  font-family:var(--mono);font-weight:800;font-size:12px;
  background:rgba(46,165,92,.16);color:var(--acc2);
}
.nk-av.nk-warn{background:rgba(255,159,10,.16);color:var(--warn)}
.nk-av.nk-bad{background:rgba(255,69,58,.16);color:var(--bad)}
.nk-av.nk-off{background:var(--bg2);color:var(--faint)}

.accts.list-mode .acct-name{font-size:13.5px;gap:6px;flex-wrap:wrap}
.accts.list-mode .acct-name code{font-size:13.5px;font-weight:700}
.accts.list-mode .acct-sub{font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.accts.list-mode .acct-tg{display:none}

.nk-use{min-width:0;font-family:var(--mono);font-size:12px;color:var(--muted)}
.nk-use b{font-weight:600;font-variant-numeric:tabular-nums;display:block;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nk-bar{display:block;height:4px;border-radius:99px;background:var(--line2);
  overflow:hidden;margin-top:5px;max-width:180px}
.nk-bar s{display:block;height:100%;background:var(--acc);text-decoration:none}
.nk-bar s.w{background:var(--warn)} .nk-bar s.b{background:var(--bad)}
.nk-dev{font-family:var(--mono);font-size:12px;color:var(--muted);
  font-variant-numeric:tabular-nums;text-align:start}

.accts.list-mode .acct.expanded .acct-top{background:rgba(46,165,92,.07)}
.accts.list-mode .acct-top:hover{background:var(--bg2)}

/* severity rail, like the mockup */
.accts.list-mode .acct[data-status="expired"] .acct-top{border-inline-start-color:var(--bad)}
.accts.list-mode .acct[data-status="disabled"] .acct-top{border-inline-start-color:var(--line2)}
.accts.list-mode .acct[data-status="active"] .acct-top{border-inline-start-color:var(--acc)}
.accts.list-mode .acct[data-expsoon="1"] .acct-top{border-inline-start-color:var(--warn)}

/* ── phone: the big-number card ─────────────────────────────────────────── */
@media (max-width:700px){
  .accts.list-mode{gap:10px}
  .accts.list-mode .acct{
    border:1px solid var(--line)!important;border-radius:var(--r-lg)!important;
    box-shadow:var(--shadow);
  }
  .accts.list-mode .acct-top{
    grid-template-columns:auto 1fr;gap:13px;
    padding:13px 14px;padding-inline-end:42px;
    border-inline-start:0;
  }
  .accts.list-mode .acct-top::after{inset-inline-end:12px}
  .nk-big{
    display:block;font-family:var(--mono);font-size:25px;font-weight:800;line-height:1;
    letter-spacing:-1px;min-width:60px;text-align:center;color:var(--acc2);
  }
  .nk-big small{
    display:block;font-family:inherit;font-size:9.5px;font-weight:600;color:var(--faint);
    letter-spacing:0;margin-top:5px;white-space:nowrap;
  }
  .nk-big.nk-warn{color:var(--warn)} .nk-big.nk-bad{color:var(--bad)}
  .nk-big.nk-off{color:var(--faint)}
  .accts.list-mode .nk-av,.accts.list-mode .nk-use,.accts.list-mode .nk-dev{display:none}
  .accts.list-mode .acct-name{font-size:15px}
  .accts.list-mode .acct-sub{font-size:12px}
}

/* .acct-tg lost its inline styles so the deck can hide it; restore them here */
.acct-tg{font-size:12px;margin-top:3px;display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.accts.list-mode .acct-tg{display:none}

/* The bottom tab bar is fixed, so the page has to reserve its height or the
   last row sits underneath it — which it did, on every view. */
@media (max-width:700px){
  .adm-main,.wrap{padding-bottom:calc(76px + var(--nk-sab))}
}

/* ══ Liquid Glass ══════════════════════════════════════════════════════════
   Two things carry the iOS 26 feel in the mockup, and both were missing here:

   1. the STAGE — content doesn't sit on a flat page, it sits on a rounded
      gradient pane with its own edge, so the glass has something coloured to
      refract. A flat body gives glass nothing to do.
   2. the SPECULAR INSET — a 1px white highlight along the top inside edge.
      backdrop-filter alone reads as murky grey; the highlight is what makes
      the eye see a lit pane of glass.
   ══════════════════════════════════════════════════════════════════════════ */
.adm-view,
.tab-panel:not([hidden]){
  position:relative;
  border-radius:26px;
  padding:14px;
  border:1px solid var(--line);
  background:var(--stage);
  box-shadow:var(--shadow);
}
.adm-view[hidden]{display:none}

/* every translucent surface gets the full glass recipe, not just a tint */
.topbar,.adm-top,.adm-side,.tabbar,.cust-tabs,
.accts-head,.filter-row,.nk-actbar{
  background:var(--glass);
  backdrop-filter:blur(24px) saturate(180%);
  -webkit-backdrop-filter:blur(24px) saturate(180%);
  border:.5px solid var(--glass-edge);
  box-shadow:0 8px 30px rgba(0,0,0,.22), var(--glass-inset);
}
.adm-top,.topbar{border-inline:0;border-top:0}
.adm-side{border-top:0;border-bottom:0}
.tabbar{border-inline:0;border-bottom:0}

/* cards sit ON the stage, so they stay solid — glass on glass reads as mud */
.adm-view .card,.tab-panel .card,.adm-view .accts.list-mode .acct,.nk-card{
  box-shadow:0 4px 18px rgba(0,0,0,.18);
}

/* the search + filter bars are the mockup's floating glass chrome */
.accts-head{border-radius:var(--r-pill);padding:8px 10px}
.accts-head h3{margin-inline-start:6px}
.acct-search{background:rgba(0,0,0,.16);border-color:transparent}
:root[data-theme="light"] .acct-search{background:rgba(0,0,0,.05)}
.filter-row{border-radius:var(--r-xl)}
.segs,.view-toggle{background:rgba(0,0,0,.2)}
:root[data-theme="light"] .segs,
:root[data-theme="light"] .view-toggle{background:rgba(0,0,0,.06)}

@media (max-width:700px){
  .adm-view,.tab-panel:not([hidden]){padding:10px;border-radius:20px}
  .accts-head{border-radius:var(--r-lg)}
}
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) .acct-search{background:rgba(0,0,0,.05)}
  :root:not([data-theme="dark"]) .segs,
  :root:not([data-theme="dark"]) .view-toggle{background:rgba(0,0,0,.06)}
}

/* ══ customer app ══════════════════════════════════════════════════════════
   The account line becomes a proper hero: the number people came to read, and
   the one action they came to take, both above the fold on a phone. */
.cust-summary{
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);
  padding:13px 15px;margin:0 0 12px;box-shadow:var(--shadow);
  display:flex;align-items:center;gap:13px;flex-wrap:wrap;
}
.cust-summary-name{font-size:17px;font-weight:800;letter-spacing:-.3px}
.cust-summary > .muted{font-size:12.5px}

/* the passkey prompt is a one-time ask; it shouldn't own the top of the app */
#pk-banner{padding:12px 14px}
#pk-banner h3{font-size:13.5px;margin:0 0 4px}
#pk-banner p{font-size:12px;margin:0 0 10px}

@media (min-width:761px){
  /* the grid was two columns but every card spanned both, so it never used them */
  .cust-grid{gap:14px}
}
@media (max-width:760px){
  .cust-summary{padding:12px 13px}
  .cust-summary-name{font-size:18px}
}

/* On a phone, the config card is what people opened the app for — put it
   first. The service summary and the live chart are context; they read fine
   below it. On a laptop there's room for the natural order. */
#wg-config-card{order:-1}
@media (max-width:760px){ .cust-grid{display:flex;flex-direction:column} }

/* ══ sheet ═════════════════════════════════════════════════════════════════
   Same shape as NarniaPay's np-sheet. Tapping a dashboard stat used to jump
   you to the Clients view and lose your place; now the answer opens over the
   page — docked to the bottom on a phone, centred on a laptop. */
.nk-sheet{
  position:fixed;inset:0;z-index:9990;display:flex;justify-content:center;
  align-items:center;background:rgba(0,0,0,.16);opacity:0;
  transition:opacity .24s var(--ease);
}
.nk-sheet.on{opacity:1}
.nk-sheet-card{
  display:flex;flex-direction:column;width:520px;max-width:calc(100% - 24px);
  max-height:82vh;background:var(--card);border:1px solid var(--line2);
  border-radius:var(--r-xl);box-shadow:var(--shadow2);overflow:hidden;
  transform:scale(.97);transition:transform .26s var(--ease);
}
.nk-sheet.on .nk-sheet-card{transform:none}
.nk-sheet-head{
  display:flex;align-items:center;gap:10px;padding:14px 16px;flex:none;
  border-bottom:1px solid var(--line);
}
.nk-sheet-head b{flex:1;min-width:0;font-size:15px;font-weight:800;letter-spacing:-.2px}
.nk-sheet-x{
  border:0;background:var(--bg2);color:var(--muted);width:32px;height:32px;
  border-radius:50%;cursor:pointer;font-size:19px;line-height:1;flex:none;
}
.nk-sheet-x:hover{color:var(--txt);background:var(--raised)}
.nk-sheet-body{overflow-y:auto;-webkit-overflow-scrolling:touch;padding:6px 0 10px}
.nk-sheet-empty{padding:26px 16px;text-align:center;color:var(--faint);font-size:13.5px}

@media (max-width:760px){
  .nk-sheet{
    align-items:flex-end;background:rgba(0,0,0,.4);
    backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
    padding:calc(env(safe-area-inset-top,0px) + 8px) 0 0;
  }
  .nk-sheet-card{
    width:100%;max-width:600px;margin:0 auto;
    border-radius:26px 26px 0 0;border-inline:0;border-bottom:0;
    max-height:calc(100dvh - env(safe-area-inset-top,0px) - 8px);
    padding-bottom:max(var(--nk-sab),10px);
    transform:translateY(100%);
    transition:transform .34s cubic-bezier(.32,.72,0,1);
    box-shadow:0 -0.5px 0 rgba(255,255,255,.06), 0 -10px 48px rgba(0,0,0,.5);
  }
  .nk-sheet.on .nk-sheet-card{transform:none}
  /* grab handle */
  .nk-sheet-card::before{
    content:'';display:block;flex:none;width:38px;height:5px;margin:8px auto 4px;
    border-radius:3px;background:var(--faint);opacity:.35;
  }
}

/* rows inside a sheet */
.nk-srow{
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:11px;
  padding:10px 16px;border-bottom:1px solid var(--line);cursor:pointer;
  background:none;border-inline:0;border-top:0;width:100%;
  font-family:inherit;text-align:start;color:var(--txt);
}
.nk-srow:last-child{border-bottom:0}
.nk-srow[hidden]{display:none}
.nk-srow:hover{background:var(--bg2)}
.nk-srow .nm{min-width:0}
.nk-srow .nm b{display:block;font-size:13.5px;font-weight:700;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nk-srow .nm span{display:block;font-size:11px;color:var(--faint)}
.nk-srow .rt{font-family:var(--mono);font-size:12px;color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* ══ swipe on client rows ══════════════════════════════════════════════════ */
.nk-swipe{position:relative;overflow:hidden;touch-action:pan-y;overscroll-behavior-x:none}
.nk-pan{position:absolute;top:0;bottom:0;width:0;overflow:hidden;display:flex;z-index:0}
.nk-pl{left:0}
.nk-pr{right:0}
.nk-act{
  border:0;height:100%;padding:0 10px;cursor:pointer;overflow:hidden;
  font-family:inherit;font-weight:800;font-size:12px;color:#fff;white-space:nowrap;
  display:flex;align-items:center;justify-content:center;background:#5a6577;
}
.nk-act.renew{background:var(--acc)}
.nk-act.off{background:var(--warn)}
.nk-act.on{background:var(--acc)}
.nk-act.del{background:var(--bad)}
.nk-swtop{position:relative;z-index:1;background:var(--card);will-change:transform}
body.nk-dragging{user-select:none;-webkit-user-select:none;cursor:grabbing}

/* ══ long lists ════════════════════════════════════════════════════════════
   243 customers were all laid out and painted on every render. content-visibility
   lets the browser skip off-screen ones while leaving them in the DOM, so the
   existing search/filter/sort/bulk code (which walks real nodes) is untouched. */
.accts.list-mode .acct{
  content-visibility:auto;
  contain-intrinsic-size:auto 71px;
}
@media (max-width:700px){
  .accts.list-mode .acct{contain-intrinsic-size:auto 110px}
}
.scard{cursor:pointer}


/* ══ Today ═════════════════════════════════════════════════════════════════
   A four-column <table> can't fit a phone. My first pass stacked each entry
   into three rows with a full-width button — 185px per entry, so exactly one
   was visible. Two rows: who + action on top, what's wrong + usage under it. */
@media (max-width:700px){
  table.tw{display:block;width:100%}
  table.tw thead{display:none}
  table.tw tbody{display:block}
  table.tw tr{
    display:grid;grid-template-columns:1fr auto;gap:3px 10px;
    padding:9px 2px;border-bottom:1px solid var(--line);align-items:center;
  }
  table.tw tr:last-child{border-bottom:0}
  table.tw tbody td{display:block;padding:0;border:0;min-width:0}
  table.tw tbody td:nth-child(1){grid-column:1;grid-row:1;font-weight:700;font-size:13.5px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  table.tw tbody td:nth-child(2){grid-column:1;grid-row:2}
  table.tw tbody td:nth-child(2) .fpill{font-size:11px;padding:2px 8px}
  table.tw tbody td:nth-child(3){grid-column:1;grid-row:2;justify-self:end;
    font-size:11.5px;color:var(--muted);text-align:end!important}
  table.tw tbody td:nth-child(4){grid-column:2;grid-row:1/span 2;text-align:end!important}
  table.tw tbody td:nth-child(4) .btn{white-space:nowrap;padding:8px 12px;min-height:36px}
  /* the header block above the list gives back another entry's worth */
  .adm-view[data-view="today"] .card > h3{font-size:14px;margin-bottom:2px}
  .adm-view[data-view="today"] .card > p{font-size:11.5px;margin-bottom:8px}
  .tw-tabs{margin-bottom:8px}
}
}

/* ── sheet: grab handle, sticky tools, severity tones ───────────────────── */
.nk-grab{display:none}
.nk-sheet-card::before{content:none!important}
@media (max-width:760px){
  .nk-grab{
    display:block;flex:none;width:38px;height:5px;margin:8px auto 2px;
    border-radius:3px;background:var(--faint);opacity:.35;
    cursor:grab;touch-action:none;
  }
  /* a 5px bar is impossible to grab, so give it an invisible 22px target */
  .nk-grab::after{content:'';position:absolute;inset-inline:0;height:26px;margin-top:-10px}
  .nk-sheet-card{position:relative}
  .nk-sheet-head{cursor:grab;touch-action:none}
}
.nk-sheet-tools{
  display:flex;gap:8px;align-items:center;padding:9px 14px;flex:none;
  border-bottom:1px solid var(--line);background:var(--card);
  position:sticky;top:0;z-index:2;
}
.nk-find{
  flex:1;min-width:0;display:flex;align-items:center;gap:7px;padding:0 11px;
  background:var(--bg2);border:1px solid var(--line2);border-radius:var(--r-pill);
  color:var(--faint);
}
.nk-find input:not([type=checkbox]):not([type=radio]){
  flex:1;min-width:0;background:none;border:0;outline:none;box-shadow:none;
  color:var(--txt);font-family:inherit;font-size:14px;padding:8px 0;min-height:0;
  border-radius:0;
}
.nk-sort{
  flex:none;max-width:44%;background:var(--bg2);border:1px solid var(--line2);
  border-radius:var(--r-pill);padding:8px 11px;font-size:12.5px;font-weight:700;
  color:var(--txt);font-family:inherit;min-height:0;
}
.nk-av.nk-s-warn{background:rgba(255,159,10,.16);color:var(--warn)}
.nk-av.nk-s-bad{background:rgba(255,69,58,.16);color:var(--bad)}
.nk-av.nk-s-off{background:var(--bg2);color:var(--faint)}

/* ── Clients: one compact toolbar that stays with you ───────────────────── */
@media (max-width:700px){
  .accts-head{
    position:sticky;top:calc(58px + env(safe-area-inset-top));z-index:8;
  }
  .filter-row{
    position:sticky;top:calc(120px + env(safe-area-inset-top));z-index:7;
    /* the pills collapse into two native selects, so nothing scrolls sideways */
    flex-wrap:wrap;overflow:visible;
    -webkit-mask-image:none;mask-image:none;
  }
  .filter-row .fbtn{display:none}
  .filter-row .nk-filtsel{display:block}
  .filter-row .view-toggle{margin-inline-start:auto}
}
.nk-filtsel{
  display:none;flex:1;min-width:0;background:var(--bg2);border:1px solid var(--line2);
  border-radius:var(--r-pill);padding:8px 12px;font-size:12.5px;font-weight:700;
  color:var(--txt);font-family:inherit;min-height:38px;
}

/* a sheet must not hand its scroll to the page behind it */
.nk-sheet,.nk-sheet-body{overscroll-behavior:contain}

/* a sheet that has another one stacked on top of it recedes slightly */
.nk-sheet.nk-under .nk-sheet-card{
  transform:scale(.96) translateY(-8px);
  filter:brightness(.82);
  transition:transform .28s var(--ease),filter .28s var(--ease);
}

/* the sheet sits above the keyboard rather than under it (see --nk-kb) */
@media (max-width:760px){
  .nk-sheet{padding-bottom:var(--nk-kb,0px)}
  .nk-sheet-card{
    max-height:calc(100dvh - env(safe-area-inset-top,0px) - 8px - var(--nk-kb,0px));
  }
}

/* ══ WireGuard management sheet ════════════════════════════════════════════ */
.nk-wsum{font-size:12px;color:var(--muted);padding:2px 2px 10px}
.nk-wcard{background:var(--bg2);border:1px solid var(--line);border-radius:14px;
  padding:11px 12px;margin-bottom:10px}
.nk-wch{display:flex;align-items:center;font-size:12.5px;font-weight:800;margin-bottom:9px}
.nk-wch .n{margin-inline-start:auto;font-family:var(--mono);font-size:11px;
  color:var(--faint);font-weight:400}
.nk-qa{display:grid;grid-template-columns:repeat(2,1fr);gap:7px}
.nk-qa button{
  border:1px solid var(--line2);background:var(--card);color:var(--txt);border-radius:12px;
  padding:10px 8px;font-family:inherit;font-size:12.5px;font-weight:700;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:3px;min-height:52px;
  transition:transform .2s var(--spring);
}
.nk-qa button:active{transform:scale(.95)}
.nk-qa button small{font-weight:500;font-size:10px;color:var(--faint);font-family:var(--mono)}
.nk-qa button.hot{background:var(--acc);border-color:transparent;color:#fff}
.nk-qa button.hot small{color:rgba(255,255,255,.85)}

.nk-wtbl{width:100%;border-collapse:collapse;font-size:12.5px}
.nk-wtbl td{padding:7px 4px;border-bottom:1px solid var(--line)}
.nk-wtbl tr:last-child td{border-bottom:0}
.nk-wtbl td:first-child{width:26px}
.nk-wtbl .nm{font-family:var(--mono);font-size:12px}
.nk-wtbl .ac{text-align:end;white-space:nowrap}
.nk-wtbl input[type=checkbox]{accent-color:var(--acc);width:17px;height:17px}
.nk-ib{
  display:inline-grid;place-items:center;width:30px;height:30px;border-radius:9px;
  border:1px solid var(--line2);background:var(--card);color:var(--muted);
  margin-inline-start:5px;font-size:10.5px;font-weight:700;text-decoration:none;cursor:pointer;
}
.nk-ib:hover{color:var(--txt)}
.nk-ib svg{width:14px;height:14px}
.nk-bulk{display:flex;align-items:center;gap:9px;margin-top:9px;padding-top:9px;
  border-top:1px solid var(--line);font-size:12px;color:var(--muted)}
.nk-bulk .rm{
  margin-inline-start:auto;border:1px solid rgba(255,69,58,.4);background:transparent;
  color:var(--bad);border-radius:10px;padding:7px 13px;font-family:inherit;
  font-size:12px;font-weight:700;cursor:pointer;
}
.nk-wgm .mrow{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:8px}
.nk-wgm .mrow .ml{font-size:11.5px;color:var(--faint);min-width:64px}
.nk-wgm .mrow input[type=number],.nk-wgm .mrow input[type=text]{
  width:92px;padding:7px 9px;font-size:13px;min-height:0;
}
.nk-fold.nk-danger > summary .v{color:var(--bad)}

/* the cancel window for one-tap actions */
.nk-undo{
  position:fixed;inset-inline:14px;bottom:calc(76px + var(--nk-sab));
  z-index:10000;display:flex;align-items:center;gap:12px;
  background:var(--card);border:1px solid var(--line2);border-radius:14px;
  padding:11px 14px;box-shadow:var(--shadow2);
  opacity:0;transform:translateY(12px);transition:.24s var(--ease);
}
.nk-undo.on{opacity:1;transform:none}
/* the draining bar under the undo row — reads as time left without reading */
.nk-undo-rail{display:block;position:absolute;left:10px;right:10px;bottom:5px;height:2.5px;
  border-radius:2px;background:var(--line2);overflow:hidden}
.nk-undo-rail s{display:block;height:100%;width:100%;background:var(--acc2);
  border-radius:2px;text-decoration:none}
.nk-undo{position:fixed;padding-bottom:15px}
.nk-undo b{flex:1;min-width:0;font-size:12.5px;font-weight:700}
.nk-undo button{
  border:0;background:none;color:var(--acc2);font-family:inherit;
  font-weight:800;font-size:12.5px;cursor:pointer;padding:4px 6px;
}
@media (min-width:761px){
  .nk-undo{inset-inline:auto;inset-inline-end:22px;bottom:22px;min-width:280px}
  .nk-qa{grid-template-columns:repeat(3,1fr)}
}

/* ══ customer WireGuard tab: grouped by location ═══════════════════════════ */
.wg-locs{display:grid;gap:8px}
.wg-loc > summary .v{font-weight:700;font-size:13px}
.wg-loc > summary .pillc{
  margin-inline-start:8px;font-family:var(--mono);font-size:11px;color:var(--faint);
  background:var(--card);border:1px solid var(--line);border-radius:999px;padding:1px 8px;
}
.wg-loc .nk-foldbody{padding:10px}
.wg-dev-card{background:var(--card)}
.wg-dev-card .dev-name{font-size:11.5px}

/* a whole card that folds: the summary keeps the card's own heading */
details.nk-cfold > summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;gap:9px;
  margin:-2px 0 0;user-select:none;
}
details.nk-cfold > summary::-webkit-details-marker{display:none}
details.nk-cfold > summary h3{margin:0;flex:1;min-width:0}
details.nk-cfold > summary .nk-caret{flex:none;color:var(--faint);transition:transform .25s var(--ease)}
details.nk-cfold[open] > summary .nk-caret{transform:rotate(90deg)}
details.nk-cfold[open] > summary{margin-bottom:10px}

/* ══ customer service card ═════════════════════════════════════════════════
   Five stat blocks at 80-91px each stacked into 290px on a phone. The same
   facts fit in three tight columns; the header pill already carries the day
   count, so these are reference, not headline. */
@media (max-width:760px){
  .tab-panel .card > .row{
    display:grid!important;grid-template-columns:repeat(3,minmax(0,1fr));
    gap:8px!important;
  }
  .tab-panel .card > .row .stat{
    padding:9px 10px!important;border-radius:12px!important;min-width:0;
  }
  .tab-panel .card > .row .stat:last-child{grid-column:1/-1}
  .tab-panel .card > .row .stat .k,
  .tab-panel .card > .row .stat .l{font-size:10px}
  .tab-panel .card > .row .stat .big,
  .tab-panel .card > .row .stat .v{font-size:17px!important}
  .tab-panel .card > .row .stat b{font-size:13px}
}

/* ══ customer Tools tab ════════════════════════════════════════════════════
   Three diagnostic cards plus a full speed-test dial ran 2.3 screens. The dial
   is the only thing worth its space; the rest fold. */
.tab-panel[data-panel="tools"] > .card,
.tab-panel[data-panel="tools"] > details.card{margin-bottom:10px}
@media (max-width:760px){
  #speed-gauge{max-width:210px}
  #speed-card{padding:12px 13px}
  #speed-card .st-srv{padding:6px 11px;font-size:11.5px;min-height:32px}
  /* the three relocated diagnostics get a tight header and no filler */
  #protect-card,#srv-status-card,#usage-hist-card{padding:12px 13px}
  #protect-card h3,#srv-status-card h3,#usage-hist-card h3,
  #protect-card > div:first-child,#srv-status-card > div:first-child,
  #usage-hist-card > div:first-child{font-size:13.5px;margin-bottom:6px}
  #protect-card p,#srv-status-card p,#usage-hist-card p{font-size:11.5px;margin:0 0 8px}
}

/* ══ minimal speed test ════════════════════════════════════════════════════
   532px for one dial: a 189px gauge, a two-row server picker and a 2×2 results
   grid. The dial earns maybe half that, the picker one row, the results one. */
@media (max-width:760px){
  #speed-card{padding:12px 13px}
  /* the canvas carries an inline max-width:360px, which outranks a plain rule */
  #speed-gauge{max-width:168px!important}
  #speed-card > div:nth-child(2){
    gap:5px!important;margin:6px 0 0!important;
    flex-wrap:nowrap!important;overflow-x:auto;scrollbar-width:none;
    justify-content:flex-start!important;
  }
  #speed-card > div:nth-child(2)::-webkit-scrollbar{display:none}
  #speed-card .st-srv{flex:none;padding:6px 10px;font-size:11.5px;min-height:32px}
  #speed-card > div:nth-child(3){margin:2px 0 0!important}
  #speed-results{
    display:grid!important;grid-template-columns:repeat(4,1fr);gap:6px!important;
    margin:6px 0 4px!important;
  }
  #speed-results > *{padding:7px 4px!important;margin:0!important;text-align:center}
  #speed-results .muted,#speed-results .k{font-size:9.5px!important}
  #speed-results b,#speed-results .v{font-size:14px!important}
  #speed-start{margin-top:6px}
}

/* ══ customer: header and service status are one card ══════════════════════ */
.cust-summary.cust-status-head{
  background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-xl) var(--r-xl) 0 0;border-bottom:0;
  padding:13px 14px 11px;margin:0 0 0;box-shadow:var(--shadow);
}
.cust-status{
  background:var(--card);border:1px solid var(--line);border-top:0;
  border-radius:0 0 var(--r-xl) var(--r-xl);padding:0 14px 13px;
  margin:0 0 12px;box-shadow:var(--shadow);
}
.cust-status .row{margin:0}
.cust-status > div:last-child{margin-bottom:0}
@media (max-width:760px){
  .cust-status{padding:0 12px 12px}
  .cust-summary.cust-status-head{padding:12px 12px 10px}
  .cust-status .row{
    display:grid!important;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px!important;
  }
  /* grid items default to min-width:auto, so a stat whose content is wider
     than its track pushes out of the card instead of shrinking */
  .cust-status .row .stat{
    padding:9px 10px!important;border-radius:11px!important;
    min-width:0;overflow:hidden;
  }
  .cust-status .row .stat > *{min-width:0;max-width:100%}
  .cust-status .row .stat .big,.cust-status .row .stat b{
    font-size:16px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;
  }
  .cust-status .row .stat label,.cust-status .row .stat .k{font-size:10px}
}

/* the account card belongs to the WireGuard tab only */
.cust-summary[hidden],.cust-status[hidden]{display:none!important}

/* ══ bottom bar and the home-indicator strip ═══════════════════════════════
   On a real phone the strip under the bar is the safe-area inset. The bar
   reserves it with padding, but if the inset arrives late (PWA launch, or an
   orientation/viewport change) the strip is left unpainted and reads as a gap
   under the bar. This paints it with the same material unconditionally, so
   there is nothing to be late for. Browsers report the inset as 0, which is
   why it never showed up in testing. */
/* One source of truth for the bottom inset.

   In an installed PWA the phone reported BOTH a 34px safe-area-inset-bottom
   AND a layout viewport 37px shorter than the screen — iOS had already kept
   the home-indicator strip outside the viewport, so honouring the inset on top
   of that reserved the same space twice: 34px of dead glass under the tab
   labels plus a 37px band below. It read as the bar floating off the bottom.

   Every consumer now goes through this variable so narnia-ui.js can zero it
   when it measures that double-count, and leave it alone everywhere else. */
:root{--nk-sab:env(safe-area-inset-bottom, 0px)}

@media (max-width:760px){
  .tabbar{
    bottom:0;
    padding-bottom:max(6px, var(--nk-sab));
  }
  .tabbar::after{
    content:"";position:absolute;left:0;right:0;top:100%;
    height:var(--nk-sab);
    background:var(--glass);
    backdrop-filter:blur(24px) saturate(180%);
    -webkit-backdrop-filter:blur(24px) saturate(180%);
    pointer-events:none;
  }
}
@media (max-width:700px){
  .adm-side{
    bottom:0;
    padding-bottom:max(6px, var(--nk-sab));
  }
  .adm-side::after{
    content:"";position:absolute;left:0;right:0;top:100%;
    height:var(--nk-sab);
    background:var(--glass);
    backdrop-filter:blur(24px) saturate(180%);
    -webkit-backdrop-filter:blur(24px) saturate(180%);
    pointer-events:none;
  }
}

/* ── theme picker ────────────────────────────────────────────────────────
   Sits beside the language button on every page, login included, so the
   choice is available before anyone signs in. Segmented rather than a
   cycling button: all three states are visible, and "system" is a state you
   can actually see you are in. */
.nk-theme{display:inline-flex;align-items:center;gap:2px;padding:2px;
  border:1px solid var(--line2);border-radius:var(--r-pill);background:var(--bg2);
  vertical-align:middle}
/* 33x30 rather than the 28x26 this started as: the audit flags anything under
   30px as too small to hit with a thumb, and it was right — these are controls
   people actually press, not decoration. */
.nk-theme-b{display:inline-flex;align-items:center;justify-content:center;
  width:33px;height:30px;padding:0;border:0;border-radius:var(--r-pill);
  background:none;color:var(--faint);cursor:pointer;font-family:inherit;
  transition:background .16s var(--ease),color .16s var(--ease)}
.nk-theme-b svg{width:15px;height:15px;display:block}
.nk-theme-b:hover{color:var(--muted)}
.nk-theme-b.on{background:var(--card);color:var(--acc2);box-shadow:var(--shadow)}
@media (max-width:420px){
  .nk-theme-b{width:31px;height:30px}
  .nk-theme-b svg{width:14px;height:14px}
}

/* compact form: one button on a narrow header, opening a sheet */
.nk-theme-one{display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:32px;padding:0;border:1px solid var(--line2);
  border-radius:var(--r-pill);background:var(--bg2);color:var(--muted);
  cursor:pointer;font-family:inherit;vertical-align:middle}
.nk-theme-one svg{width:16px;height:16px;display:block}
.nk-theme-row{display:flex;align-items:center;gap:12px;width:100%;
  padding:14px 14px;border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--bg2);color:var(--txt);font-family:inherit;font-size:15px;
  font-weight:600;cursor:pointer;margin-bottom:8px;text-align:start}
.nk-theme-row svg{width:18px;height:18px;flex:0 0 auto;color:var(--faint)}
.nk-theme-row.on{border-color:var(--acc);color:var(--acc2)}
.nk-theme-row.on svg{color:var(--acc2)}


