/* ════════════════════════════════════════════════════════════════════════
   NazBook SHARED COMPONENTS  ·  "Cyber-Glass"
   Load AFTER assets/tokens.css and BEFORE any screen-specific <style>
   (screen styles may override; they must still use tokens only).
   Everything here is theme- and palette-aware via tokens — no raw hex.
   ════════════════════════════════════════════════════════════════════════ */

body{font-family:'IBM Plex Sans Arabic',sans-serif;background:var(--bg);color:var(--on);transition:background .3s,color .3s}
/* §3.1: every screen sets dir="rtl" on <html> (not body — the plan's literal
   body[dir=rtl] never matches this markup). Arabic glyphs' taller ascenders/
   descenders clip under a tight line-height, and some contexts inherit a
   stray letter-spacing from Tailwind's tracking-* utilities — neither should
   ever apply to Arabic body copy. */
html[dir="rtl"] body{letter-spacing:normal;line-height:1.55}
.material-symbols-outlined{font-variation-settings:'FILL' 0,'wght' 300,'GRAD' 0,'opsz' 24}
.ms-filled{font-variation-settings:'FILL' 1,'wght' 400}
[hidden]{display:none!important}
:focus-visible{outline:2px solid var(--aqua)!important;outline-offset:2px;border-radius:8px}

/* ── background ambiance ─────────────────────────────────────────────────
   mesh: dark = brand radial wash; light (§11.2-4) = barely-there top gradient.
   orbs: dark-only, STATIC (§11.7: no infinite decorative animation); hidden in light. */
.mesh-bg{position:fixed;inset:0;z-index:-2;opacity:var(--mesh-op,1);transition:opacity .3s;background:
  radial-gradient(circle at 18% 20%,rgba(0,220,229,.14) 0%,transparent 48%),
  radial-gradient(circle at 82% 78%,rgba(52,61,150,.18) 0%,transparent 50%),
  radial-gradient(circle at 60% 8%,rgba(142,45,226,.10) 0%,transparent 40%)}
[data-theme="light"] .mesh-bg{opacity:1;background:linear-gradient(180deg,rgba(8,145,163,.05) 0%,transparent 220px)}
[data-palette="jade"] .mesh-bg{background:
  radial-gradient(circle at 18% 20%,rgba(92,168,124,.16) 0%,transparent 48%),
  radial-gradient(circle at 82% 78%,rgba(26,81,64,.30) 0%,transparent 50%),
  radial-gradient(circle at 60% 8%,rgba(183,229,186,.08) 0%,transparent 40%)}
[data-palette="jade"][data-theme="light"] .mesh-bg{background:linear-gradient(180deg,rgba(40,135,96,.05) 0%,transparent 220px)}
.glow-orb,.orb{position:fixed;border-radius:50%;z-index:-1;pointer-events:none;opacity:var(--orb-op,.22);filter:blur(110px)}
.glow-orb{width:440px;height:440px;opacity:var(--mesh-op,1);filter:blur(80px)}
[data-theme="light"] .glow-orb,[data-theme="light"] .orb{display:none}

/* ── elevation: card (glass) · overlay · modal (opaque) ────────────────── */
.glass{backdrop-filter:blur(40px);-webkit-backdrop-filter:blur(40px);background:var(--glass-bg);border:1px solid var(--glass-bd);box-shadow:var(--glass-sh)}
.card{backdrop-filter:blur(40px);-webkit-backdrop-filter:blur(40px);background:var(--glass-bg);border:1px solid var(--glass-bd);border-radius:1.25rem;box-shadow:var(--glass-sh)}
.glass-overlay{backdrop-filter:blur(40px);-webkit-backdrop-filter:blur(40px);background:var(--glass-bg);border:1px solid var(--overlay-bd);box-shadow:var(--overlay-sh)}
.surface-modal{background:var(--surface-solid);border:1px solid var(--overlay-bd);box-shadow:var(--overlay-sh)}

/* ── stat cards (KPI tiles) — one shared size/shape everywhere ───────────
   Replaces 9 screens' worth of drifted padding/font-size + the copy-pasted
   local .kpi hover blocks. Compose as class="stat-card card" (button or div);
   .stat-card only sets internal layout, .card supplies the surface/border. */
.stat-card{padding:.6rem .75rem;border-radius:.85rem;text-align:right;position:relative;display:block;width:100%}
.stat-card .stat-label{display:flex;align-items:center;gap:.35rem;font-size:11px;color:var(--on-dim);line-height:1.3}
.stat-card .stat-label .material-symbols-outlined{font-size:14px}
.stat-card .stat-value{font-size:1.05rem;font-weight:700;margin-top:.3rem;font-variant-numeric:tabular-nums;line-height:1.2}
button.stat-card,a.stat-card{cursor:pointer;transition:border-color .15s,transform .15s}
button.stat-card:hover,a.stat-card:hover{border-color:rgb(var(--primary-rgb) / .35)}
.stat-card.is-active{border-color:rgb(var(--primary-rgb) / .5);box-shadow:inset 0 0 0 1px rgb(var(--primary-rgb) / .25)}
.stat-grid{display:grid;gap:.75rem}

/* ── buttons ────────────────────────────────────────────────────────────── */
.btn-primary{background:var(--primary);color:var(--on-primary);font-weight:700;box-shadow:var(--primary-glow);transition:transform .18s,box-shadow .2s,background .18s;padding:.55rem 1rem;border-radius:.75rem;display:inline-flex;align-items:center;gap:.4rem}
.btn-primary:hover{background:var(--primary-hover);box-shadow:var(--primary-glow-hover);transform:translateY(-1px)}
.btn-primary:active{transform:scale(.97)}
.btn-primary:disabled{opacity:.4;box-shadow:none;cursor:not-allowed;transform:none}
.btn-ghost{background:var(--field);border:1px solid var(--glass-bd);color:var(--on-var);transition:background .18s,color .18s,border-color .18s;padding:.55rem 1rem;border-radius:.75rem;display:inline-flex;align-items:center;gap:.4rem}
.btn-ghost:hover{background:var(--field-bd);color:var(--on)}
.btn-ghost:disabled{opacity:.4;cursor:not-allowed}
.btn-ghost.is-active{background:var(--primary-container);border-color:var(--primary-container-bd);color:var(--primary-ink)}

/* §3.5: every modal/drawer save action used to pair btn-primary with a raw
   flex-1 utility, so on desktop (where the modal itself is width-capped at
   max-w-md but the button still ate all remaining footer width) it read as
   one oversized button next to one tiny "إلغاء" — content+padding sizing,
   never stretched, is the one shared rule every save action should follow. */
.btn-save{background:var(--primary);color:var(--on-primary);font-weight:700;box-shadow:var(--primary-glow);transition:transform .18s,box-shadow .2s,background .18s;padding:0 1.5rem;height:2.5rem;border-radius:.65rem;display:inline-flex;align-items:center;justify-content:center;gap:.4rem;flex:0 0 auto}
.btn-save:hover{background:var(--primary-hover);box-shadow:var(--primary-glow-hover)}
.btn-save:active{transform:scale(.97)}
.btn-save:disabled{opacity:.4;box-shadow:none;cursor:not-allowed;transform:none}

/* ── fields ─────────────────────────────────────────────────────────────── */
/* !important beats the Tailwind forms plugin (forces white otherwise) */
.fld{background:var(--field)!important;border:1px solid var(--field-bd)!important;border-radius:.65rem!important;color:var(--on)!important;-webkit-appearance:none!important;appearance:none!important;padding:.55rem .85rem;width:100%;font-family:inherit;font-size:.9rem;outline:none;transition:border-color .18s,box-shadow .18s}
.fld:focus{border-color:var(--aqua)!important;box-shadow:var(--focus-glow)!important}
.fld::placeholder{color:var(--on-dim)!important}
.fld.err{border-color:var(--error)!important;color:var(--error)!important}
.fld:disabled{opacity:.45;cursor:not-allowed}
select.fld{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23849495' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")!important;background-repeat:no-repeat!important;background-position:left .65rem center!important;background-size:15px!important;padding-left:2.1rem!important}
/* native <option> popups ignore translucent parent bg — without this they render
   OS-default white, and forced light text becomes white-on-white */
select.fld option{background:var(--surface-solid);color:var(--on)}
/* Safety net (this exact bug has recurred more than once): ANY native <select> in
   the app, even one that forgets the .fld class, still gets dark/readable options
   instead of the OS-default white-highlight-on-dark-theme clash. */
select option{background:var(--surface-solid);color:var(--on)}

/* ── chips & pills — status = solid/tinted chip + bright text, no green/yellow ── */
.chip{font-size:.72rem;padding:.18rem .55rem;border-radius:9999px;background:var(--field);border:1px solid var(--glass-bd);color:var(--on-var)}
.pill{font-size:.72rem;font-weight:700;padding:.2rem .6rem;border-radius:9999px;display:inline-flex;align-items:center;gap:.3rem;white-space:nowrap}
.p-ok,.p-ship{background:var(--primary-container);color:var(--primary-dim);border:1px solid var(--primary-container-bd)}
.p-warn,.p-wait{background:var(--warn-container);color:var(--warn-ink);border:1px solid var(--warn-container-bd)}
.p-err{background:var(--error-container);color:var(--error);border:1px solid var(--error-container-bd)}
.p-neutral,.p-new{background:var(--field);color:var(--on-var);border:1px solid var(--glass-bd)}

/* ── toggle ─────────────────────────────────────────────────────────────── */
.tg{width:42px;height:23px;border-radius:12px;background:var(--field-bd);border:1px solid var(--glass-bd);position:relative;transition:background .22s;flex-shrink:0;cursor:pointer}
.tg::after{content:'';width:17px;height:17px;border-radius:50%;background:#fff;position:absolute;top:2px;right:2px;transition:transform .22s;box-shadow:0 1px 2px rgba(0,0,0,.25)}
.tg.on{background:var(--primary-dim);border-color:var(--primary)}
.tg.on::after{transform:translateX(-19px)}
.tg.lock{opacity:.4;cursor:not-allowed}

/* ── tabs ───────────────────────────────────────────────────────────────── */
.tab{padding:.5rem 1rem;border-radius:1.1rem;font-size:.875rem;font-weight:600;color:var(--on-dim);cursor:pointer;transition:all .18s}
.tab.active{background:var(--field-bd);color:var(--primary-ink)}

/* ── checkboxes — SOFT corners everywhere, never square ─────────────────── */
input[type=checkbox]{border-radius:6px!important}
input[type=checkbox].cb,.cb{appearance:none!important;-webkit-appearance:none!important;width:22px;height:22px;border-radius:7px!important;border:2px solid var(--field-bd);background:var(--field);cursor:pointer;display:inline-grid;place-content:center;transition:.15s;vertical-align:middle;flex-shrink:0}
.cb:hover{border-color:var(--primary)}
.cb:checked{background:var(--primary);border-color:var(--primary)}
.cb:checked::after{content:"";width:11px;height:6px;border:2.2px solid var(--on-primary);border-top:0;border-right:0;transform:rotate(-45deg) translateY(-1px)}

/* ── loading ────────────────────────────────────────────────────────────── */
.skel{background:var(--skel);border-radius:.5rem;position:relative;overflow:hidden}
.skel::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,var(--skel-sheen),transparent);transform:translateX(100%);animation:sheen 1.4s infinite}
@keyframes sheen{to{transform:translateX(-100%)}}
.spin{width:22px;height:22px;border-radius:50%;border:2.5px solid var(--field-bd);border-top-color:var(--primary);animation:rot .7s linear infinite}
@keyframes rot{to{transform:rotate(360deg)}}

/* ── accent border (was the animated conic loop) ─────────────────────────
   §11.7: the 8.55s infinite conic spin was motion without meaning + GPU cost.
   Now a STATIC brand-gradient border; screens may add a hover glow. */
.ab{border-color:transparent!important;position:relative}
.ab::after{content:'';position:absolute;inset:-1px;border-radius:inherit;padding:1.1px;background:linear-gradient(135deg,var(--primary-container-bd),rgba(124,108,255,.35) 55%,rgba(142,45,226,.25));-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none}

/* ── tooltip (.tip[data-tip]) ───────────────────────────────────────────── */
.tip{position:relative}
.tip:hover::after,.tip:focus-visible::after{content:attr(data-tip);position:absolute;bottom:130%;right:50%;transform:translateX(50%);white-space:normal;width:max-content;max-width:230px;text-align:center;background:var(--surface-solid);border:1px solid var(--overlay-bd);color:var(--on);font-size:11px;line-height:1.5;padding:5px 9px;border-radius:8px;z-index:50;box-shadow:var(--overlay-sh)}

/* ── nav (icon rail + shared bits) ──────────────────────────────────────── */
/* §3.7: was --on-dim (the muted/caption tier) — too faint for something
   that's the ENTIRE content of an icon-only interactive control, worst in
   light mode (4.56:1) but really a wrong-tier pick in both themes. --on-var
   is the same family, just the tier actually meant for this. */
.nav-item{height:38px;width:38px;border-radius:.6rem;display:flex;align-items:center;justify-content:center;color:var(--on-var);transition:all .18s;cursor:pointer}
.nav-item:hover{background:var(--field);color:var(--on)}
.nav-item.active{background:var(--primary-container);color:var(--primary-ink)}
.logo-grad{background:linear-gradient(135deg,var(--primary) 0%,var(--indigo) 55%,var(--purple) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent}

/* ── English IG handles: LTR island, left-aligned ───────────────────────── */
.ig{direction:ltr;unicode-bidi:isolate;color:var(--primary-ink);font-weight:600;text-decoration:none}
.ig:hover{text-decoration:underline}

/* ── scrollbars ─────────────────────────────────────────────────────────── */
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--field-bd);border-radius:10px}
::-webkit-scrollbar-thumb:hover{background:var(--outline-v)}

/* ── entrance / stagger (§11.7) ────────────────────────────────────────────
   Apply `.stagger-in` to a LIST CONTAINER (e.g. a <tbody>) only on the render
   call that first paints it — screens must drop the class again on every
   subsequent re-render (filter/sort/search), otherwise child nodes replay
   the entrance every time they're re-inserted via innerHTML. That per-screen
   "first paint only" flag is what makes this meaningful motion instead of
   the exact decorative-replay problem §11.7 calls out. Capped at 15 rows —
   longer lists share the last delay rather than trailing off forever. */
@keyframes rowIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.stagger-in>*{animation:rowIn var(--dur-component) var(--ease-out-fast) both}
.stagger-in>*:nth-child(1){animation-delay:calc(var(--stagger-step) * 0)}
.stagger-in>*:nth-child(2){animation-delay:calc(var(--stagger-step) * 1)}
.stagger-in>*:nth-child(3){animation-delay:calc(var(--stagger-step) * 2)}
.stagger-in>*:nth-child(4){animation-delay:calc(var(--stagger-step) * 3)}
.stagger-in>*:nth-child(5){animation-delay:calc(var(--stagger-step) * 4)}
.stagger-in>*:nth-child(6){animation-delay:calc(var(--stagger-step) * 5)}
.stagger-in>*:nth-child(7){animation-delay:calc(var(--stagger-step) * 6)}
.stagger-in>*:nth-child(8){animation-delay:calc(var(--stagger-step) * 7)}
.stagger-in>*:nth-child(9){animation-delay:calc(var(--stagger-step) * 8)}
.stagger-in>*:nth-child(10){animation-delay:calc(var(--stagger-step) * 9)}
.stagger-in>*:nth-child(11){animation-delay:calc(var(--stagger-step) * 10)}
.stagger-in>*:nth-child(12){animation-delay:calc(var(--stagger-step) * 11)}
.stagger-in>*:nth-child(13){animation-delay:calc(var(--stagger-step) * 12)}
.stagger-in>*:nth-child(14){animation-delay:calc(var(--stagger-step) * 13)}
.stagger-in>*:nth-child(n+15){animation-delay:calc(var(--stagger-step) * 14)}

/* ── optimistic UI feedback (§11.7) ──────────────────────────────────────
   A control mid-flight to the server; `.opt-fail` briefly flags one that
   got rolled back so the revert doesn't read as a silent, confusing snap-back. */
.opt-pending{opacity:.55;pointer-events:none;transition:opacity var(--dur-micro) var(--ease-out-fast)}
@keyframes optFail{0%,100%{background:transparent}30%{background:var(--error-container)}}
.opt-fail{animation:optFail .6s var(--ease-out-fast)}

/* ── motion kill-switch ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){*,::before,::after{animation:none!important;transition-duration:.01ms!important}}
