@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;500;600;700;800;900&family=Tajawal:wght@300;400;500;700;800&display=swap');

/* ============================================
   DENTAL CLINIC MANAGEMENT - GLOBAL STYLES
   RTL Arabic interface with 3 theme options
   ============================================ */
/* ============================================================
   Modirify Design Tokens (Phase 3 U-1)
   ============================================================
   Foundation tokens — type scale, z-index scale, focus rings,
   glass surfaces, hover-lift, density placeholder. Loaded BEFORE
   the main styles.css via an @import at the top of styles.css so
   every theme block and component class can reference these
   values without worrying about cascade order.

   What IS in this file:
     §1 Type scale       — 6 steps, Hybrid Linear+Stripe (V-1/2, ADR-048)
     §2 Z-index scale    — 8 semantic layers (replaces 1..3000 chaos)
     §3 Focus tokens     — unified accent ring (2 strengths)
     §4 Glass tokens     — single source of truth, auto-dark (A1)
     §5 Hover-lift       — only 3 allowed values (-1 / -2 / -3)
     §6 Density          — placeholder for U-10 (decision C2)
     §7 Shimmer + tint   — V-1/5 (ADR-048) accent-tinted skeleton +
                           Stripe hero-card soft gradient base

   What is NOT here (lives in styles.css, intentionally untouched):
     • --space-1..12, --duration-*, --ease-*          (already tokenized)
     • --bg-*, --text-primary/-secondary/-tertiary,
       --border-*, --accent-*                         (theme palette)
     • --success/-soft, --warning/-soft, ...          (status palette)
     • --radius-*, --shadow-*                         (per-theme already)

   See DECISIONS.md ADR-017 for the U-1 design rationale and
   ADR-048 for the V-1/2 Hybrid 6-size pivot.
============================================================ */
:root {
  /* ──────────────────────────────────────────────────────────
     §1 Type scale (V-1/2, ADR-048) — Hybrid 6 sizes
     Linear-clarity's 5 sizes (11/13/15/22/36) + Stripe-density's
     --text-base (14px) for data-dense surfaces (Billing / Finance
     / Analytics tables). Replaces the U-1 10-token scale.

     Use guide:
       --text-xs   (11px)  chips, badges, metadata
       --text-sm   (13px)  body — default
       --text-base (14px)  data-dense ONLY (tables in Billing/Finance/Analytics)
       --text-md   (15px)  card titles, primary text, buttons, inputs
       --text-lg   (22px)  page titles, KPI value (compact)
       --text-xl   (36px)  hero numbers (dashboard greeting, metric tile value)

     Dropped vs U-1: --text-2xs (10px) absorbed into --text-xs; intermediate
     --text-lg (16) / --text-xl (18) / --text-2xl (22) / --text-3xl (28) /
     --text-4xl (36) compressed into the 6-step ladder. The single styles.css
     consumer of the old --text-xl (.empty-state.v2.is-lg title, was 18px)
     is remapped to the new --text-lg (22px) — semantic match for a title.

     Line-heights stay on the existing 4-step --leading-* scale
     (tight/snug/normal/relaxed = 1.2/1.35/1.5/1.7) — paired by
     screen-author at touch point, not auto-paired here.
     ────────────────────────────────────────────────────────── */
  --text-xs:   11px;
  --text-sm:   13px;
  --text-base: 14px;
  --text-md:   15px;
  --text-lg:   22px;
  --text-xl:   36px;

  /* Line-heights paired with the type scale */
  --leading-tight:   1.2;   /* hero titles, large numbers */
  --leading-snug:    1.35;  /* card titles, section heads */
  --leading-normal:  1.5;   /* body text */
  --leading-relaxed: 1.7;   /* long-form descriptions, modal sub */

  /* ──────────────────────────────────────────────────────────
     §2 Z-index scale — 8 semantic layers
     Order top-to-bottom: tooltips > toasts > drawers > modals
     > dropdowns > topbar > sticky > base. The boot splash uses
     --z-max so app overlays never sit on top of it.
     ────────────────────────────────────────────────────────── */
  --z-base:           1;
  --z-sticky:         10;
  --z-topbar:         50;
  --z-dropdown:       100;   /* notifications, theme picker, date filter */
  --z-modal-backdrop: 200;
  --z-modal:          210;
  --z-drawer:         300;
  --z-toast:          500;
  --z-tooltip:        700;
  --z-max:            999;   /* boot splash — never go past */

  /* ──────────────────────────────────────────────────────────
     §3 Focus tokens — unified accent ring
     Use --ring-shadow for buttons / interactive cards (3px, 35%).
     Use --ring-shadow-soft for inputs / inline targets (3px, 22%).
     Replaces five inline copies of
     "0 0 0 3px color-mix(... accent 22%, transparent)".
     ────────────────────────────────────────────────────────── */
  --ring-width:       3px;
  --ring-color:       color-mix(in srgb, var(--accent) 35%, transparent);
  --ring-color-soft:  color-mix(in srgb, var(--accent) 22%, transparent);
  --ring-shadow:      0 0 0 var(--ring-width) var(--ring-color);
  --ring-shadow-soft: 0 0 0 var(--ring-width) var(--ring-color-soft);

  /* ──────────────────────────────────────────────────────────
     §4 Glass tokens (A1) — single source of truth
     Light-themed surfaces use --glass-bg / --glass-border /
     --glass-shadow. Dark themes (luxe, midnight) override these
     in their own theme block via auto-switch below.
     Replaces the four-way duplication of
     ".modal", ".gm-box", ".accounting-modal", ".mk2-drawer".
     ────────────────────────────────────────────────────────── */
  --glass-bg:        rgba(255, 255, 255, 0.88);
  --glass-blur:      24px;
  --glass-blur-sm:   10px;
  --glass-border:    rgba(255, 255, 255, 0.6);
  --glass-shadow:
    0 24px 60px rgba(0, 0, 0, 0.14),
    0 4px 16px rgba(0, 0, 0, 0.08);

  /* Dark-theme variants — applied below for luxe + midnight */
  --glass-bg-dark:     rgba(13, 18, 38, 0.87);
  --glass-border-dark: rgba(255, 255, 255, 0.08);
  --glass-shadow-dark:
    0 24px 60px rgba(0, 0, 0, 0.45),
    0 4px 16px rgba(0, 0, 0, 0.35);

  /* ──────────────────────────────────────────────────────────
     §5 Hover-lift — only 3 allowed values
     --lift-1: subtle (chips, list rows, table rows).
     --lift-2: standard (cards, KPI tiles, nav items).
     --lift-3: prominent (metric tiles, feature cards).
     Magic translateY values outside these three are a smell.
     ────────────────────────────────────────────────────────── */
  --lift-1: -1px;
  --lift-2: -2px;
  --lift-3: -3px;

  /* ──────────────────────────────────────────────────────────
     §6 Density (C2) — placeholder for U-10
     Currently --density-scale = 1 (no effect). When U-10 wires
     the compact / comfortable toggle, the scale will multiply
     into space + padding helpers so the existing density
     toggle in TweaksPanel finally has teeth. Defined now to
     avoid retrofitting every primitive again later.
     ────────────────────────────────────────────────────────── */
  --density-scale: 1;

  /* ──────────────────────────────────────────────────────────
     §7 Shimmer + tint (V-1/5, ADR-048) — Hybrid Stripe layer
     --shimmer-base       — base color of the skeleton gradient
                            (matches loading-surface background).
     --shimmer-highlight  — accent-tinted highlight that sweeps
                            across. 7% accent mixed with bg-hover —
                            subtle teal pulse on Clean, theme-aware
                            on every other theme (so dark themes
                            stay dark-and-accent-flavored, not
                            light-flashy).
     --shimmer-duration   — animation duration. 1.6s = slightly
                            slower than the legacy 1.4s for a more
                            "premium" rhythm (Vercel/Stripe pattern).
     --tint-hero-strength — opacity of the soft gradient overlay
                            on hero cards (Stripe's 4% sweep from
                            corner). Tokenized so V-1/3 dark themes
                            can override (dark surfaces need a
                            stronger tint to be visible).
     ────────────────────────────────────────────────────────── */
  --shimmer-base:       var(--bg-subtle);
  --shimmer-highlight:  color-mix(in srgb, var(--accent) 7%, var(--bg-hover));
  --shimmer-duration:   1.6s;
  --tint-hero-strength: 4%;

  /* ──────────────────────────────────────────────────────────
     §8 Logo sizes (V-Logo, ADR-070) — unified scale
     Source of truth lives in app/src/ui/logo.jsx (LOGO_SIZES);
     these tokens mirror the values for any CSS-only consumer
     (transitions, breakpoint overrides) without re-importing.
     ────────────────────────────────────────────────────────── */
  --logo-xs:  80px;   /* sidebar mini / compact strips */
  --logo-sm:  140px;  /* brand strip on verify / celebration cards */
  --logo-md:  200px;  /* onboarding welcome step */
  --logo-lg:  220px;  /* sidebar standard */
  --logo-xl:  280px;  /* login portal hero */
  --logo-transition: width 320ms cubic-bezier(0.34, 1.56, 0.64, 1), opacity 220ms ease;

  /* ──────────────────────────────────────────────────────────
     §9 Pre-auth palette (ADR-086) — single source of truth for
     the eight pre-auth surfaces (boot splash, landing nav, login
     portal, register, forgot, check-email, verify celebration,
     onboarding wizard). Each surface uses these tokens instead of
     hardcoded teal hexes so future theme variants (luxe, midnight
     etc.) can re-skin pre-auth without a find-and-replace pass.

     The values mirror the landing's --lp-accent + --lp-accent-dark
     + --lp-success (kept as local aliases on .lp-shell) and
     ADR-084 unified the rest of pre-auth onto this triplet. Any
     new pre-auth element MUST use these tokens; the smoke check
     `pre-auth-banned-hex` enforces it.
     ────────────────────────────────────────────────────────── */
  --auth-primary:      #0ea5b7;  /* primary brand teal             */
  --auth-primary-dark: #0a8a99;  /* dark teal — links, badges, text */
  --auth-success:      #22c55e;  /* completion / "ready" states     */
  --auth-primary-soft:  rgba(14, 165, 183, 0.10);  /* card tints */
  --auth-primary-tint:  rgba(14, 165, 183, 0.16);  /* hovers, borders */
  --auth-success-soft:  rgba(34, 197, 94, 0.10);   /* done states */

  /* ──────────────────────────────────────────────────────────
     §10 Responsive Foundation (Phase 1.5 — 2026-05-26)
     ────────────────────────────────────────────────────────── */
  /* Canonical breakpoints. These values are also referenced in
     @media queries throughout the codebase as raw px (CSS variables
     can't appear inside @media). Source of truth lives here so
     future audits have ONE place to read them.
       Phone landscape and up     ≥ 480px (30em)
       Tablet portrait and up     ≥ 768px (48em)
       Laptop and up              ≥ 1024px (64em)
       Desktop and up             ≥ 1280px (80em)
     Mobile-first convention: write CSS for phones first, then
     layer up with @media (min-width: ...). Avoid the inverted
     @media (max-width: ...) pattern outside transitional patches.
     ────────────────────────────────────────────────────────── */
  --bp-phone:   30em;   /* 480px  — phone landscape + up */
  --bp-tablet:  48em;   /* 768px  — tablet portrait + up */
  --bp-laptop:  64em;   /* 1024px — laptop + up          */
  --bp-desktop: 80em;   /* 1280px — desktop + up         */

  /* Fluid spacing — clamp(min, fluid-via-vw, max).
     The middle term scales with the viewport width so spacing
     grows smoothly between breakpoints instead of jumping.
     Used by the Layout Primitives (.l-stack / .l-cluster / etc).
     Numbers in comments are rem→px @ 16px root font.
     ────────────────────────────────────────────────────────── */
  --space-fluid-3xs: clamp(0.125rem, 0.25vw + 0.0625rem, 0.25rem); /*  2 →  4 */
  --space-fluid-2xs: clamp(0.25rem,  0.5vw  + 0.125rem,  0.5rem);  /*  4 →  8 */
  --space-fluid-xs:  clamp(0.5rem,   1vw    + 0.25rem,   0.75rem); /*  8 → 12 */
  --space-fluid-sm:  clamp(0.75rem,  1.5vw  + 0.375rem,  1rem);    /* 12 → 16 */
  --space-fluid-md:  clamp(1rem,     2vw    + 0.5rem,    1.5rem);  /* 16 → 24 */
  --space-fluid-lg:  clamp(1.5rem,   3vw    + 0.75rem,   2rem);    /* 24 → 32 */
  --space-fluid-xl:  clamp(2rem,     4vw    + 1rem,      3rem);    /* 32 → 48 */
  --space-fluid-2xl: clamp(2.5rem,   5vw    + 1.25rem,   4rem);    /* 40 → 64 */

  /* Fluid typography — for hero titles and large headlines that
     should breathe on desktop but stay legible on phones. Body
     text continues to use the fixed scale (§1) because consistent
     sizes help dense surfaces (tables) stay scannable. Use these
     ONLY for headlines that look awkward when they don't scale
     (e.g., the hero name "أحمد محمد" at 36px is too big on a 320px
     phone).
     ────────────────────────────────────────────────────────── */
  --fs-fluid-title: clamp(1.125rem, 1vw + 0.875rem, 1.375rem); /* 18 → 22 */
  --fs-fluid-h2:    clamp(1.25rem,  2vw + 0.75rem,  1.75rem);  /* 20 → 28 */
  --fs-fluid-hero:  clamp(1.5rem,   3vw + 0.75rem,  2.25rem);  /* 24 → 36 */

  /* Container size tokens — used by Layout Primitives to decide
     when to "switch" from horizontal to vertical layouts. These
     are intentionally LARGER than viewport breakpoints because
     they're container-aware, not viewport-aware.
     ────────────────────────────────────────────────────────── */
  --container-narrow: 30rem;  /* 480px — switcher / sidebar threshold */
  --container-prose:  60ch;   /* readable line length                 */
  --container-wide:   80rem;  /* 1280px — max page width              */

  /* ──────────────────────────────────────────────────────────
     §11 Premium modal shell tokens (V-Polish, 2026-05-27)
     Opt-in `<ResponsiveModal className="rm-card--premium">`
     reads these for the "Ctrl+K-like" feel: larger radius,
     deeper float shadow, more breathing padding, and a smooth
     input-focus glow scoped to inside the premium card.
     Adding `.rm-card--premium` to a modal pulls all of these
     in at once without changing any other modal. The base
     modal tokens stay untouched so legacy modals look the same.
     ────────────────────────────────────────────────────────── */
  --radius-modal-premium:    24px;   /* base modal-box is ~14-16px */
  --shadow-modal-premium:
    0 24px 60px rgba(0, 0, 0, 0.18),
    0 4px  16px rgba(0, 0, 0, 0.10);
  --pad-modal-premium:       28px;   /* base padding is 16-20px    */
  --pad-modal-premium-sm:    20px;   /* phone-tight padding        */
  --input-focus-glow-premium:
    0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
/* Dark themes — deeper shadow so the premium card still reads as
   floating against navy/luxe surfaces. */
[data-theme="luxe"],
[data-theme="midnight"] {
  --shadow-modal-premium:
    0 24px 60px rgba(0, 0, 0, 0.55),
    0 4px  16px rgba(0, 0, 0, 0.35);
}
/* Auto-switch glass tokens for dark themes (A1 fallback) */
[data-theme="luxe"],
[data-theme="midnight"] {
  --glass-bg:     var(--glass-bg-dark);
  --glass-border: var(--glass-border-dark);
  --glass-shadow: var(--glass-shadow-dark);
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  font-family: 'Cairo', 'Tajawal', system-ui, sans-serif;
  direction: rtl;
  text-align: start;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
button, input, select, textarea {
  font-family: inherit;
  direction: rtl;
}
/* ============================================
   THEME 1: Clean Medical (Default)
   Soft white + medical teal/cyan
   ============================================ */
[data-theme="clean"] {
  --bg: #f4f7fa;
  --bg-elevated: #ffffff;
  --bg-sidebar: #ffffff;
  --bg-card: #ffffff;
  --bg-hover: #f0f5f9;
  --bg-subtle: #eef3f8;

  --text-primary: #0f1f2e;
  --text-secondary: #4a5b6d;
  --text-tertiary: #8a98a8;
  --text-muted: #b5bfc9;

  --border: #e4ebf2;
  --border-strong: #d0dae4;

  --accent: #0891b2;           /* medical teal */
  --accent-hover: #0e7490;
  --accent-soft: #ecfeff;
  --accent-text: #155e75;

  --success: #059669;
  --success-soft: #d1fae5;
  --warning: #d97706;
  --warning-soft: #fef3c7;
  --danger: #dc2626;
  --danger-soft: #fee2e2;
  --info: #2563eb;
  --info-soft: #dbeafe;
  --purple: #7c3aed;
  --purple-soft: #ede9fe;

  --shadow-sm: 0 1px 2px rgba(15, 31, 46, 0.04);
  --shadow: 0 2px 8px rgba(15, 31, 46, 0.06), 0 1px 2px rgba(15, 31, 46, 0.04);
  --shadow-lg: 0 12px 32px rgba(15, 31, 46, 0.10), 0 2px 8px rgba(15, 31, 46, 0.06);

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
}
/* ============================================
   THEME 2: Luxe Dark
   Deep navy + gold/violet accents
   ============================================ */
[data-theme="luxe"] {
  --bg: #0b1020;
  --bg-elevated: #131a2e;
  --bg-sidebar: #0f1525;
  --bg-card: #151c33;
  --bg-hover: #1c2541;
  --bg-subtle: #1a2139;

  --text-primary: #f1f5fb;
  --text-secondary: #a8b3c7;
  --text-tertiary: #6a7690;
  --text-muted: #4a5570;

  --border: #232c47;
  --border-strong: #303a58;

  --accent: #d4af6f;           /* warm gold */
  --accent-hover: #e6c18a;
  --accent-soft: #2a2419;
  --accent-text: #e6c18a;

  --success: #34d399;
  --success-soft: #0f2a22;
  --warning: #fbbf24;
  --warning-soft: #2a2212;
  --danger: #f87171;
  --danger-soft: #2a1515;
  --info: #818cf8;
  --info-soft: #1a1a33;
  --purple: #a78bfa;
  --purple-soft: #231a33;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow: 0 4px 14px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.2);
  --shadow-lg: 0 20px 50px rgba(0, 0, 0, 0.45), 0 4px 12px rgba(0, 0, 0, 0.3);

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
}
/* ============================================
   THEME 3: Warm Pastel
   Cream + soft pink/mint
   ============================================ */
[data-theme="warm"] {
  --bg: #fbf6f1;
  --bg-elevated: #ffffff;
  --bg-sidebar: #fff8f1;
  --bg-card: #ffffff;
  --bg-hover: #fbf1e8;
  --bg-subtle: #f7ede3;

  --text-primary: #2b1810;
  --text-secondary: #5c4a3e;
  --text-tertiary: #8a7a6e;
  --text-muted: #b8ab9f;

  --border: #ecdfd1;
  --border-strong: #d9c8b5;

  --accent: #c2675b;           /* terracotta */
  --accent-hover: #a7544a;
  --accent-soft: #fbeae6;
  --accent-text: #8e3e34;

  --success: #5b8a72;
  --success-soft: #e3efe8;
  --warning: #c9944a;
  --warning-soft: #faf0d9;
  --danger: #b14848;
  --danger-soft: #f5dede;
  --info: #5b7aa3;
  --info-soft: #e0e9f3;
  --purple: #9579a5;
  --purple-soft: #ece4f1;

  --shadow-sm: 0 1px 2px rgba(43, 24, 16, 0.05);
  --shadow: 0 3px 10px rgba(43, 24, 16, 0.07), 0 1px 2px rgba(43, 24, 16, 0.04);
  --shadow-lg: 0 16px 40px rgba(43, 24, 16, 0.10), 0 3px 8px rgba(43, 24, 16, 0.06);

  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 18px;
  --radius-xl: 26px;
}
/* ============================================
   THEME 4: Sage — زيتوني هادئ
   ============================================ */
[data-theme="sage"] {
  --bg:          #f2f5f0;
  --bg-elevated: #ffffff;
  --bg-sidebar:  #f8faf6;
  --bg-card:     #ffffff;
  --bg-hover:    #eaf0e6;
  --bg-subtle:   #e8ede4;

  --text-primary:   #1a2e1a;
  --text-secondary: #3d5c3a;
  --text-tertiary:  #7a9475;
  --text-muted:     #b2c5ae;

  --border:       #d4e0ce;
  --border-strong:#bdd1b6;

  --accent:       #4a7c59;
  --accent-hover: #3a6347;
  --accent-soft:  #e8f5ec;
  --accent-text:  #2d5c3c;

  --success:      #2e7d52;
  --success-soft: #d1f0e0;
  --warning:      #c9944a;
  --warning-soft: #faf0d9;
  --danger:       #c0392b;
  --danger-soft:  #fde8e6;
  --info:         #3b7dd8;
  --info-soft:    #ddeeff;
  --purple:       #7c5cbf;
  --purple-soft:  #ede8f8;

  --shadow-sm: 0 1px 2px rgba(26,46,26,.04);
  --shadow:    0 2px 8px rgba(26,46,26,.06), 0 1px 2px rgba(26,46,26,.04);
  --shadow-lg: 0 12px 32px rgba(26,46,26,.10), 0 2px 8px rgba(26,46,26,.06);

  --radius-sm: 6px;
  --radius:    10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
}
/* ============================================
   THEME 5: Ocean — أزرق عميق حديث
   ============================================ */
[data-theme="ocean"] {
  --bg:          #e8f4fd;
  --bg-elevated: #ffffff;
  --bg-sidebar:  #f0f8ff;
  --bg-card:     #ffffff;
  --bg-hover:    #d4ecfb;
  --bg-subtle:   #e0f0fa;

  --text-primary:   #0a2540;
  --text-secondary: #1a4971;
  --text-tertiary:  #5a87b8;
  --text-muted:     #99bedd;

  --border:        #c2ddf5;
  --border-strong: #a8cff0;

  --accent:       #0070cc;
  --accent-hover: #005aad;
  --accent-soft:  #ddeeff;
  --accent-text:  #004a99;

  --success:      #0a8a5f;
  --success-soft: #d0f5e8;
  --warning:      #d4890a;
  --warning-soft: #fff2d0;
  --danger:       #d63031;
  --danger-soft:  #fde8e8;
  --info:         #6c5ce7;
  --info-soft:    #ebe8fd;
  --purple:       #a855f7;
  --purple-soft:  #f3e8ff;

  --shadow-sm: 0 1px 2px rgba(10,37,64,.05);
  --shadow:    0 2px 8px rgba(10,37,64,.07), 0 1px 2px rgba(10,37,64,.04);
  --shadow-lg: 0 12px 32px rgba(10,37,64,.12), 0 2px 8px rgba(10,37,64,.06);

  --radius-sm: 6px;
  --radius:    10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
}
/* ============================================
   THEME 6: Blush — وردي ناعم (مناسب للأطفال)
   ============================================ */
[data-theme="blush"] {
  --bg:          #fdf4f6;
  --bg-elevated: #ffffff;
  --bg-sidebar:  #fff8fa;
  --bg-card:     #ffffff;
  --bg-hover:    #fce8ed;
  --bg-subtle:   #faeef2;

  --text-primary:   #2d1420;
  --text-secondary: #6b3a4e;
  --text-tertiary:  #b07a90;
  --text-muted:     #d4afc0;

  --border:        #f0d0dc;
  --border-strong: #e8b8ca;

  --accent:       #d4547a;
  --accent-hover: #bc3d63;
  --accent-soft:  #fde8ef;
  --accent-text:  #9c2a4f;

  --success:      #5a9e6f;
  --success-soft: #e0f5e8;
  --warning:      #d4890a;
  --warning-soft: #fff2d0;
  --danger:       #c0392b;
  --danger-soft:  #fde8e6;
  --info:         #5b7dd8;
  --info-soft:    #dde8ff;
  --purple:       #9b59b6;
  --purple-soft:  #f0e6f8;

  --shadow-sm: 0 1px 2px rgba(45,20,32,.04);
  --shadow:    0 2px 8px rgba(45,20,32,.06), 0 1px 2px rgba(45,20,32,.04);
  --shadow-lg: 0 12px 32px rgba(45,20,32,.10), 0 2px 8px rgba(45,20,32,.06);

  --radius-sm: 8px;
  --radius:    14px;
  --radius-lg: 18px;
  --radius-xl: 26px;
}
/* ============================================
   THEME 7: Midnight — أسود فاخر + أحمر
   ============================================ */
[data-theme="midnight"] {
  --bg:          #080c10;
  --bg-elevated: #0f1520;
  --bg-sidebar:  #0b1018;
  --bg-card:     #121a28;
  --bg-hover:    #1a2438;
  --bg-subtle:   #151e2e;

  --text-primary:   #f0f4fc;
  --text-secondary: #9aabc4;
  --text-tertiary:  #546880;
  --text-muted:     #334455;

  --border:        #1e2c40;
  --border-strong: #273850;

  --accent:       #e84545;
  --accent-hover: #cc2e2e;
  --accent-soft:  #2a1010;
  --accent-text:  #ff7070;

  --success:      #22d196;
  --success-soft: #0a2a20;
  --warning:      #f5b731;
  --warning-soft: #2a2008;
  --danger:       #ff4757;
  --danger-soft:  #2a0f12;
  --info:         #6c9bff;
  --info-soft:    #101830;
  --purple:       #bd93f9;
  --purple-soft:  #1e1030;

  --shadow-sm: 0 1px 3px rgba(0,0,0,.4);
  --shadow:    0 4px 14px rgba(0,0,0,.5), 0 1px 3px rgba(0,0,0,.3);
  --shadow-lg: 0 20px 50px rgba(0,0,0,.6), 0 4px 12px rgba(0,0,0,.4);

  --radius-sm: 6px;
  --radius:    10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
}
[data-theme="midnight"] .btn.primary { color: #ffffff; }
[data-theme="midnight"] .sidebar-logo-mark { color: #fff; }
[data-theme="midnight"] .nav-item .badge-count { color: #fff; }
[data-theme="midnight"] .nav-item.active {
  background: var(--bg-hover);
  color: var(--accent-text);
}
/* ============================================
   THEME 8: Desert — رملي دافئ شرقي
   ============================================ */
[data-theme="desert"] {
  --bg:          #f5efe6;
  --bg-elevated: #fdf8f2;
  --bg-sidebar:  #f8f2ea;
  --bg-card:     #fdf8f2;
  --bg-hover:    #ede4d4;
  --bg-subtle:   #ede4d6;

  --text-primary:   #2c1a08;
  --text-secondary: #6b4c28;
  --text-tertiary:  #a07c58;
  --text-muted:     #c9ab8a;

  --border:        #e0cdb0;
  --border-strong: #ccb898;

  --accent:       #c47c2a;
  --accent-hover: #a86520;
  --accent-soft:  #f8eddc;
  --accent-text:  #8a5010;

  --success:      #5a8a42;
  --success-soft: #e2f0d8;
  --warning:      #d45f0a;
  --warning-soft: #fde8d0;
  --danger:       #c0392b;
  --danger-soft:  #fde0de;
  --info:         #4a7abf;
  --info-soft:    #dce8f5;
  --purple:       #8e5fad;
  --purple-soft:  #ede0f8;

  --shadow-sm: 0 1px 2px rgba(44,26,8,.05);
  --shadow:    0 2px 8px rgba(44,26,8,.07), 0 1px 2px rgba(44,26,8,.04);
  --shadow-lg: 0 12px 32px rgba(44,26,8,.10), 0 2px 8px rgba(44,26,8,.06);

  --radius-sm: 8px;
  --radius:    12px;
  --radius-lg: 16px;
  --radius-xl: 22px;
}
/* ============================================
   THEME 9: Violet — بنفسجي راقي مميز
   ============================================ */
[data-theme="violet"] {
  --bg:          #f5f0ff;
  --bg-elevated: #ffffff;
  --bg-sidebar:  #f9f5ff;
  --bg-card:     #ffffff;
  --bg-hover:    #ede4ff;
  --bg-subtle:   #ece5ff;

  --text-primary:   #1e0a40;
  --text-secondary: #4a2d80;
  --text-tertiary:  #8b6abf;
  --text-muted:     #bba8e0;

  --border:        #ddd0f8;
  --border-strong: #ccb8f5;

  --accent:       #7c3aed;
  --accent-hover: #6425d0;
  --accent-soft:  #ede9fe;
  --accent-text:  #5b21b6;

  --success:      #059669;
  --success-soft: #d1fae5;
  --warning:      #d97706;
  --warning-soft: #fef3c7;
  --danger:       #dc2626;
  --danger-soft:  #fee2e2;
  --info:         #2563eb;
  --info-soft:    #dbeafe;
  --purple:       #9333ea;
  --purple-soft:  #f3e8ff;

  --shadow-sm: 0 1px 2px rgba(30,10,64,.04);
  --shadow:    0 2px 8px rgba(30,10,64,.07), 0 1px 2px rgba(30,10,64,.04);
  --shadow-lg: 0 12px 32px rgba(30,10,64,.12), 0 2px 8px rgba(30,10,64,.06);

  --radius-sm: 8px;
  --radius:    12px;
  --radius-lg: 16px;
  --radius-xl: 22px;
}
/* Theme picker dropdown */
.theme-picker-drop {
  position: fixed;
  top: 56px;
  inset-inline-end: 100px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 14px 16px;
  z-index: 300;
  min-width: 260px;
}
.theme-picker-drop .tpd-title {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: 10px;
}
.theme-picker-drop .tpd-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
}
.theme-picker-drop .tpd-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  padding: 6px 4px;
  border-radius: var(--radius);
  border: 2px solid transparent;
  transition: border-color var(--duration-fast), background var(--duration-fast);
}
.theme-picker-drop .tpd-item:hover { background: var(--bg-hover); }
.theme-picker-drop .tpd-item.active { border-color: var(--accent); }
.theme-picker-drop .tpd-swatch {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 2px solid rgba(0,0,0,.08);
  flex-shrink: 0;
}
.theme-picker-drop .tpd-label {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-secondary);
  text-align: center;
}
/* U-8: hint pointing dev-only themes to the Tweaks panel */
.theme-picker-drop .tpd-hint {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 10px;
  color: var(--text-tertiary);
  text-align: center;
  line-height: 1.5;
}
/* ============================================
   Layout
   ============================================ */
#root, .app-root {
  width: 100%;
  height: 100dvh;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text-primary);
  display: flex;
  overflow: hidden;
}
.main-shell {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}
.page-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}
/* ============================================
   Scrollbars
   ============================================ */
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 10px;
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
}
/* ============================================
   Reusable bits
   ============================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--bg-subtle);
  color: var(--text-primary);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-smooth);
  white-space: nowrap;
  font-family: inherit;
}
.btn:hover { background: var(--bg-hover); }
.btn.primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
[data-theme="luxe"] .btn.primary { color: #0b1020; }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.ghost {
  background: transparent;
  color: var(--text-secondary);
}
.btn.ghost:hover { background: var(--bg-hover); color: var(--text-primary); }
.btn.outline {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text-primary);
}
.btn.outline:hover { background: var(--bg-hover); }
.btn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn.danger:hover { background: color-mix(in oklab, var(--danger) 85%, #000); }
.btn.sm { padding: 6px 12px; font-size: 13px; }
.btn.icon { padding: 8px; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 999px;
  background: var(--bg-subtle);
  color: var(--text-secondary);
  white-space: nowrap;
}
.chip.success { background: var(--success-soft); color: var(--success); }
.chip.warning { background: var(--warning-soft); color: var(--warning); }
.chip.danger { background: var(--danger-soft); color: var(--danger); }
.chip.info { background: var(--info-soft); color: var(--info); }
.chip.accent { background: var(--accent-soft); color: var(--accent-text); }
.chip.purple { background: var(--purple-soft); color: var(--purple); }
.card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.input, .select, .textarea {
  width: 100%;
  padding: 10px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 14px;
  transition: all var(--duration-fast) var(--ease-smooth);
  outline: none;
  font-family: inherit;
}
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.input::placeholder, .textarea::placeholder { color: var(--text-muted); }
.label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.divider {
  height: 1px;
  background: var(--border);
  margin: 16px 0;
}
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
/* ============================================
   Sidebar
   ============================================ */
.sidebar {
  width: 260px;
  background: var(--bg-sidebar);
  border-inline-start: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex-shrink: 0;
}
.sidebar-logo {
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 10px;
  padding: 8px 4px 10px 18px;
}
.logo-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-start;
  text-decoration: none;
  width: 100%;
  height: 88px;
  overflow: hidden;
  margin-inline-start: auto;
  margin-inline-end: 0;
  text-align: start;
  background: transparent;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
  border: 0;
}
/* V-Logo (ADR-070): width set inline by the ModirifyLogo component
   (size=lg → 220px). Wrapper only owns positioning + the slight
   nudge that visually centers the wordmark inside the sidebar gutter. */
.logo-wrap .modirify-logo {
  margin-inline-start: auto;
  margin-inline-end: 0;
  object-position: top right;
  transform: translateX(10px) translateY(-2px);
}
.sidebar-logo-mark {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 18px;
  flex-shrink: 0;
}
[data-theme="luxe"] .sidebar-logo-mark { color: #0b1020; }
.sidebar-logo-title { font-weight: 800; font-size: 15px; color: var(--text-primary); line-height: 1.2; }
.sidebar-logo-sub { font-size: 11px; color: var(--text-tertiary); }
/* V-Logo (ADR-070) — Unified ModirifyLogo base styles.
   Component lives in app/src/ui/logo.jsx and sets width inline via
   the LOGO_SIZES scale (xs=80, sm=140, md=200, lg=220, xl=280).
   These base styles give every instance the same display/object
   behavior + a smooth width transition so the brand "breathes"
   between contexts (login → onboarding → sidebar). */
.modirify-logo {
  display: block;
  height: auto;
  max-width: 100%;
  object-fit: contain;
  object-position: center;
  transition: var(--logo-transition);
}
@media (prefers-reduced-motion: reduce) {
  .modirify-logo { transition: none; }
}
.sidebar-group-label {
  padding: 16px 20px 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  text-transform: uppercase;
}
.nav-items {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 10px;
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-weight: 500;
  font-size: 14px;
  cursor: pointer;
  border: none;
  background: transparent;
  text-align: start;
  width: 100%;
  transition: all var(--duration-fast) var(--ease-smooth);
  font-family: inherit;
}
.nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.nav-item.active {
  background: var(--accent-soft);
  color: var(--accent-text);
  font-weight: 700;
}
[data-theme="luxe"] .nav-item.active { background: var(--bg-hover); color: var(--accent); }
.nav-item .icon-box {
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.nav-item .badge-count {
  margin-inline-start: auto;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  min-width: 20px;
  text-align: center;
}
[data-theme="luxe"] .nav-item .badge-count { color: #0b1020; }
/* ADR-145 F3: legal links cluster sitting between the mini-stats card
   and the avatar row. Small (11px), muted, single line on desktop;
   wraps on narrow rails without breaking the layout. The dots are
   visual separators marked aria-hidden so screen readers skip them. */
.sidebar-legal {
  padding: 6px 14px 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
  font-size: 11px;
  color: var(--text-tertiary);
  border-top: 1px solid var(--border);
  opacity: 0.85;
}
.sidebar-legal a {
  color: var(--text-tertiary);
  text-decoration: none;
  padding: 2px 4px;
  border-radius: 4px;
  transition: color 160ms ease, background 160ms ease;
}
.sidebar-legal a:hover,
.sidebar-legal a:focus-visible {
  color: var(--accent);
  background: var(--bg-subtle);
  outline: none;
}
.sidebar-legal span[aria-hidden] {
  opacity: 0.4;
  user-select: none;
}
.sidebar-footer {
  padding: 12px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
}
.avatar {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--accent), var(--info));
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  flex-shrink: 0;
  font-size: 14px;
}
.avatar.sm { width: 30px; height: 30px; font-size: 12px; border-radius: 8px; }
.avatar.xs { width: 24px; height: 24px; font-size: 10px; border-radius: 6px; }
.avatar.lg { width: 54px; height: 54px; font-size: 18px; border-radius: 14px; }
/* ============================================
   Topbar
   ============================================ */
.topbar {
  height: 64px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 24px;
  gap: 16px;
  flex-shrink: 0;
}
.topbar .search {
  flex: 1;
  max-width: 440px;
  position: relative;
}
.topbar .search input {
  width: 100%;
  padding: 9px 40px 9px 14px;
  background: var(--bg-subtle);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 13px;
  color: var(--text-primary);
  outline: none;
}
.topbar .search input:focus {
  background: var(--bg-elevated);
  border-color: var(--border-strong);
}
.topbar .search .search-icon {
  position: absolute;
  inset-inline-end: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-tertiary);
  pointer-events: none;
}
.topbar-actions { display: flex; align-items: center; gap: 8px; margin-inline-start: auto; }
.icon-btn {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid transparent;
  cursor: pointer;
  position: relative;
  transition: all var(--duration-fast) var(--ease-smooth);
}
.icon-btn:hover { background: var(--bg-subtle); color: var(--text-primary); }
.icon-btn .pulse-dot {
  position: absolute;
  top: 8px;
  inset-inline-end: 9px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  border: 2px solid var(--bg-elevated);
}
/* ============================================
   Page header
   ============================================ */
.page-header {
  padding: 24px 32px 8px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.page-title {
  font-size: 24px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}
.page-subtitle {
  font-size: 13px;
  color: var(--text-tertiary);
  margin-top: 4px;
}
.page-content {
  padding: 16px 32px 32px;
}
/* ============================================
   Grid helpers
   ============================================ */
.grid { display: grid; gap: 16px; }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
.grid.cols-5 { grid-template-columns: repeat(5, 1fr); }
.grid.cols-6 { grid-template-columns: repeat(6, 1fr); }
.flex { display: flex; }
.flex.gap-8 { gap: 8px; }
.flex.gap-12 { gap: 12px; }
.flex.gap-16 { gap: 16px; }
.flex.ai-c { align-items: center; }
.flex.jc-sb { justify-content: space-between; }
.flex.wrap { flex-wrap: wrap; }
/* ============================================
   Animations
   ============================================ */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes slideIn {
  from { opacity: 0; transform: translateX(-20px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}
/* accountingBackdropIn keyframe consolidated into backdropIn (V-Interaction/3, ADR-064) — identical opacity-only fade */
@keyframes accountingModalIn {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.975) translateY(12px); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1) translateY(0); }
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
.fade-in { animation: fadeIn 0.25s ease-out; }
.scale-in { animation: scaleIn var(--duration-base) var(--ease-out); }
.accounting-backdrop { animation: backdropIn var(--duration-base) var(--ease-out); }
.accounting-modal { animation: accountingModalIn 0.22s cubic-bezier(0.2, 0.85, 0.25, 1) both; will-change: transform, opacity; }
/* ============================================
   Modal — Glass Morphism Style
   ============================================ */
@keyframes modalIn {
  from { opacity: 0; transform: translateY(18px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}
@keyframes backdropIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.65);
  backdrop-filter: blur(var(--glass-blur-sm));
  -webkit-backdrop-filter: blur(var(--glass-blur-sm));
  display: grid;
  place-items: center;
  z-index: 100;
  animation: backdropIn var(--duration-base) var(--ease-out);
}
[data-theme="luxe"] .modal-backdrop,
[data-theme="midnight"] .modal-backdrop { background: rgba(0, 0, 0, 0.55); }
/* Glass card — used by .modal AND .modal-box. Glass values come
   from tokens.css (--glass-bg / --glass-blur / --glass-border /
   --glass-shadow); dark themes auto-switch via [data-theme] overrides
   in tokens.css, so no per-theme block is needed here (ADR-017). */
.modal, .modal-box {
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--glass-shadow);
  max-width: 600px;
  width: calc(100vw - 40px);
  max-height: calc(100dvh - 80px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: modalIn 0.28s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.modal.lg, .modal-lg  { max-width: 760px; }
.modal.xl, .modal-xl  { max-width: 1100px; }
.modal-header {
  padding: 20px 24px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.07);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
[data-theme="luxe"] .modal-header,
[data-theme="midnight"] .modal-header { border-bottom-color: rgba(255,255,255,0.07); }
.modal-title { font-size: 18px; font-weight: 800; color: var(--text-primary); }
.modal-body { padding: 24px; overflow-y: auto; flex: 1; }
.modal-footer {
  padding: 16px 24px;
  border-top: 1px solid rgba(0, 0, 0, 0.07);
  display: flex;
  gap: 8px;
  justify-content: flex-start;
}
[data-theme="luxe"] .modal-footer,
[data-theme="midnight"] .modal-footer { border-top-color: rgba(255,255,255,0.07); }
/* Accounting modals — override .card with glass tokens (ADR-017) */
.accounting-modal {
  background: var(--glass-bg) !important;
  backdrop-filter: blur(var(--glass-blur)) !important;
  -webkit-backdrop-filter: blur(var(--glass-blur)) !important;
  border: 1px solid var(--glass-border) !important;
  box-shadow: var(--glass-shadow) !important;
  border-radius: var(--radius-xl) !important;
}
/* ============================================
   Glass Modal Utility — for inline-style modals
   Add className="gm-bd" to backdrop, "gm-box" to modal box
   ============================================ */
.gm-bd {
  background: rgba(0, 0, 0, 0.22) !important;
  backdrop-filter: blur(var(--glass-blur-sm)) !important;
  -webkit-backdrop-filter: blur(var(--glass-blur-sm)) !important;
}
[data-theme="luxe"] .gm-bd,
[data-theme="midnight"] .gm-bd { background: rgba(0, 0, 0, 0.55) !important; }
.gm-box {
  background: var(--glass-bg) !important;
  backdrop-filter: blur(var(--glass-blur)) !important;
  -webkit-backdrop-filter: blur(var(--glass-blur)) !important;
  border: 1px solid var(--glass-border) !important;
  box-shadow: var(--glass-shadow) !important;
  border-radius: var(--radius-xl) !important;
  animation: modalIn 0.28s cubic-bezier(0.16, 1, 0.3, 1) both !important;
}
/* ============================================
   Tables
   ============================================ */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.data-table thead th {
  text-align: start;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-tertiary);
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--bg-subtle);
  white-space: nowrap;
}
.data-table tbody td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  color: var(--text-primary);
  vertical-align: middle;
}
.data-table tbody tr:hover { background: var(--bg-hover); }
.data-table tbody tr:last-child td { border-bottom: none; }
/* ============================================
   Tweaks panel
   ============================================ */
.tweaks-panel {
  position: fixed;
  bottom: 20px;
  inset-inline-start: 20px;
  width: 280px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 16px;
  z-index: 1000;
  animation: scaleIn var(--duration-base) var(--ease-out);
}
.tweaks-panel h4 {
  font-size: 13px;
  font-weight: 800;
  color: var(--text-primary);
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.tweak-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
}
.tweak-row .label-txt { font-size: 12px; color: var(--text-secondary); font-weight: 500; }
/* U-8: dev-only theme grid inside Tweaks panel (6 swatches) */
.tweak-theme-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.tweak-theme-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 4px;
  background: transparent;
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--duration-fast), background var(--duration-fast), transform var(--duration-fast);
}
.tweak-theme-item:hover { background: var(--bg-hover); transform: translateY(var(--lift-1)); }
.tweak-theme-item.active { border-color: var(--accent); background: var(--bg-hover); }
.tweak-theme-item:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow);
}
.tweak-theme-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(0,0,0,.08);
  flex-shrink: 0;
}
.tweak-theme-label {
  font-size: 9px;
  font-weight: 600;
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.2;
}
.theme-swatches { display: flex; gap: 6px; }
.theme-swatch {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  cursor: pointer;
  border: 2px solid transparent;
  transition: all var(--duration-fast) var(--ease-smooth);
  position: relative;
}
.theme-swatch.active { border-color: var(--accent); transform: scale(1.1); }
.theme-swatch[data-preview="clean"] { background: linear-gradient(135deg, #f4f7fa 50%, #0891b2 50%); }
.theme-swatch[data-preview="luxe"] { background: linear-gradient(135deg, #0b1020 50%, #d4af6f 50%); }
.theme-swatch[data-preview="warm"] { background: linear-gradient(135deg, #fbf6f1 50%, #c2675b 50%); }
/* ============================================
   Utility
   ============================================ */
.text-xs { font-size: 11px; }
.text-sm { font-size: 13px; }
.text-base { font-size: 14px; }
.text-lg { font-size: 16px; }
.text-xl { font-size: 20px; }
.text-2xl { font-size: 26px; }
.text-3xl { font-size: 32px; }
.font-bold { font-weight: 700; }
.font-extrabold { font-weight: 800; }
.text-secondary { color: var(--text-secondary); }
.text-tertiary { color: var(--text-tertiary); }
.text-muted { color: var(--text-muted); }
.text-success { color: var(--success); }
.text-danger { color: var(--danger); }
.text-accent { color: var(--accent); }
.mb-4 { margin-bottom: 4px; }
.mb-8 { margin-bottom: 8px; }
.mb-12 { margin-bottom: 12px; }
.mb-16 { margin-bottom: 16px; }
.mb-24 { margin-bottom: 24px; }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; }
.p-16 { padding: 16px; }
.p-20 { padding: 20px; }
.p-24 { padding: 24px; }
.w-full { width: 100%; }
.progress {
  height: 6px;
  background: var(--bg-subtle);
  border-radius: 999px;
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
  transition: width var(--duration-slow) var(--ease-smooth);
}
.kbd {
  display: inline-block;
  padding: 2px 6px;
  font-size: 11px;
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-tertiary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 4px;
}
/* Login screen specific */
.login-shell {
  width: 100%;
  height: 100dvh;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: var(--bg);
  overflow: hidden;
}
.login-hero {
  background: linear-gradient(135deg, var(--accent) 0%, var(--info) 100%);
  position: relative;
  overflow: hidden;
  color: #fff;
  padding: 48px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
[data-theme="luxe"] .login-hero {
  background: linear-gradient(135deg, #1a1f3a 0%, #2a2030 100%);
  color: var(--accent);
}
.login-form-side {
  display: grid;
  place-items: center;
  padding: 48px;
  overflow-y: auto;
}
.empty-state {
  padding: 48px 24px;
  text-align: center;
  color: var(--text-tertiary);
}
.empty-state-icon {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: var(--bg-subtle);
  display: grid;
  place-items: center;
  margin: 0 auto 16px;
  color: var(--text-muted);
}
/* Calendar */
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  background: var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
}
.calendar-day-header {
  background: var(--bg-subtle);
  padding: 10px;
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-tertiary);
  text-transform: uppercase;
}
.calendar-day {
  background: var(--bg-elevated);
  min-height: 90px;
  padding: 8px;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-smooth);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.calendar-day:hover { background: var(--bg-hover); }
.calendar-day.other-month { opacity: 0.4; }
.calendar-day.today .day-num {
  background: var(--accent);
  color: #fff;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
}
[data-theme="luxe"] .calendar-day.today .day-num { color: #0b1020; }
.day-num { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.event-pill {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--accent-soft);
  color: var(--accent-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.event-pill.warning { background: var(--warning-soft); color: var(--warning); }
.event-pill.success { background: var(--success-soft); color: var(--success); }
/* Appointment timeline */
.timeline {
  position: relative;
  padding-inline-end: 24px;
}
.timeline::before {
  content: "";
  position: absolute;
  inset-inline-end: 8px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: var(--border);
}
.timeline-item {
  position: relative;
  padding: 0 28px 20px 0;
}
.timeline-item::before {
  content: "";
  position: absolute;
  inset-inline-end: 4px;
  top: 6px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--bg-elevated);
}
/* KPI card */
.kpi {
  padding: 20px;
}
.kpi .label { font-size: 12px; color: var(--text-tertiary); font-weight: 600; margin: 0 0 8px; }
.kpi .value { font-size: 28px; font-weight: 800; color: var(--text-primary); line-height: 1; letter-spacing: -0.02em; }
.kpi .trend {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 700;
  margin-top: 8px;
}
.kpi .trend.up { color: var(--success); }
.kpi .trend.down { color: var(--danger); }
.kpi-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
/* Toast */
.toast {
  position: fixed;
  bottom: 24px;
  inset-inline-end: 24px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 14px 18px;
  z-index: 2000;
  display: flex;
  align-items: center;
  gap: 12px;
  animation: scaleIn var(--duration-base) var(--ease-out);
  font-weight: 600;
  color: var(--text-primary);
  font-size: 14px;
  max-width: 360px;
}
.toast.success { border-color: var(--success); }
.toast-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  background: var(--success-soft);
  color: var(--success);
  flex-shrink: 0;
}
/* Tabs */
.tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 20px;
  overflow-x: auto;
}
.tab {
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-tertiary);
  cursor: pointer;
  border: none;
  background: transparent;
  border-bottom: 2px solid transparent;
  transition: all var(--duration-fast) var(--ease-smooth);
  white-space: nowrap;
  font-family: inherit;
  margin-bottom: -1px;
}
.tab:hover { color: var(--text-primary); }
.tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.app-shell {
  flex: 1;
  width: 100%;
  height: 100%;
  display: flex;
}
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}
.main-content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}
@media (max-width: 1200px) {
  .sidebar {
    width: 224px;
  }
  .page-header {
    padding: 20px 24px 8px;
  }
  .page-content {
    padding: 14px 24px 24px;
  }
  .grid.cols-4 {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 1024px) {
  .topbar {
    padding: 0 16px;
    gap: 12px;
  }
  .topbar .search {
    max-width: 320px;
  }
  .page-title {
    font-size: 22px;
  }
  .grid.cols-3,
  .grid.cols-4 {
    grid-template-columns: repeat(2, 1fr);
  }
  .modal {
    width: calc(100vw - 24px);
    max-height: calc(100dvh - 32px);
  }
  .modal-header,
  .modal-body,
  .modal-footer {
    padding-inline: 18px;
  }
  .data-table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
    -webkit-overflow-scrolling: touch;
  }
}
@media (max-width: 768px) {
  html, body {
    overflow: auto;
  }
  #root,
  .app-root,
  .app-shell,
  .main,
  .main-shell {
    min-height: 100dvh;
    height: auto;
  }
  /* U-7/2 — the desktop sidebar is hidden on mobile; navigation moves
     into the MobileNav bottom-sheet (opened by the topbar hamburger). */
  .app-shell > .sidebar {
    display: none;
  }
  .topbar {
    height: auto;
    padding: 12px 16px;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
  }
  /* V-Mobile/BackStack: back-arrow (when present) sits before hamburger.
     Both are flex-shrink:0 so the title block always gets remaining
     width. Selectors are class-based (not nth-child) so the layout
     doesn't break when the conditional back-arrow toggles in/out. */
  .topbar > .topbar-back {
    order: -1;
    flex-shrink: 0;
  }
  /* Hamburger first, title block takes remaining width on the same row */
  .topbar > .topbar-hamburger {
    order: 0;
    flex-shrink: 0;
  }
  .topbar > .topbar-title-block {
    order: 1;
    flex: 1;
    min-width: 0;
  }
  .topbar .search {
    order: 3;
    width: 100%;
    max-width: none;
  }
  .topbar-actions {
    order: 4;
    width: 100%;
    margin-inline-start: 0;
    justify-content: flex-start;
    flex-wrap: wrap;
  }
  .page-header {
    padding: 16px 16px 8px;
    align-items: flex-start;
  }
  .page-title {
    font-size: 20px;
  }
  .page-subtitle {
    font-size: 12px;
  }
  .page-content {
    padding: 12px 16px 20px;
  }
  .grid.cols-2,
  .grid.cols-3,
  .grid.cols-4 {
    grid-template-columns: 1fr;
  }
  .modal-header,
  .modal-body,
  .modal-footer {
    padding: 16px;
  }
  .toast {
    inset-inline: 12px;
    bottom: 12px;
    max-width: none;
  }
  .tweaks-panel {
    width: calc(100vw - 24px);
    inset-inline-start: 12px;
    bottom: 72px;
  }
  .login-shell {
    grid-template-columns: 1fr;
    height: auto;
  }
  .login-hero {
    min-height: 240px;
    padding: 28px;
  }
  .login-form-side {
    padding: 24px 16px;
  }
}
@keyframes spin { to { transform: rotate(360deg); } }
/* ============================================================
   Kanban Board — العيادة اليوم
   ============================================================ */
.kanban-board {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 8px;
  align-items: start;
}
.kanban-col {
  min-width: 150px;
  max-width: 220px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.kanban-col-hdr {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 700;
  font-size: 12px;
  background: var(--bg-elevated);
}
.kanban-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 9px;
  background: var(--bg-elevated);
  transition: box-shadow var(--duration-base) var(--ease-smooth), transform var(--duration-base) var(--ease-smooth);
  cursor: default;
  font-size: 12px;
}
.kanban-card:hover {
  box-shadow: var(--shadow);
  transform: translateY(var(--lift-1));
}
.kanban-empty {
  text-align: center;
  color: var(--text-tertiary);
  padding: 16px 6px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  font-size: 11px;
}
/* ============================================================
   WhatsApp Reminders
   ============================================================ */
.btn.wa-green {
  background: #25D366;
  color: #fff;
  border-color: #25D366;
}
.btn.wa-green:hover {
  background: #1da851;
  border-color: #1da851;
}
.wa-template-preview {
  background: #dcfce7;
  border: 1px solid #bbf7d0;
  border-radius: 12px 12px 12px 4px;
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.8;
  color: #065f46;
  white-space: pre-line;
}
.wa-template-preview::before {
  content: 'نص الرسالة';
  display: block;
  font-size: 10px;
  font-weight: 700;
  color: #16a34a;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: 8px;
}
.wa-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 14px;
}
.wa-stat {
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  border-radius: var(--radius);
  padding: 12px 14px;
}
.wa-stat-label {
  font-size: 11px;
  color: var(--text-tertiary);
  margin-bottom: 6px;
}
.wa-stat-value {
  font-size: 22px;
  font-weight: 800;
  color: var(--text-primary);
}
.wa-template-editor {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: 12px;
}
.wa-variable-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.wa-variable-chip {
  border: 1px dashed #86efac;
  background: #f0fdf4;
  color: #166534;
  border-radius: 999px;
  padding: 8px 10px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.wa-variable-chip:hover {
  background: #dcfce7;
}
.wa-recipient-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-hover);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease-smooth), box-shadow var(--duration-base) var(--ease-smooth), transform var(--duration-base) var(--ease-smooth);
}
.wa-recipient-row:hover {
  transform: translateY(var(--lift-1));
}
.wa-recipient-row.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}
@media (max-width: 900px) {
  .wa-stats,
  .wa-template-editor {
    grid-template-columns: 1fr;
  }
}
/* ============================================================
   Lab Orders
   ============================================================ */
.chip.lab-pending { background: var(--warning-soft); color: var(--warning); }
.chip.lab-sent    { background: var(--info-soft);    color: var(--info);    }
.chip.lab-done    { background: var(--success-soft); color: var(--success); }
.chip.lab-late    { background: var(--danger-soft);  color: var(--danger);  font-weight: 800; }
.data-table tbody tr.lab-late-row td {
  background: color-mix(in srgb, var(--danger-soft) 40%, transparent);
}
.data-table tbody tr.lab-late-row:hover td {
  background: var(--danger-soft);
}
/* Wave 2a (V-Patients/4) — patient rows with outstanding debt get a
   subtle red leading edge. The .patients-table mobile-card sibling
   inherits the same accent via .dt-card.patient-row-debt rule below. */
.data-table tbody tr.patient-row-debt > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--danger);
}
[dir="rtl"] .data-table tbody tr.patient-row-debt > td:first-child {
  box-shadow: inset -3px 0 0 0 var(--danger);
}
.dt-card.patient-row-debt {
  border-inline-start: 3px solid var(--danger);
}
/* Wave 2b (V-Billing/6) — invoice rows get a leading edge keyed to
   status: paid=success / partial=accent / unpaid=danger. Applied to
   both the desktop table row's first cell AND the mobile card's
   border-inline-start so the visual cue carries across viewports. */
.data-table tbody tr.billing-row--paid    > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--success);
}
.data-table tbody tr.billing-row--partial > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--accent);
}
.data-table tbody tr.billing-row--unpaid  > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--danger);
}
[dir="rtl"] .data-table tbody tr.billing-row--paid    > td:first-child {
  box-shadow: inset -3px 0 0 0 var(--success);
}
[dir="rtl"] .data-table tbody tr.billing-row--partial > td:first-child {
  box-shadow: inset -3px 0 0 0 var(--accent);
}
[dir="rtl"] .data-table tbody tr.billing-row--unpaid  > td:first-child {
  box-shadow: inset -3px 0 0 0 var(--danger);
}
.dt-card.billing-row--paid    { border-inline-start: 3px solid var(--success); }
.dt-card.billing-row--partial { border-inline-start: 3px solid var(--accent); }
.dt-card.billing-row--unpaid  { border-inline-start: 3px solid var(--danger); }
/* Wave 2d (V-Inventory/5) — inventory rows get a leading edge keyed
   to stock status: out=danger / low=warning. Available rows stay
   neutral (no border). Applied to both desktop table row first-cell
   AND mobile card border-inline-start. */
.data-table tbody tr.inv-row--out > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--danger);
}
.data-table tbody tr.inv-row--low > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--warning);
}
[dir="rtl"] .data-table tbody tr.inv-row--out > td:first-child {
  box-shadow: inset -3px 0 0 0 var(--danger);
}
[dir="rtl"] .data-table tbody tr.inv-row--low > td:first-child {
  box-shadow: inset -3px 0 0 0 var(--warning);
}
.dt-card.inv-row--out { border-inline-start: 3px solid var(--danger); }
.dt-card.inv-row--low { border-inline-start: 3px solid var(--warning); }
/* ============================================================
   UI Consistency Pass
   Shared visual polish only. Keep behavior and data contracts intact.
   ============================================================ */
:where(.btn, .icon-btn, .nav-item, .tab, .input, .select, .textarea) {
  -webkit-tap-highlight-color: transparent;
}
.btn {
  min-height: 42px;
  line-height: 1.25;
}
.btn.sm {
  min-height: 34px;
}
.btn.icon {
  min-width: 40px;
  min-height: 40px;
}
.btn svg,
.icon-btn svg,
.nav-item svg {
  flex-shrink: 0;
}
.btn:disabled,
.icon-btn:disabled,
.nav-item:disabled {
  opacity: .55;
  cursor: not-allowed;
  box-shadow: none;
}
/* U-10/2: legacy outline-based focus rule removed. Canonical
   --ring-shadow rule now lives at line ~4573 (Unified focus rings)
   and explicitly includes .icon-btn + .nav-item. */
.input,
.select,
.textarea {
  min-height: 42px;
  line-height: 1.45;
}
.textarea {
  min-height: 92px;
  resize: vertical;
}
.input:disabled,
.select:disabled,
.textarea:disabled {
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  cursor: not-allowed;
  opacity: 1;
}
.card {
  transition: border-color var(--duration-fast) var(--ease-smooth), box-shadow var(--duration-fast) var(--ease-smooth), background-color var(--duration-fast) var(--ease-smooth);
}
.card:focus-within {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-soft) 80%, transparent);
}
.page-title {
  line-height: 1.25;
  letter-spacing: 0;
}
.page-subtitle {
  line-height: 1.6;
}
.page-header > *,
.topbar > * {
  min-width: 0;
}
.page-header .flex {
  flex-wrap: wrap;
}
.topbar .search input {
  min-height: 40px;
}
.topbar .search input::placeholder {
  color: var(--text-muted);
}
.nav-item {
  line-height: 1.35;
}
.nav-item > span:not(.icon-box):not(.badge-count) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.data-table {
  border-spacing: 0;
}
.data-table thead th {
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
}
.data-table tbody td {
  line-height: 1.55;
}
.data-table tbody tr {
  transition: background-color var(--duration-fast) var(--ease-smooth);
}
.data-table .icon-btn {
  width: 34px;
  height: 34px;
  border-radius: 9px;
}
.tabs {
  gap: 6px;
  scrollbar-width: thin;
}
.tab {
  min-height: 42px;
  line-height: 1.35;
  white-space: nowrap;
}
.empty-state {
  min-height: 180px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 8px;
  line-height: 1.6;
}
.empty-state-icon {
  box-shadow: inset 0 0 0 1px var(--border);
}
.kpi .value {
  line-height: 1.15;
}
.kpi .trend,
.toast,
.event-pill,
.modal-title {
  line-height: 1.4;
}
.modal-body {
  overscroll-behavior: contain;
}
.modal-footer {
  flex-wrap: wrap;
}
.chip {
  line-height: 1.35;
}
.calendar-day {
  min-width: 0;
}
@media (max-width: 1200px) {
  .grid.cols-5,
  .grid.cols-6 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (max-width: 1024px) {
  .grid.cols-5,
  .grid.cols-6 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 768px) {
  .logo-wrap {
    height: 64px;
    justify-content: center;
  }

  .logo-wrap img {
    width: 158px;
    transform: none;
    object-position: center right;
  }

  .grid.cols-5,
  .grid.cols-6 {
    grid-template-columns: 1fr;
  }

  .btn {
    min-height: 40px;
    padding: 9px 13px;
  }

  .data-table thead th,
  .data-table tbody td {
    padding: 12px;
  }

  .calendar-day {
    min-height: 78px;
  }

  .modal-footer .btn {
    flex: 1 1 120px;
  }
}
@media (max-width: 520px) {
  .page-header .flex,
  .topbar-actions {
    gap: 6px;
  }

  .chip {
    max-width: 100%;
    white-space: normal;
  }

  .calendar-day {
    min-height: 70px;
    padding: 6px;
  }
}
/* ============================================================
   Marketing UI Refresh - safe visual layer from Lovable
   ============================================================ */
/* ============================================================
   MARKETING SCREEN — UI/UX REFRESH
   Append this file after styles.css. Uses existing tokens only.
   Works with all themes (clean, luxe, warm, sage, ocean, blush,
   midnight, desert, violet).
   ============================================================ */
/* -- Layout shell -------------------------------------------- */
.mk-shell { display: grid; gap: 18px; }
.mk-hero {
  position: relative;
  padding: 22px 24px;
  border-radius: var(--radius-xl);
  background:
    linear-gradient(135deg,
      color-mix(in oklab, var(--accent) 12%, var(--bg-card)) 0%,
      var(--bg-card) 60%);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.mk-hero-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; position: relative; z-index: 1;
}
.mk-hero-title {
  font-size: 24px; font-weight: 900; color: var(--text-primary);
  letter-spacing: 0; line-height: 1.2;
}
.mk-hero-sub {
  margin-top: 6px; color: var(--text-secondary); font-size: 13.5px; line-height: 1.7;
}
.mk-hero-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* -- Stepper -------------------------------------------------- */
.mk-stepper {
  margin-top: 18px; position: relative; z-index: 1;
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px;
}
.mk-step {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--radius);
  background: color-mix(in oklab, var(--bg-card) 78%, transparent);
  border: 1px solid var(--border); min-width: 0;
}
.mk-step.is-done { border-color: color-mix(in oklab, var(--success) 50%, var(--border)); }
.mk-step.is-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 18%, transparent);
}
.mk-step .mk-step-num {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; font-weight: 900; font-size: 12px;
  background: var(--bg-subtle); color: var(--text-secondary);
  border: 1px solid var(--border);
}
.mk-step.is-done .mk-step-num { background: var(--success-soft); color: var(--success); border-color: transparent; }
.mk-step.is-active .mk-step-num { background: var(--accent); color: #fff; border-color: transparent; }
[data-theme="luxe"] .mk-step.is-active .mk-step-num,
[data-theme="midnight"] .mk-step.is-active .mk-step-num { color: #0b1020; }
.mk-step-body { min-width: 0; }
.mk-step-label { font-size: 11.5px; color: var(--text-tertiary); font-weight: 700; }
.mk-step-value {
  font-size: 13px; font-weight: 800; color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 1100px) { .mk-stepper { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .mk-stepper { grid-template-columns: 1fr; } }
/* -- Section card -------------------------------------------- */
.mk-section {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.mk-section-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--bg-card), color-mix(in oklab, var(--bg-card) 92%, var(--bg-subtle)));
}
.mk-section-head h3 {
  font-size: 15px; font-weight: 800; color: var(--text-primary); margin: 0;
  display: flex; align-items: center; gap: 8px;
}
.mk-section-head .mk-section-icon {
  width: 32px; height: 32px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-text);
}
.mk-section-sub { font-size: 12px; color: var(--text-tertiary); margin-top: 3px; }
.mk-section-body { padding: 18px; }
.mk-section-body.tight { padding: 14px 18px; }
/* -- KPI strip ----------------------------------------------- */
.mk-kpis {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.mk-kpi {
  position: relative; padding: 14px 14px 14px 16px;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg-card); transition: transform var(--duration-fast) var(--ease-smooth), border-color var(--duration-fast) var(--ease-smooth);
}
.mk-kpi:hover { transform: translateY(var(--lift-1)); border-color: color-mix(in oklab, var(--accent) 35%, var(--border)); }
.mk-kpi-label { font-size: 11.5px; color: var(--text-tertiary); font-weight: 700; }
.mk-kpi-value { font-size: 22px; font-weight: 900; color: var(--text-primary); margin-top: 4px; line-height: 1.1; }
.mk-kpi-hint  { font-size: 11px; color: var(--text-tertiary); margin-top: 4px; }
.mk-kpi-hint.is-danger { color: var(--danger); }
.mk-kpi-bar {
  position: absolute; inset-inline-start: 0; inset-block: 10px;
  width: 3px; border-radius: 3px; background: var(--accent); opacity: .85;
}
.mk-kpi.is-success .mk-kpi-bar { background: var(--success); }
.mk-kpi.is-warning .mk-kpi-bar { background: var(--warning); }
.mk-kpi.is-danger  .mk-kpi-bar { background: var(--danger); }
.mk-kpi.is-info    .mk-kpi-bar { background: var(--info); }
.mk-kpi.is-purple  .mk-kpi-bar { background: var(--purple); }
/* -- Channel chips (clickable) ------------------------------- */
.mk-channels { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.mk-channel {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg-subtle);
  font-size: 13px; font-weight: 700; color: var(--text-secondary);
  cursor: pointer; user-select: none; transition: all var(--duration-fast) var(--ease-smooth);
}
.mk-channel input { accent-color: var(--accent); }
.mk-channel:hover { background: var(--bg-hover); }
.mk-channel.is-active {
  background: var(--accent-soft); color: var(--accent-text);
  border-color: color-mix(in oklab, var(--accent) 50%, transparent);
}
.mk-channel.is-disabled { opacity: .55; cursor: not-allowed; }
.mk-channel .mk-channel-hint { font-size: 11px; color: var(--text-tertiary); font-weight: 600; }
/* -- Connection banner --------------------------------------- */
.mk-connect {
  margin-top: 14px; padding: 14px 16px;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg-subtle);
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.mk-connect.is-on {
  background: var(--success-soft);
  border-color: color-mix(in oklab, var(--success) 30%, var(--border));
}
.mk-connect.is-off { border-color: color-mix(in oklab, var(--warning) 30%, var(--border)); }
.mk-connect-title { font-weight: 900; color: var(--text-primary); display: flex; align-items: center; gap: 8px; }
.mk-connect-status-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--warning); box-shadow: 0 0 0 4px color-mix(in oklab, var(--warning) 18%, transparent);
}
.mk-connect.is-on .mk-connect-status-dot {
  background: var(--success); box-shadow: 0 0 0 4px color-mix(in oklab, var(--success) 18%, transparent);
}
.mk-connect-pages { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; width: 100%; }
.mk-connect-page {
  font-size: 12px; padding: 5px 10px; border-radius: 999px;
  background: var(--bg-card); border: 1px solid var(--border);
  color: var(--text-secondary);
}
/* -- Calendar ------------------------------------------------- */
.mk-cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
}
.mk-cal-head {
  text-align: center; font-size: 11.5px; font-weight: 800;
  color: var(--text-tertiary); padding: 6px 0;
}
.mk-cal-cell {
  min-height: 116px; padding: 8px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-card);
  display: flex; flex-direction: column; gap: 6px;
  transition: background var(--duration-fast) var(--ease-smooth), border-color var(--duration-fast) var(--ease-smooth);
}
.mk-cal-cell:not(.is-blank):hover { background: var(--bg-hover); }
.mk-cal-cell.is-blank { background: transparent; border-color: transparent; }
.mk-cal-cell.is-today { border-color: var(--accent); }
.mk-cal-cell.has-posts { cursor: pointer; }
.mk-cal-num { font-weight: 800; font-size: 13px; color: var(--text-primary); }
.mk-cal-count {
  font-size: 10.5px; padding: 2px 7px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-text); font-weight: 800;
}
.mk-cal-pill {
  border: 1px solid var(--border); border-radius: 8px;
  padding: 6px 8px; text-align: start;
  font-size: 11px; line-height: 1.4; color: var(--text-primary);
  background: var(--bg-subtle); cursor: pointer; overflow: hidden;
  display: grid; gap: 2px;
}
.mk-cal-pill.is-published { background: var(--success-soft); }
.mk-cal-pill.is-approved  { background: color-mix(in oklab, var(--success) 12%, var(--bg-card)); }
.mk-cal-pill.is-error     { background: var(--danger-soft); border-color: var(--danger); }
.mk-cal-pill.is-generating{ background: var(--accent-soft); border-color: var(--accent); }
.mk-cal-pill.is-image     { background-size: cover; background-position: center; }
.mk-cal-pill .mk-cal-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mk-cal-pill .mk-cal-pill-status { font-size: 10px; font-weight: 900; }
.mk-cal-more { font-size: 11px; color: var(--text-tertiary); }
/* -- Detail sidebar ------------------------------------------ */
.mk-detail { position: sticky; top: 12px; }
.mk-detail-meta {
  display: grid; gap: 8px; margin: 12px 0;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
.mk-detail-meta .mk-meta-cell {
  padding: 9px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-subtle);
}
.mk-detail-meta .mk-meta-label { font-size: 11px; color: var(--text-tertiary); }
.mk-detail-meta .mk-meta-value { font-weight: 800; margin-top: 4px; font-size: 13px; color: var(--text-primary); }
.mk-image-empty {
  min-height: 220px; padding: 18px;
  border: 1px dashed color-mix(in oklab, var(--accent) 45%, var(--border));
  border-radius: var(--radius);
  background:
    radial-gradient(120% 80% at 0% 0%, color-mix(in oklab, var(--accent) 14%, transparent), transparent 60%),
    var(--bg-subtle);
  display: flex; flex-direction: column; gap: 10px;
}
.mk-image-empty-title {
  display: flex; align-items: center; gap: 8px;
  color: var(--accent-text); font-weight: 900;
}
.mk-image-empty-prompt { color: var(--text-secondary); line-height: 1.7; font-size: 13px; }
.mk-action-row {
  display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px;
  padding-top: 14px; border-top: 1px dashed var(--border);
}
/* -- Reason / hint blocks ------------------------------------ */
.mk-reason {
  margin-top: 12px; padding: 12px 14px; border-radius: var(--radius);
  background: var(--accent-soft); color: var(--text-secondary);
  line-height: 1.7; font-size: 13px;
  border-inline-start: 3px solid var(--accent);
}
.mk-error-banner {
  margin-top: 10px; padding: 12px 14px; border-radius: var(--radius);
  background: var(--danger-soft); color: var(--danger);
  font-weight: 800; font-size: 13px; line-height: 1.7;
  border-inline-start: 3px solid var(--danger);
}
/* -- Empty / loading ----------------------------------------- */
.mk-empty {
  padding: 44px 22px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.mk-empty-icon {
  width: 64px; height: 64px; border-radius: 20px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-text);
  margin-bottom: 6px;
}
.mk-empty-title { font-weight: 900; font-size: 18px; color: var(--text-primary); }
.mk-empty-text { color: var(--text-secondary); max-width: 460px; line-height: 1.7; }
.mk-loading {
  padding: 36px; text-align: center; color: var(--text-secondary);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.mk-spin { animation: mkSpin 1s linear infinite; }
@keyframes mkSpin { to { transform: rotate(360deg); } }
/* -- Brand identity ------------------------------------------ */
.mk-brand-grid {
  display: grid; gap: 14px;
  grid-template-columns: minmax(0, 1.2fr) minmax(280px, .8fr);
  align-items: start;
}
@media (max-width: 900px) { .mk-brand-grid { grid-template-columns: 1fr; } }
.mk-color-pick {
  display: grid; grid-template-columns: 44px 1fr; gap: 8px;
}
.mk-color-pick input[type="color"] {
  width: 44px; height: 40px; padding: 2px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg-card); cursor: pointer;
}
.mk-asset-box {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px; background: var(--bg-subtle);
}
.mk-asset-grid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
}
.mk-asset-tile {
  position: relative; border: 1px solid var(--border);
  border-radius: 10px; overflow: hidden; background: var(--bg-card);
}
.mk-asset-tile img { display: block; width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.mk-asset-tile .mk-asset-remove {
  position: absolute; top: 4px; inset-inline-end: 4px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: rgba(255,255,255,.92); border: 1px solid var(--border);
  color: var(--text-primary);
}
.mk-asset-label {
  padding: 4px 6px; font-size: 10px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* -- Two-column main grid ------------------------------------ */
.mk-main {
  display: grid; gap: 16px;
  grid-template-columns: minmax(0, 1.15fr) minmax(340px, .85fr);
  align-items: start;
}
@media (max-width: 1100px) { .mk-main { grid-template-columns: 1fr; } .mk-detail { position: static; } }
/* -- Status pill (top) --------------------------------------- */
.mk-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 800;
  background: var(--bg-subtle); color: var(--text-secondary);
  border: 1px solid var(--border);
}
.mk-pill .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.mk-pill.is-success { background: var(--success-soft); color: var(--success); border-color: transparent; }
.mk-pill.is-warning { background: var(--warning-soft); color: var(--warning); border-color: transparent; }
.mk-pill.is-danger  { background: var(--danger-soft);  color: var(--danger);  border-color: transparent; }
.mk-pill.is-accent  { background: var(--accent-soft);  color: var(--accent-text); border-color: transparent; }
/* -- Animations ---------------------------------------------- */
@keyframes mkPulse {
  0%,100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 35%, transparent); }
  50%     { box-shadow: 0 0 0 8px color-mix(in oklab, var(--accent) 0%, transparent); }
}
.mk-pulse { animation: mkPulse 1.4s ease-in-out infinite; }
@keyframes mkPostIn {
  from { opacity: 0; transform: translateY(4px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.mk-anim-in { animation: mkPostIn .22s ease both; }
/* ============================================================
   Marketing Screen — Concept V2 stylesheet
   Append AFTER marketing-ui.css (or replace it).
   100% built on existing CSS variables (--bg, --bg-card, --bg-subtle,
   --bg-elevated, --bg-hover, --border, --border-strong,
   --text-primary, --text-secondary, --text-tertiary, --text-muted,
   --accent, --accent-hover, --accent-soft, --accent-text,
   --success, --success-soft, --warning, --warning-soft,
   --danger, --danger-soft, --info, --info-soft, --purple, --purple-soft,
   --shadow, --shadow-sm, --shadow-lg, --radius, --radius-sm,
   --radius-lg, --radius-xl).
   RTL-first: written assuming dir="rtl" on <html>.
   ============================================================ */
.mk2-shell{display:flex;flex-direction:column;gap:14px;padding:14px;min-width:0}
/* ---------- ZONE 1+2 : HERO + ACTION CENTER ---------- */
/* V-Marketing/1 (ADR-056): .mk2-hero is now a structural 2-col grid —
   .dash-hero (left, inside .mk2-hero-main) provides the visual surface
   alongside .mk2-action-center (right, self-contained card). Dropped
   the wrapping gradient + border + padding + shadow that used to make
   the .mk2-hero card visible; without that, the new dash-hero shell
   would have looked like a card-in-card. */
.mk2-hero{
  display:grid;grid-template-columns:1fr 340px;gap:14px;
  position:relative;
}
.mk2-hero-main{min-width:0;position:relative;z-index:1;display:flex;flex-direction:column;gap:14px}
.mk2-hero-main .dash-hero{margin-bottom:0}
.mk2-hero-body{display:flex;flex-direction:column;gap:12px}
.mk2-hero-controls{flex-direction:row !important;align-items:center}
.mk2-hero-month{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:8px}
.mk2-month-input{
  background:var(--bg-subtle);border:1px solid var(--border);
  border-radius:var(--radius);padding:8px 12px;font-weight:700;
  color:var(--text-primary);font-size:13px;cursor:pointer;
}
.mk2-month-input:hover{border-color:var(--accent)}
.mk2-status-chip{
  display:inline-flex;align-items:center;gap:6px;padding:5px 12px;
  border-radius:999px;font-size:12px;font-weight:700;
  background:var(--bg-subtle);color:var(--text-secondary);border:1px solid var(--border);
}
.mk2-status-chip .dot{width:7px;height:7px;border-radius:50%;background:currentColor}
.mk2-status-chip.is-accent{background:var(--accent-soft);color:var(--accent-text);border-color:transparent}
.mk2-status-chip.is-success{background:var(--success-soft);color:var(--success);border-color:transparent}
.mk2-status-chip.is-danger{background:var(--danger-soft);color:var(--danger);border-color:transparent}
.mk2-status-chip.is-warning{background:var(--warning-soft);color:var(--warning);border-color:transparent}
.mk2-hero-title{
  font-size:30px;font-weight:900;letter-spacing:0;
  color:var(--text-primary);margin:6px 0 6px;line-height:1.15;
}
.mk2-hero-sub{color:var(--text-secondary);font-size:14px;line-height:1.7;margin:0 0 12px;max-width:62ch}
.mk2-progress{
  position:relative;height:10px;border-radius:999px;
  background:var(--bg-subtle);overflow:hidden;margin-bottom:14px;
  border:1px solid var(--border);
}
.mk2-progress-bar{
  height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--accent),var(--accent-hover));
  transition:width .6s cubic-bezier(.2,.8,.2,1);
}
.mk2-progress-text{
  position:absolute;inset-inline-start:12px;top:50%;transform:translateY(-50%);
  font-size:11px;font-weight:800;color:var(--text-primary);
  text-shadow:0 1px 2px rgba(255,255,255,.6);
}
.mk2-alerts{display:flex;flex-wrap:wrap;gap:8px}
.mk2-alert{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 12px;border-radius:999px;font-size:12px;font-weight:700;
  background:var(--bg-subtle);color:var(--text-secondary);border:1px solid var(--border);
}
.mk2-alert.is-warning{background:var(--warning-soft);color:var(--warning);border-color:transparent}
.mk2-alert.is-danger{background:var(--danger-soft);color:var(--danger);border-color:transparent}
.mk2-alert.is-info{background:var(--info-soft);color:var(--info);border-color:transparent}
.mk2-alert.is-accent{background:var(--accent-soft);color:var(--accent-text);border-color:transparent}
.mk2-alert.is-success{background:var(--success-soft);color:var(--success);border-color:transparent}
.mk2-readiness-card{
  margin-bottom:12px;padding:12px;border:1px solid var(--border);
  border-radius:var(--radius-lg);background:rgba(255,255,255,.72);
  box-shadow:var(--shadow-sm);
}
.mk2-readiness-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:10px}
.mk2-readiness-title{font-size:13px;font-weight:900;color:var(--text-primary)}
.mk2-readiness-sub{font-size:11px;color:var(--text-tertiary);margin-top:2px}
.mk2-readiness-score{font-size:24px;line-height:1;color:var(--accent-text)}
.mk2-readiness-bar{
  height:7px;border-radius:999px;background:var(--bg-subtle);
  overflow:hidden;border:1px solid var(--border);margin-bottom:10px;
}
.mk2-readiness-bar span{
  display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--accent),var(--accent-hover));
  transition:width .5s ease;
}
.mk2-readiness-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px}
.mk2-readiness-item{
  min-width:0;padding:8px 6px;border-radius:var(--radius-sm);
  background:var(--bg-subtle);border:1px solid transparent;text-align:center;
}
.mk2-readiness-value{display:block;font-size:15px;font-weight:900;color:var(--text-primary);line-height:1.1}
.mk2-readiness-label{display:block;margin-top:4px;font-size:10px;font-weight:700;color:var(--text-tertiary);overflow-wrap:anywhere}
.mk2-readiness-item.is-success .mk2-readiness-value{color:var(--success)}
.mk2-readiness-item.is-info .mk2-readiness-value{color:var(--info)}
.mk2-readiness-item.is-accent .mk2-readiness-value{color:var(--accent-text)}
.mk2-readiness-item.is-purple .mk2-readiness-value{color:var(--purple)}
.mk2-readiness-item.is-danger{background:var(--danger-soft)}
.mk2-readiness-item.is-danger .mk2-readiness-value{color:var(--danger)}
.mk2-setup-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin-top:12px}
.mk2-setup-card{
  display:flex;align-items:center;gap:9px;min-width:0;text-align:start;
  padding:10px 12px;border-radius:var(--radius);border:1px solid var(--border);
  background:var(--bg-card);color:var(--text-primary);cursor:pointer;
  transition:transform var(--duration-fast) var(--ease-smooth),border-color var(--duration-fast) var(--ease-smooth),background var(--duration-fast) var(--ease-smooth);
}
.mk2-setup-card:hover{transform:translateY(var(--lift-1));border-color:var(--accent);background:var(--bg-hover)}
.mk2-setup-icon{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;border-radius:9px;background:var(--bg-subtle);color:var(--accent-text);
}
.mk2-setup-copy{display:flex;flex-direction:column;min-width:0;flex:1}
.mk2-setup-title{font-size:12px;font-weight:900;color:var(--text-primary)}
.mk2-setup-status{font-size:11px;font-weight:700;color:var(--text-tertiary);margin-top:2px}
.mk2-setup-card.is-success .mk2-setup-status{color:var(--success)}
.mk2-setup-card.is-warning .mk2-setup-status{color:var(--warning)}
.mk2-setup-card.is-danger .mk2-setup-status{color:var(--danger)}
/* ---------- AI ACTION CENTER ---------- */
.mk2-action-center{
  background:var(--bg-card);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:16px;
  display:flex;flex-direction:column;gap:14px;position:relative;z-index:1;
}
.mk2-ac-header{display:flex;align-items:center;gap:10px}
.mk2-ac-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:10px;
  background:var(--accent-soft);color:var(--accent-text);
}
.mk2-ac-title{font-weight:900;font-size:14px;color:var(--text-primary)}
.mk2-ac-sub{font-size:11px;color:var(--text-tertiary);margin-top:2px}
/* Plan C W2: credit balance banner inside the action center.
   ADR-074 amendment: gold-toned coin + count-up animation + status badge. */
.mk2-credit-banner{
  display:flex;flex-direction:column;gap:8px;
  padding:12px 14px;border-radius:var(--radius);
  border:1px solid var(--border);
  background:linear-gradient(135deg, var(--bg-subtle) 0%, var(--bg-card) 100%);
  position:relative;overflow:hidden;
  animation:mk2CreditIn 320ms var(--ease-out, ease-out) both;
}
.mk2-credit-banner::before{
  content:'';position:absolute;inset:0;
  background:linear-gradient(135deg, transparent 30%, rgba(245,158,11,.06) 100%);
  pointer-events:none;
}
.mk2-credit-banner.is-success{background:linear-gradient(135deg, var(--success-soft) 0%, var(--bg-card) 100%);border-color:var(--success);}
.mk2-credit-banner.is-warning{background:linear-gradient(135deg, var(--warning-soft) 0%, var(--bg-card) 100%);border-color:var(--warning);}
.mk2-credit-banner.is-danger{background:linear-gradient(135deg, var(--danger-soft) 0%, var(--bg-card) 100%);border-color:var(--danger);}
.mk2-credit-row{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:800;color:var(--text-primary);position:relative;z-index:1;}
/* ADR-074 (Polish): gold-toned coin icon with pulse on key-change. */
.mk2-credit-coin{
  display:inline-flex;align-items:center;justify-content:center;
  width:28px;height:28px;border-radius:50%;
  background:linear-gradient(135deg,#fbbf24 0%,#f59e0b 100%);
  color:#78350f;
  box-shadow:0 2px 8px rgba(245,158,11,.35), inset 0 1px 1px rgba(255,255,255,.4);
  flex-shrink:0;
  animation:mk2CoinPulse 600ms var(--ease-out, ease-out) both;
}
.mk2-credit-banner.is-danger .mk2-credit-coin{
  background:linear-gradient(135deg,#fca5a5 0%,#dc2626 100%);color:#fff;
  box-shadow:0 2px 8px rgba(220,38,38,.35), inset 0 1px 1px rgba(255,255,255,.3);
}
.mk2-credit-label{flex:1;}
.mk2-credit-badge{
  font-size:10px;font-weight:900;padding:2px 8px;border-radius:999px;
  background:var(--accent-soft);color:var(--accent-text);
  letter-spacing:.3px;
}
/* ADR-073 (G-3): explicit متبقى/من layout replaces ambiguous "12 / 2". */
.mk2-credit-numbers{font-size:13px;justify-content:flex-start;font-variant-numeric:tabular-nums;}
.mk2-credit-numbers .mk2-credit-remaining{
  font-size:22px;font-weight:900;color:var(--text-primary);
  margin:0 2px;padding:0 4px;
  animation:mk2NumberPop 360ms var(--ease-out, ease-out) both;
  display:inline-block;
}
.mk2-credit-banner.is-success .mk2-credit-numbers .mk2-credit-remaining{color:var(--success);}
.mk2-credit-banner.is-warning .mk2-credit-numbers .mk2-credit-remaining{color:var(--warning);}
.mk2-credit-banner.is-danger .mk2-credit-numbers .mk2-credit-remaining{color:var(--danger);}
.mk2-credit-numbers .mk2-credit-total{font-weight:700;color:var(--text-secondary);}
.mk2-credit-hint{font-size:11px;color:var(--text-tertiary);line-height:1.4;position:relative;z-index:1;}
/* ADR-075 §4: always-visible upgrade CTA inside the credit banner. */
.mk2-credit-upgrade-btn{
  display:inline-flex;align-items:center;gap:6px;
  margin-top:8px;padding:6px 12px;
  border:1px solid var(--accent);
  background:var(--bg-card);color:var(--accent);
  border-radius:999px;font-size:12px;font-weight:700;
  cursor:pointer;transition:all 160ms var(--ease-out, ease-out);
  position:relative;z-index:1;
}
.mk2-credit-upgrade-btn:hover{background:var(--accent);color:var(--bg-card);transform:translateY(var(--lift-1));}
.mk2-credit-banner.is-danger .mk2-credit-upgrade-btn{
  border-color:var(--danger);color:var(--danger);
  animation:mk2UpgradePulse 1.4s ease-in-out infinite;
}
.mk2-credit-banner.is-danger .mk2-credit-upgrade-btn:hover{background:var(--danger);color:var(--bg-card);}
@keyframes mk2UpgradePulse{
  0%,100%{box-shadow:0 0 0 0 rgba(220,38,38,0);}
  50%{box-shadow:0 0 0 4px rgba(220,38,38,.16);}
}
/* ADR-075 §3: Pre-generation confirm modal — cost transparency before
   the AI call commits credits. Three actions (All / Text only / Cancel)
   stack vertically on mobile, row on desktop. */
.mk2-confirm-body{display:flex;flex-direction:column;gap:14px;padding:4px;}
.mk2-confirm-headline{
  font-size:15px;font-weight:800;color:var(--text-primary);line-height:1.5;
}
.mk2-confirm-costs{
  display:flex;flex-direction:column;gap:6px;
  padding:12px 14px;border-radius:var(--radius-sm);
  background:var(--bg-subtle);border:1px solid var(--border-subtle, var(--border));
}
.mk2-confirm-cost-row{
  display:flex;align-items:center;gap:8px;
  font-size:13px;color:var(--text-secondary);
}
.mk2-confirm-cost-row strong{
  font-weight:900;color:var(--text-primary);font-variant-numeric:tabular-nums;
}
.mk2-confirm-cost-row.mk2-confirm-cost-sub{font-size:12px;color:var(--text-tertiary);}
.mk2-confirm-cost-row.mk2-confirm-cost-balance{
  margin-top:4px;padding-top:8px;border-top:1px dashed var(--border-subtle, var(--border));
  font-size:13px;color:var(--text-primary);font-weight:600;
}
.mk2-confirm-coin{color:#d97706;}
.mk2-confirm-warn{
  display:flex;align-items:flex-start;gap:8px;
  padding:10px 12px;border-radius:var(--radius-sm);
  background:var(--warning-soft);border-right:3px solid var(--warning);
  font-size:12px;color:var(--text-primary);line-height:1.6;
}
.mk2-confirm-warn.is-danger{
  background:var(--danger-soft);border-right-color:var(--danger);color:var(--danger);
}
.mk2-confirm-warn strong{font-weight:900;}
.mk2-confirm-actions{
  display:flex;flex-direction:column;gap:8px;margin-top:6px;
}
.mk2-confirm-actions .btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:10px 14px;font-size:14px;font-weight:700;
}
.mk2-confirm-btn-all{
  background:linear-gradient(135deg, var(--accent) 0%, var(--accent-strong, var(--accent)) 100%);
  color:#fff;border:none;
}
.mk2-confirm-btn-all.is-warning{
  background:linear-gradient(135deg, var(--warning) 0%, #f59e0b 100%);
}
.mk2-confirm-btn-all:hover:not(:disabled){transform:translateY(var(--lift-1));box-shadow:0 6px 20px rgba(14,165,183,.28);}
.mk2-confirm-btn-text{background:var(--bg-card);color:var(--text-primary);border:1px solid var(--border);}
.mk2-confirm-btn-text:hover:not(:disabled){background:var(--bg-subtle);}
.mk2-confirm-btn-cancel{background:transparent;color:var(--text-tertiary);border:none;}
.mk2-confirm-btn-cancel:hover{color:var(--text-secondary);}
.mk2-confirm-actions .btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none;}
.mk2-confirm-hint{
  font-size:11px;color:var(--text-tertiary);line-height:1.5;text-align:center;
  margin-top:2px;
}
/* ADR-073 (G-2) + ADR-074 polish: pre-flight cost preview chip. */
.mk2-cost-preview{
  display:flex;align-items:center;gap:8px;
  padding:8px 12px;border-radius:var(--radius-sm);
  background:var(--info-soft,var(--bg-subtle));border:1px dashed var(--info,var(--border));
  font-size:12px;color:var(--text-secondary);line-height:1.4;
  animation:mk2CostFadeIn 280ms var(--ease-out, ease-out) both;
}
.mk2-cost-preview.is-warning{
  background:var(--warning-soft);border-color:var(--warning);color:var(--text-primary);
  animation:mk2CostFadeIn 280ms var(--ease-out, ease-out) both, mk2CostWarn 1.2s ease-in-out 280ms;
}
.mk2-cost-preview .mk2-cost-icon{display:inline-flex;color:var(--accent);flex-shrink:0;}
.mk2-cost-preview.is-warning .mk2-cost-icon{color:var(--warning);}
.mk2-cost-text{display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px;}
.mk2-cost-amount{
  display:inline-flex;align-items:center;gap:4px;
  padding:2px 8px;border-radius:999px;
  background:rgba(245,158,11,.15);
  font-weight:900;
}
.mk2-cost-preview.is-warning .mk2-cost-amount{background:rgba(220,38,38,.18);}
.mk2-cost-coin{color:#d97706;display:inline-flex;align-items:center;}
.mk2-cost-preview.is-warning .mk2-cost-coin{color:var(--danger);}
.mk2-cost-warning{font-weight:800;color:var(--danger);}
.mk2-cost-preview strong{font-weight:900;font-variant-numeric:tabular-nums;}
@keyframes mk2CreditIn{
  from{opacity:0;transform:translateY(-4px) scale(.98);}
  to{opacity:1;transform:translateY(0) scale(1);}
}
@keyframes mk2CoinPulse{
  0%{transform:scale(.85) rotate(-12deg);opacity:0;}
  60%{transform:scale(1.12) rotate(6deg);opacity:1;}
  100%{transform:scale(1) rotate(0deg);opacity:1;}
}
@keyframes mk2NumberPop{
  0%{transform:scale(.7);opacity:0;}
  55%{transform:scale(1.18);opacity:1;}
  100%{transform:scale(1);opacity:1;}
}
@keyframes mk2CostFadeIn{
  from{opacity:0;transform:translateY(-4px);}
  to{opacity:1;transform:translateY(0);}
}
@keyframes mk2CostWarn{
  0%,100%{box-shadow:0 0 0 0 rgba(220,38,38,0);}
  50%{box-shadow:0 0 0 4px rgba(220,38,38,.18);}
}
/* ADR-074 (G-16 + G-29): Marketing Upgrade Modal — opens on 402. */
.mk-upgrade{display:flex;flex-direction:column;gap:18px;}
.mk-upgrade__lead{
  font-size:14px;color:var(--text-secondary);line-height:1.7;
  margin:0;padding:12px 14px;border-radius:var(--radius-sm);
  background:var(--warning-soft);border-right:3px solid var(--warning);
}
.mk-upgrade__error{
  display:flex;align-items:center;gap:8px;
  padding:10px 12px;border-radius:var(--radius-sm);
  background:var(--danger-soft);color:var(--danger);font-weight:700;font-size:13px;
}
.mk-upgrade__loading,.mk-upgrade__empty{
  display:flex;align-items:center;justify-content:center;gap:8px;
  padding:32px;color:var(--text-tertiary);font-size:13px;
}
.mk-upgrade__loading svg{animation:spin 1s linear infinite;}
.mk-upgrade__section{display:flex;flex-direction:column;gap:12px;}
.mk-upgrade__section-head{
  display:flex;align-items:center;gap:12px;
  padding-bottom:8px;border-bottom:1px solid var(--border);
}
.mk-upgrade__section-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;border-radius:10px;
  flex-shrink:0;
}
.mk-upgrade__plan-icon{
  background:linear-gradient(135deg,var(--accent),var(--accent-hover));color:#fff;
  box-shadow:0 2px 8px rgba(14,165,183,.3);
}
.mk-upgrade__pack-icon{
  background:linear-gradient(135deg,#fbbf24 0%,#f59e0b 100%);color:#78350f;
  box-shadow:0 2px 8px rgba(245,158,11,.35);
}
.mk-upgrade__section-title{font-weight:900;font-size:15px;color:var(--text-primary);}
.mk-upgrade__section-sub{font-size:12px;color:var(--text-tertiary);margin-top:2px;}
.mk-upgrade__cards{
  display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
}
.mk-upgrade__cards--packs{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));}
.mk-upgrade__card{
  position:relative;
  display:flex;flex-direction:column;gap:12px;
  padding:16px;border-radius:var(--radius);
  background:var(--bg-card);border:1px solid var(--border);
  transition:transform var(--duration-fast) var(--ease-smooth), box-shadow var(--duration-fast) var(--ease-smooth);
}
.mk-upgrade__card:hover{transform:translateY(var(--lift-1));box-shadow:0 8px 20px -8px rgba(0,0,0,.15);}
.mk-upgrade__card.is-highlighted{
  border-color:var(--accent);
  box-shadow:0 0 0 1px var(--accent),0 8px 24px -8px rgba(14,165,183,.4);
  background:linear-gradient(180deg,var(--accent-soft) 0%,var(--bg-card) 30%);
}
.mk-upgrade__badge{
  position:absolute;top:-9px;inset-inline-end:12px;
  padding:3px 10px;border-radius:999px;
  background:linear-gradient(135deg,var(--accent),var(--accent-hover));color:#fff;
  font-size:10px;font-weight:900;letter-spacing:.3px;
  box-shadow:0 4px 10px rgba(14,165,183,.3);
}
.mk-upgrade__card-title{font-size:16px;font-weight:900;color:var(--text-primary);}
.mk-upgrade__card-price{display:flex;align-items:baseline;gap:4px;color:var(--text-secondary);font-size:13px;}
.mk-upgrade__card-price strong{font-size:24px;font-weight:900;color:var(--text-primary);font-variant-numeric:tabular-nums;}
.mk-upgrade__card.is-highlighted .mk-upgrade__card-price strong{color:var(--accent);}
.mk-upgrade__features{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:6px;font-size:12px;color:var(--text-secondary);}
.mk-upgrade__features li{display:flex;align-items:center;gap:6px;}
.mk-upgrade__features li svg{color:var(--success);flex-shrink:0;}
.mk-upgrade__card .btn.w-full{width:100%;justify-content:center;}
.mk-upgrade__pack{
  display:flex;flex-direction:column;gap:8px;
  padding:14px;border-radius:var(--radius-sm);
  background:var(--bg-card);border:1px solid var(--border);
  transition:transform var(--duration-fast) var(--ease-smooth);
}
.mk-upgrade__pack:hover{transform:translateY(var(--lift-1));}
.mk-upgrade__pack-head{display:flex;align-items:center;gap:8px;}
.mk-upgrade__pack-coin{
  display:inline-flex;align-items:center;justify-content:center;
  width:26px;height:26px;border-radius:50%;
  background:linear-gradient(135deg,#fbbf24 0%,#f59e0b 100%);color:#78350f;
  flex-shrink:0;
}
.mk-upgrade__pack-title{font-weight:800;font-size:13px;color:var(--text-primary);}
.mk-upgrade__pack-credits{font-size:13px;color:var(--text-secondary);}
.mk-upgrade__pack-credits strong{font-size:18px;font-weight:900;color:var(--text-primary);font-variant-numeric:tabular-nums;}
.mk-upgrade__pack-price{font-size:14px;font-weight:900;color:var(--accent);font-variant-numeric:tabular-nums;}
.mk-upgrade__footer-note{
  display:flex;align-items:flex-start;gap:8px;
  padding:10px 12px;border-radius:var(--radius-sm);
  background:var(--bg-subtle);border:1px dashed var(--border);
  font-size:11px;color:var(--text-tertiary);line-height:1.5;
}
.mk-upgrade__footer-note svg{flex-shrink:0;margin-top:2px;color:var(--info,var(--accent));}
@media (max-width:560px){
  .mk-upgrade__cards{grid-template-columns:1fr;}
}
.mk2-next-action{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:14px 16px;border-radius:var(--radius);
  border:none;cursor:pointer;font-weight:800;font-size:14px;
  background:linear-gradient(135deg,var(--accent),var(--accent-hover));
  color:#fff;box-shadow:0 8px 20px -6px var(--accent);
  transition:transform var(--duration-fast) var(--ease-smooth), box-shadow var(--duration-fast) var(--ease-smooth);
}
.mk2-next-action:hover:not(:disabled){transform:translateY(var(--lift-1));box-shadow:0 12px 24px -8px var(--accent)}
.mk2-next-action:disabled{opacity:.6;cursor:not-allowed}
.mk2-next-action.is-warning{background:linear-gradient(135deg,var(--warning),#b45309)}
.mk2-next-action.is-danger{background:linear-gradient(135deg,var(--danger),#991b1b)}
.mk2-next-action.is-success{background:linear-gradient(135deg,var(--success),#047857)}
.mk2-next-action.is-info{background:linear-gradient(135deg,var(--info),#1e40af)}
.mk2-ac-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.mk2-ac-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:9px 10px;border-radius:var(--radius-sm);
  background:var(--bg-subtle);border:1px solid var(--border);
  color:var(--text-primary);font-size:12px;font-weight:700;cursor:pointer;
  transition:all var(--duration-fast) var(--ease-smooth);
}
.mk2-ac-btn:hover:not(:disabled){background:var(--bg-hover);border-color:var(--accent)}
.mk2-ac-btn:disabled{opacity:.5;cursor:not-allowed}
.mk2-ac-btn.is-danger{color:var(--danger);border-color:var(--danger)}
/* V-Marketing/4 (ADR-056): destructive subgroup separator + label */
.mk2-ac-destructive{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px dashed var(--border)}
.mk2-ac-destructive-label{font-size:10px;font-weight:800;color:var(--text-tertiary);letter-spacing:.04em;text-transform:none}
/* V-Finance/Pricing F-7 (ADR-057 follow-up): tabs row is the ONLY
   sticky surface. Pre-fix the hero + tabs both sat above an
   inner-scrolling .finance-content — so visually the hero stayed
   pinned at top (which the owner didn't want). New structure:
   .finance-shell flex column → .finance-tabs-wrap OUTSIDE the scroll
   (sticks at top) + .finance-scroll wraps hero + content (both scroll
   away). The date filter is hosted inside .finance-tabs-wrap so it
   stays accessible while scrolling. */
.finance-shell{display:flex;flex-direction:column;height:100%;background:var(--bg-primary)}
.finance-tabs-wrap{
  flex-shrink:0;display:flex;align-items:center;justify-content:space-between;
  gap:16px;padding:6px 14px 0;border-bottom:1px solid var(--border);
  background:var(--bg-primary);position:relative;z-index:5;
}
.finance-tabs-wrap .tabs{flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin}
.finance-tabs-date{flex-shrink:0;display:flex;align-items:center}
.finance-tabs-date > div{margin-bottom:0}
.finance-scroll{flex:1;overflow-y:auto;min-height:0;padding:14px}
.finance-scroll .dash-hero{margin-bottom:14px}
.finance-content{display:flex;flex-direction:column}
/* Wave 5: Mobile — stack tabs over date filter so all 5 tabs are
   reachable instead of sharing one row with the date pill. At <=720px
   the wrap flips to column: tabs row first (full width + horizontal
   scroll preserved), date filter row second (full-width pill). Both
   stay sticky inside .finance-shell. */
@media (max-width: 720px){
  .finance-tabs-wrap{
    flex-direction:column;align-items:stretch;gap:8px;padding:6px 12px 8px;
  }
  .finance-tabs-wrap .tabs{width:100%}
  .finance-tabs-date{justify-content:flex-start}
  .finance-tabs-date > div{width:100%}
  .finance-tabs-date .btn,
  .finance-tabs-date button{width:100%;justify-content:center}
}
/* V-Finance/5 (ADR-057): rich per-tab empty state — icon + title + hint
   (mirrors REC_KANBAN_EMPTY + MK_BOARD_EMPTY visual pattern). */
.fin-empty{
  display:flex;flex-direction:column;align-items:center;gap:6px;
  text-align:center;padding:48px 16px;color:var(--text-tertiary);
  font-size:12px;font-weight:700;
}
.fin-empty-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:14px;
  background:var(--bg-subtle);color:var(--text-tertiary);margin-bottom:4px;
}
.fin-empty-title{font-size:15px;font-weight:900;color:var(--text-primary)}
.fin-empty-hint{font-size:12px;font-weight:600;color:var(--text-tertiary);max-width:44ch;line-height:1.65}
.fin-empty.is-success .fin-empty-icon{background:var(--success-soft);color:var(--success)}
.fin-empty.is-accent  .fin-empty-icon{background:var(--accent-soft);color:var(--accent-text)}
.fin-empty.is-warning .fin-empty-icon{background:var(--warning-soft);color:var(--warning)}
.fin-empty.is-danger  .fin-empty-icon{background:var(--danger-soft);color:var(--danger)}
.fin-empty.is-muted   .fin-empty-icon{background:var(--bg-subtle);color:var(--text-tertiary)}
.mk2-kpi-strip{
  display:grid;grid-template-columns:repeat(4,1fr);gap:6px;
  padding-top:10px;border-top:1px dashed var(--border);
}
.mk2-kpi-strip .mk2-kpi:nth-child(5){grid-column:span 4}
.mk2-kpi{
  text-align:center;padding:10px 6px;border-radius:var(--radius-sm);
  background:var(--bg-subtle);
}
.mk2-kpi-num{font-weight:900;font-size:18px;color:var(--text-primary);line-height:1}
.mk2-kpi-lbl{font-size:10px;color:var(--text-tertiary);margin-top:4px;font-weight:700}
.mk2-kpi.is-success .mk2-kpi-num{color:var(--success)}
.mk2-kpi.is-info .mk2-kpi-num{color:var(--info)}
.mk2-kpi.is-purple .mk2-kpi-num{color:var(--purple)}
.mk2-kpi.is-danger .mk2-kpi-num{color:var(--danger)}
.mk2-ac-links{display:flex;flex-wrap:wrap;gap:6px}
.mk2-link{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 10px;border-radius:999px;
  background:transparent;border:1px solid var(--border);color:var(--text-secondary);
  font-size:11px;font-weight:700;cursor:pointer;transition:all var(--duration-fast) var(--ease-smooth);
}
.mk2-link:hover{border-color:var(--accent);color:var(--accent-text);background:var(--accent-soft)}
.mk2-conn-dot{width:7px;height:7px;border-radius:50%;background:var(--text-tertiary)}
.mk2-link.is-on .mk2-conn-dot{background:var(--success);box-shadow:0 0 8px var(--success)}
.mk2-link.is-off .mk2-conn-dot{background:var(--danger)}
/* ---------- ZONE 3 : WORKSPACE ---------- */
.mk2-workspace{
  display:flex;flex-direction:column;gap:12px;
  background:var(--bg-card);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:14px;
}
.mk2-ws-head{
  display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
}
.mk2-ws-titleblock{min-width:220px;flex:1}
.mk2-ws-title{font-size:18px;font-weight:900;color:var(--text-primary);margin:0 0 4px;line-height:1.25}
.mk2-ws-sub{font-size:12px;color:var(--text-tertiary);margin:0;line-height:1.6}
.mk2-ws-tabs{
  display:inline-flex;background:var(--bg-subtle);
  border-radius:var(--radius);padding:4px;border:1px solid var(--border);gap:2px;
}
.mk2-tab{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 14px;border-radius:calc(var(--radius) - 4px);
  background:transparent;border:none;cursor:pointer;
  color:var(--text-secondary);font-size:12px;font-weight:700;
  transition:all var(--duration-fast) var(--ease-smooth);
}
.mk2-tab:hover{color:var(--text-primary)}
.mk2-tab.is-active{background:var(--bg-card);color:var(--text-primary);box-shadow:var(--shadow-sm)}
.mk2-filter-row{
  display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;
  padding:8px 10px;border:1px solid var(--border);border-radius:var(--radius);
  background:var(--bg-subtle);
}
.mk2-filter-label{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:800;color:var(--text-secondary)}
.mk2-ws-filters{display:flex;flex-wrap:wrap;gap:6px}
.mk2-chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 10px;border-radius:999px;
  background:var(--bg-card);border:1px solid var(--border);
  color:var(--text-secondary);font-size:11px;font-weight:800;cursor:pointer;
  transition:all var(--duration-fast) var(--ease-smooth);
}
.mk2-chip:hover{border-color:var(--accent);color:var(--text-primary)}
.mk2-chip.is-active{background:var(--accent);color:#fff;border-color:transparent}
.mk2-chip.is-danger{color:var(--danger);border-color:var(--danger-soft)}
.mk2-chip.is-active.is-danger{background:var(--danger);color:#fff}
.mk2-chip-num{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:20px;height:18px;padding:0 6px;border-radius:999px;
  background:rgba(0,0,0,.08);font-size:10px;font-weight:900;
}
.mk2-chip.is-active .mk2-chip-num{background:rgba(255,255,255,.25)}
/* ---------- BOARD (Kanban) ---------- */
.mk2-board{
  display:grid;grid-template-columns:repeat(5,minmax(220px,1fr));
  gap:12px;overflow-x:auto;padding-bottom:6px;
}
.mk2-col{
  background:var(--bg-subtle);border:1px solid var(--border);
  border-radius:var(--radius);display:flex;flex-direction:column;min-height:300px;
}
.mk2-col-head{
  display:flex;align-items:center;gap:8px;padding:12px 14px;
  border-bottom:1px solid var(--border);
}
.mk2-col-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:6px;
  background:var(--bg-card);color:var(--text-secondary);
}
.mk2-col-title{font-weight:800;font-size:13px;color:var(--text-primary);flex:1}
.mk2-col-num{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:22px;height:20px;padding:0 7px;border-radius:999px;
  background:var(--bg-card);font-size:11px;font-weight:900;color:var(--text-secondary);
}
.mk2-col.is-published .mk2-col-icon{background:var(--purple-soft);color:var(--purple)}
.mk2-col.is-scheduled .mk2-col-icon{background:var(--info-soft);color:var(--info)}
.mk2-col.is-review .mk2-col-icon{background:var(--success-soft);color:var(--success)}
.mk2-col.is-failed .mk2-col-icon{background:var(--danger-soft);color:var(--danger)}
.mk2-col.is-failed{border-color:var(--danger-soft)}
.mk2-col-body{padding:10px;display:flex;flex-direction:column;gap:8px;flex:1}
/* V-Marketing/5 (ADR-056): empty state gets icon + title + hint
   structure (mirrors REC_KANBAN_EMPTY rich pattern from V-Reception/4).
   Tone variants (.is-success / .is-accent / .is-muted) softly tint
   the icon container so the visual cue reads at a glance. */
.mk2-col-empty{
  display:flex;flex-direction:column;align-items:center;gap:6px;
  text-align:center;padding:22px 12px;color:var(--text-tertiary);
  font-size:12px;font-weight:700;border:1px dashed var(--border);
  border-radius:var(--radius-sm);background:var(--bg-card);
}
.mk2-col-empty-icon{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:10px;
  background:var(--bg-subtle);color:var(--text-tertiary);margin-bottom:2px;
}
.mk2-col-empty-title{font-size:13px;font-weight:900;color:var(--text-primary)}
.mk2-col-empty-hint{font-size:11px;font-weight:600;color:var(--text-tertiary);max-width:36ch;line-height:1.55}
.mk2-col-empty.is-success .mk2-col-empty-icon{background:var(--success-soft);color:var(--success)}
.mk2-col-empty.is-accent  .mk2-col-empty-icon{background:var(--accent-soft);color:var(--accent-text)}
.mk2-col-empty.is-muted   .mk2-col-empty-icon{background:var(--bg-subtle);color:var(--text-tertiary)}
.mk2-post-card{
  display:flex;flex-direction:column;gap:8px;padding:0;
  background:var(--bg-card);border:1px solid var(--border);
  border-radius:var(--radius);cursor:pointer;text-align:start;
  overflow:hidden;transition:all var(--duration-fast) var(--ease-smooth);
}
.mk2-post-card:hover{transform:translateY(var(--lift-1));box-shadow:var(--shadow);border-color:var(--accent)}
.mk2-post-card.is-selected{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.mk2-post-thumb{
  height:90px;background:var(--bg-subtle) center/cover no-repeat;
  display:flex;align-items:center;justify-content:center;color:var(--text-tertiary);
}
.mk2-post-thumb.is-empty{background:linear-gradient(135deg,var(--bg-subtle),var(--bg-hover))}
.mk2-post-thumb.is-pulsing{animation:mk2Pulse 1.4s ease-in-out infinite}
.mk2-post-body{padding:10px 12px 12px;display:flex;flex-direction:column;gap:6px}
.mk2-post-title{font-weight:800;font-size:13px;color:var(--text-primary);line-height:1.4;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.mk2-post-meta{font-size:11px;color:var(--text-tertiary);display:flex;flex-wrap:wrap;gap:4px}
.mk2-post-foot{display:flex;flex-wrap:wrap;gap:4px;margin-top:2px}
.mk2-post-pill{
  display:inline-flex;align-items:center;padding:3px 8px;border-radius:999px;
  font-size:10px;font-weight:800;
  background:var(--bg-subtle);color:var(--text-secondary);
}
.mk2-post-pill.is-success{background:var(--success-soft);color:var(--success)}
.mk2-post-pill.is-info{background:var(--info-soft);color:var(--info)}
.mk2-post-pill.is-warning{background:var(--warning-soft);color:var(--warning)}
.mk2-post-pill.is-danger{background:var(--danger-soft);color:var(--danger)}
.mk2-post-pill.is-accent{background:var(--accent-soft);color:var(--accent-text)}
.mk2-post-pill.is-purple{background:var(--purple-soft);color:var(--purple)}
/* ---------- TIMELINE ---------- */
.mk2-card{
  background:var(--bg-card);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:16px;
}
.mk2-timeline{display:flex;flex-direction:column;gap:6px;padding:8px}
.mk2-tl-row{
  display:grid;grid-template-columns:64px 14px 60px 1fr auto;align-items:center;gap:12px;
  padding:10px 12px;border:1px solid var(--border);border-radius:var(--radius);
  background:var(--bg-card);cursor:pointer;text-align:start;transition:all var(--duration-fast) var(--ease-smooth);
}
.mk2-tl-row:hover{background:var(--bg-hover);border-color:var(--accent)}
.mk2-tl-row.is-selected{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.mk2-tl-date{text-align:center}
.mk2-tl-day{font-weight:900;font-size:18px;color:var(--text-primary);line-height:1}
.mk2-tl-time{font-size:10px;color:var(--text-tertiary);margin-top:3px;font-weight:700}
.mk2-tl-dot{width:10px;height:10px;border-radius:50%;background:var(--text-tertiary)}
.mk2-tl-dot[data-tone="success"]{background:var(--success)}
.mk2-tl-dot[data-tone="info"]{background:var(--info)}
.mk2-tl-dot[data-tone="warning"]{background:var(--warning)}
.mk2-tl-dot[data-tone="danger"]{background:var(--danger)}
.mk2-tl-dot[data-tone="accent"]{background:var(--accent)}
.mk2-tl-dot[data-tone="purple"]{background:var(--purple)}
.mk2-tl-thumb{
  width:60px;height:60px;border-radius:var(--radius-sm);
  background:var(--bg-subtle) center/cover no-repeat;
  display:flex;align-items:center;justify-content:center;color:var(--text-tertiary);
}
.mk2-tl-body{min-width:0}
.mk2-tl-title{font-weight:800;font-size:13px;color:var(--text-primary);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mk2-tl-meta{font-size:11px;color:var(--text-tertiary);margin-top:3px}
/* ---------- LOADING / EMPTY ---------- */
.mk2-loading,.mk2-empty{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:12px;padding:60px 20px;text-align:center;
}
.mk2-empty-icon{
  width:64px;height:64px;border-radius:50%;
  background:var(--accent-soft);color:var(--accent-text);
  display:flex;align-items:center;justify-content:center;
}
.mk2-empty-title{font-weight:900;font-size:18px;color:var(--text-primary)}
.mk2-empty-text{color:var(--text-secondary);font-size:14px;line-height:1.7;max-width:50ch}
/* ---------- ZONE 4 : DETAIL CONTENT (drawer shell retired) ----------
   ADR-139 Wave 9 (2026-05-28): the bespoke .mk2-drawer-* shell rules
   are retired. All 3 marketing drawers (brand / settings / post) now
   render through ResponsiveModal so they inherit the premium shell +
   drag handle bottom-sheet + Ctrl+K animation curve. The remaining
   .mk2-detail-* / .mk-image-empty / .mk-reason rules below are used
   INSIDE the post-drawer body and stay. */
.mk2-detail-meta{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:8px;margin-bottom:14px;
}
.mk2-meta-cell{
  background:var(--bg-subtle);border-radius:var(--radius-sm);padding:8px 10px;
}
.mk2-meta-l{font-size:10px;color:var(--text-tertiary);font-weight:700;margin-bottom:3px}
.mk2-meta-v{font-size:12px;color:var(--text-primary);font-weight:800}
.mk2-detail-image{
  border:1px solid var(--border);border-radius:var(--radius);
  overflow:hidden;background:var(--bg-subtle);
}
.mk2-detail-image img{display:block;width:100%;aspect-ratio:1/1;object-fit:cover}
.mk2-detail-text{
  min-height:200px;padding:14px;
  border:1px solid var(--border);border-radius:var(--radius);
  background:var(--bg-subtle);white-space:pre-wrap;line-height:1.85;
  color:var(--text-primary);font-size:13px;
}
.mk2-detail-preview{
  margin-top:14px;padding:14px;
  border:1px solid var(--border);border-radius:var(--radius);
  background:var(--bg-elevated);
}
/* ---------- RESPONSIVE ---------- */
@media (max-width:1180px){
  .mk2-hero{grid-template-columns:1fr}
  .mk2-action-center{order:0}
  .mk2-board{grid-template-columns:repeat(3,minmax(220px,1fr))}
}
@media (max-width:780px){
  .mk2-shell{padding:12px;gap:12px}
  .mk2-hero{padding:16px}
  .mk2-hero-title{font-size:24px}
  .mk2-readiness-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .mk2-setup-row{grid-template-columns:1fr}
  .mk2-board{grid-template-columns:1fr}
  .mk2-ws-head{flex-direction:column;align-items:stretch}
  .mk2-filter-row{align-items:stretch}
  .mk2-ws-filters{width:100%}
  .mk2-tl-row{grid-template-columns:50px 10px 1fr auto}
  .mk2-tl-thumb{display:none}
  /* ADR-139 W9: .mk2-drawer rule retired — drawers migrated to ResponsiveModal. */
  .mk2-kpi-strip{grid-template-columns:repeat(2,1fr)}
  .mk2-kpi-strip .mk2-kpi:nth-child(5){grid-column:span 2}
}
/* ============================================================
   End Marketing Screen ? Concept V2 stylesheet
   ============================================================ */
/* ============================================================
   Patient File - Concept V2 selective polish
   Scoped to pf2-* classes only
   ============================================================ */
.pf2{
  --pf2-card-shadow:0 10px 28px rgba(15,23,42,.06);
}
.pf2-hero{
  position:relative;
  z-index:1;
  display:grid;
  grid-template-columns:auto auto minmax(0,1fr) minmax(280px,360px) auto;
  gap:14px;
  align-items:center;
  margin:0 0 14px;
  padding:18px;
  border:1px solid var(--border);
  border-radius:var(--radius);
  background:linear-gradient(135deg,var(--bg-elevated),var(--bg-subtle));
  box-shadow:var(--pf2-card-shadow);
}
.pf2-back{
  flex-shrink:0;
}
.pf2-avatar{
  width:64px;
  height:64px;
  border-radius:18px;
  display:grid;
  place-items:center;
  background:var(--accent);
  color:#fff;
  font-size:24px;
  font-weight:900;
}
.pf2-hero-main{
  min-width:0;
}
.pf2-kicker,
.pf2-section-eyebrow{
  display:block;
  margin-bottom:4px;
  color:var(--text-tertiary);
  font-size:11px;
  font-weight:800;
  letter-spacing:0;
}
.pf2-title-row{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  align-items:center;
}
.pf2-title{
  margin:0;
  color:var(--text-primary);
  font-size:28px;
  font-weight:900;
  line-height:1.2;
  letter-spacing:0;
}
.pf2-subtitle{
  margin-top:5px;
  color:var(--text-secondary);
  font-size:13px;
  font-weight:700;
}
.pf2-meta-row{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin-top:10px;
}
.pf2-meta-row span{
  display:inline-flex;
  gap:6px;
  align-items:center;
  min-height:28px;
  padding:5px 9px;
  border:1px solid var(--border);
  border-radius:999px;
  background:var(--bg-elevated);
  color:var(--text-secondary);
  font-size:12px;
  font-weight:700;
}
.pf2-hero-stats{
  display:grid;
  gap:8px;
  min-width:0;
}
.pf2-stat-card,
.pf2-stat-grid > div{
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-elevated);
}
.pf2-stat-card{
  padding:12px;
}
.pf2-stat-card span,
.pf2-stat-grid span{
  display:block;
  color:var(--text-tertiary);
  font-size:10px;
  font-weight:800;
}
.pf2-stat-card strong{
  display:block;
  margin-top:4px;
  color:var(--danger);
  font-size:22px;
  font-weight:900;
}
.pf2-stat-card small{
  display:block;
  margin-top:2px;
  color:var(--text-tertiary);
  font-size:10px;
}
.pf2-stat-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:8px;
}
.pf2-stat-grid > div{
  padding:9px;
  text-align:center;
}
.pf2-stat-grid strong{
  display:block;
  margin-top:3px;
  color:var(--text-primary);
  font-size:16px;
  font-weight:900;
}
.pf2-actions{
  display:flex;
  flex-direction:column;
  gap:8px;
}
.pf2-actions .btn{
  justify-content:center;
  white-space:nowrap;
}
.pf2-command{
  display:flex;
  gap:10px;
  align-items:center;
  margin:0 0 14px;
  padding:12px 14px;
  border:1px solid var(--border);
  border-radius:var(--radius);
  background:var(--bg-elevated);
}
.pf2-command-icon{
  width:38px;
  height:38px;
  border-radius:12px;
  display:grid;
  place-items:center;
  background:var(--accent-soft);
  color:var(--accent);
}
.pf2-tone-success .pf2-command-icon{background:var(--success-soft);color:var(--success)}
.pf2-tone-warning .pf2-command-icon{background:var(--warning-soft);color:var(--warning)}
.pf2-tone-danger .pf2-command-icon{background:var(--danger-soft);color:var(--danger)}
.pf2-command-label{
  color:var(--text-tertiary);
  font-size:11px;
  font-weight:800;
}
.pf2-command-title{
  margin-top:2px;
  color:var(--text-primary);
  font-size:14px;
  font-weight:900;
}
.pf2-content{
  display:flex;
  flex-direction:column;
  gap:16px;
}
.pf2-tabs{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  padding:8px;
  border:1px solid var(--border);
  border-radius:var(--radius);
  background:var(--bg-elevated);
}
.pf2-tab{
  min-height:36px;
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:8px 12px;
  border:1px solid transparent;
  border-radius:var(--radius-sm);
  background:transparent;
  color:var(--text-secondary);
  font:inherit;
  font-size:12px;
  font-weight:800;
  cursor:pointer;
}
.pf2-tab:hover{
  border-color:var(--border);
  background:var(--bg-subtle);
}
.pf2-tab.active{
  border-color:var(--accent);
  background:var(--accent-soft);
  color:var(--accent-text);
}
.pf2-overview{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(300px,380px);
  gap:16px;
}
.pf2-main-col,
.pf2-col-side{
  display:flex;
  flex-direction:column;
  gap:16px;
  min-width:0;
}
.pf2-col-side{
  position:sticky;
  top:16px;
  align-self:start;
}
.pf2-panel{
  border:1px solid var(--border);
  border-radius:var(--radius);
  background:var(--bg-elevated);
  box-shadow:var(--pf2-card-shadow);
  padding:16px;
}
.pf2-panel-head{
  display:flex;
  justify-content:space-between;
  align-items:flex-start;
  gap:12px;
  margin-bottom:14px;
}
.pf2-panel h2{
  margin:0;
  color:var(--text-primary);
  font-size:16px;
  font-weight:900;
  letter-spacing:0;
}
.pf2-snapshot-grid{
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  gap:10px;
}
.pf2-info-card{
  display:flex;
  gap:10px;
  align-items:center;
  min-width:0;
  padding:12px;
  border:1px solid var(--border);
  border-radius:var(--radius);
  background:var(--bg-elevated);
}
.pf2-info-icon{
  width:36px;
  height:36px;
  border-radius:12px;
  display:grid;
  place-items:center;
  flex-shrink:0;
  background:var(--accent-soft);
  color:var(--accent);
}
.pf2-info-card span{
  display:block;
  color:var(--text-tertiary);
  font-size:10px;
  font-weight:800;
}
.pf2-info-card strong{
  display:block;
  margin-top:3px;
  overflow:hidden;
  color:var(--text-primary);
  font-size:13px;
  font-weight:900;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.pf2-clinical-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:10px;
}
.pf2-clinical-card{
  padding:12px;
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
}
.pf2-clinical-card span{
  display:block;
  color:var(--text-tertiary);
  font-size:11px;
  font-weight:800;
}
.pf2-clinical-card strong{
  display:block;
  margin-top:4px;
  color:var(--text-primary);
  font-size:14px;
  font-weight:900;
}
.pf2-clinical-card.pf2-success strong{color:var(--success)}
.pf2-clinical-card.pf2-warning strong{color:var(--warning)}
.pf2-clinical-card.pf2-danger strong{color:var(--danger)}
.pf2-alert-note{
  display:flex;
  gap:8px;
  align-items:flex-start;
  margin-top:12px;
  padding:12px;
  border-radius:var(--radius-sm);
  background:var(--warning-soft);
  color:var(--warning);
  font-size:13px;
  font-weight:800;
}
.pf2-timeline{
  display:grid;
  gap:10px;
}
.pf2-timeline-item{
  display:grid;
  grid-template-columns:34px minmax(0,1fr);
  gap:10px;
  padding:12px;
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
}
.pf2-timeline-icon{
  width:34px;
  height:34px;
  border-radius:12px;
  display:grid;
  place-items:center;
  background:var(--bg-elevated);
  color:var(--accent);
}
.pf2-timeline-item span,
.pf2-doc-item span,
.pf2-list-item span,
.pf2-next-visit span{
  display:block;
  color:var(--text-tertiary);
  font-size:11px;
  font-weight:700;
}
.pf2-timeline-item strong,
.pf2-doc-item strong,
.pf2-list-item strong,
.pf2-next-visit strong{
  display:block;
  margin-top:2px;
  color:var(--text-primary);
  font-size:13px;
  font-weight:900;
}
.pf2-timeline-item p{
  margin:4px 0 0;
  color:var(--text-secondary);
  font-size:12px;
  line-height:1.7;
}
.pf2-finance-card{
  border-color:rgba(239,68,68,.22);
}
.pf2-balance-main{
  padding:14px;
  border-radius:var(--radius);
  background:var(--danger-soft);
  color:var(--danger);
}
.pf2-balance-main span,
.pf2-balance-main small{
  display:block;
  font-size:11px;
  font-weight:800;
}
.pf2-balance-main strong{
  display:block;
  margin:4px 0;
  font-size:26px;
  font-weight:900;
}
.pf2-money-grid{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:8px;
  margin:10px 0 14px;
}
.pf2-money-grid > div{
  padding:10px;
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
}
.pf2-money-grid span{
  display:block;
  color:var(--text-tertiary);
  font-size:10px;
  font-weight:800;
}
.pf2-money-grid strong{
  display:block;
  margin-top:3px;
  color:var(--text-primary);
  font-size:14px;
  font-weight:900;
}
.pf2-next-visit{
  display:flex;
  gap:10px;
  align-items:center;
  padding:12px;
  border-radius:var(--radius-sm);
  background:var(--accent-soft);
  color:var(--accent-text);
}
.pf2-list{
  display:grid;
  gap:8px;
}
.pf2-list-item{
  width:100%;
  padding:10px 12px;
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
  text-align:start;
  cursor:pointer;
}
.pf2-record-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:8px;
  margin-bottom:12px;
}
.pf2-record-card{
  display:flex;
  min-height:72px;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:4px;
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
  color:var(--text-primary);
  cursor:pointer;
}
.pf2-record-card span{
  color:var(--text-tertiary);
  font-size:10px;
  font-weight:800;
}
.pf2-record-card strong{
  font-size:17px;
  font-weight:900;
}
.pf2-doc-list{
  display:grid;
  gap:8px;
}
.pf2-doc-item{
  display:grid;
  grid-template-columns:20px minmax(0,1fr) auto;
  gap:8px;
  align-items:center;
  padding:10px;
  border:1px solid var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
  cursor:pointer;
}
.pf2-doc-item strong{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.pf2-doc-actions{
  display:flex;
  gap:4px;
}
.pf2-doc-action{
  width:28px;
  height:28px;
  display:grid;
  place-items:center;
  border:1px solid var(--border);
  border-radius:8px;
  background:var(--bg-elevated);
  color:var(--text-secondary);
  cursor:pointer;
}
.pf2-doc-action.danger{
  color:var(--danger);
}
.pf2-empty{
  display:grid;
  min-height:70px;
  place-items:center;
  border:1px dashed var(--border);
  border-radius:var(--radius-sm);
  background:var(--bg-subtle);
  color:var(--text-tertiary);
  font-size:13px;
  font-weight:800;
}
@media (max-width:1280px){
  .pf2-hero{
    grid-template-columns:auto auto minmax(0,1fr);
  }
  .pf2-hero-stats,
  .pf2-actions{
    grid-column:1 / -1;
  }
  .pf2-actions{
    flex-direction:row;
    flex-wrap:wrap;
  }
}
@media (max-width:1180px){
  .pf2-overview{
    grid-template-columns:1fr;
  }
  .pf2-col-side{
    position:static;
  }
  .pf2-snapshot-grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
  }
}
@media (max-width:760px){
  .pf2-hero{
    grid-template-columns:auto minmax(0,1fr);
    padding:14px;
  }
  .pf2-back{
    grid-column:1;
  }
  .pf2-avatar{
    width:52px;
    height:52px;
    border-radius:15px;
    font-size:20px;
  }
  .pf2-hero-main{
    grid-column:2;
  }
  .pf2-title{
    font-size:22px;
  }
  .pf2-stat-grid,
  .pf2-record-grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
  }
  .pf2-snapshot-grid,
  .pf2-clinical-grid,
  .pf2-money-grid{
    grid-template-columns:1fr;
  }
  .pf2-tab{
    flex:1 1 120px;
    justify-content:center;
  }
}
/* ════════════════════════════════════════════════════════════════════
   V-PatientFile (ADR-055) — sticky header + full canvas + premium anim
   Replaces the pre-V layout (pf3-rail + pf3-canvas-with-command-and-
   clinical + pf3-drawer 3-col) where identity / next-appt / balance /
   tabs were duplicated 2-3× across 4 regions and the actual tab body
   got only ~25% of the grid.
   ════════════════════════════════════════════════════════════════════ */
.pf-shell{
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* ── V-PatientFile follow-up (ADR-055 amendment) ──
   The bespoke .pf-header shell was REMOVED. PatientHeader now reuses
   the .dash-hero shell (same as Reception / Appointments / Patients /
   Billing) so the visual voice stays consistent across the hub.
   The only PatientFile-specific addition lives below: the medical
   alerts strip (.pf-hero-alerts) inside the hero + a danger-tone
   border modifier on the hero when critical alerts are present. */
.pf-hero{
  /* Tag for V-PatientFile's .dash-hero usage. The class adds no layout
     of its own — pure tagging so .has-critical + .pf-hero-alerts can
     scope without leaking into other hero usages. */
}
.pf-hero.has-critical{
  border-color: color-mix(in srgb, var(--danger) 32%, var(--border));
  box-shadow:
    0 4px 24px color-mix(in srgb, var(--danger) 8%, transparent),
    0 0 0 1px color-mix(in srgb, var(--danger) 12%, transparent);
}
/* ADR-055 amendment #3: title size compensation for short patient names.
   .dash-hero-title at 28px / 900 / -0.02em letter-spacing was designed
   for the static page titles in the other hub heroes (Reception /
   Billing / Appointments / Patients) where the text is 15–22 chars and
   the heavy weight + tight tracking + gradient feel proportional.
   Patient names are often 6–10 chars ("مريض 1", "محمد قنديل"); the
   same scale on shorter strings reads as visually oversized + overly
   condensed. This override only applies inside .pf-hero so the other
   four hub heroes are untouched. */
.pf-hero .dash-hero-title{
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 0;
}
.pf-hero-alerts{
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px dashed color-mix(in srgb, var(--border) 80%, transparent);
}
.pf-hero-alerts__label{
  color: var(--text-tertiary);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0;
  margin-inline-end: 4px;
}
/* Patient notes strip — read from the Add/Edit Patient form, shown
   only when content exists. Soft info tone so it never competes with
   the medical alerts strip above. */
.pf-hero-notes{
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: flex-start;
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 5%, var(--bg-elevated));
  border: 1px solid color-mix(in srgb, var(--accent) 14%, transparent);
}
.pf-hero-notes__label{
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--accent);
  font-size: 12px;
  font-weight: 900;
  white-space: nowrap;
}
.pf-hero-notes__body{
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.6;
  word-break: break-word;
}
/* Compact actions row — WhatsApp gets the green WA tint on hover for
   instant recognition. Other icon-only utilities (call / edit / print)
   stay neutral. */
.pf-hero-actions .btn.outline.icon{
  width: 36px;
  height: 36px;
  min-width: 36px;
  min-height: 36px;
  padding: 0;
}
.pf-hero-actions__wa:hover:not(:disabled){
  border-color: #25D366;
  color: #25D366;
}
.pf-alert{
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
  white-space: nowrap;
  border: 1px solid color-mix(in srgb, currentColor 28%, transparent);
  background: color-mix(in srgb, currentColor 14%, var(--bg-elevated));
  transition:
    transform var(--duration-fast) var(--ease-spring),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.pf-alert:hover{
  transform: translateY(var(--lift-1)) scale(1.03);
  box-shadow: var(--shadow-sm);
}
.pf-alert--danger{
  color: var(--danger);
  animation: pfAlertPulse 2.4s ease-in-out infinite;
}
.pf-alert--warning{ color: color-mix(in srgb, var(--warning) 80%, #000); }
.pf-alert--info{ color: var(--accent); }
.pf-alert--safe{ color: var(--success); }
@keyframes pfAlertPulse{
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 32%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in srgb, var(--danger) 0%, transparent); }
}
/* Sticky tab strip — hosts the <Tabs> primitive */
.pf-tab-strip{
  position: sticky;
  top: 0;
  z-index: 80;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--bg-elevated) 96%, transparent);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
}
.pf-tab-strip .tabs{
  overflow-x: auto;
}
/* Canvas — full-width tab content area */
.pf-canvas{
  min-height: 320px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elevated);
  box-shadow: 0 4px 18px -16px rgba(15, 23, 42, 0.35);
}
.pf-canvas__inner{
  animation: pfTabIn 280ms var(--ease-out);
}
@keyframes pfTabIn{
  from{ opacity: 0; transform: translateY(8px); }
  to  { opacity: 1; transform: translateY(0); }
}
/* V-PatientFile follow-up #2 (ADR-055 amendment) — table width safety.
   Earlier fix wrongly tried to force tbody cell alignment to `start`
   while keeping `numeric: true` end-aligning the headers — same column,
   different sides. Root fix landed at the consumer (PatientInvoices +
   PatientSessionsList drop `numeric: true`, matching billing-main.jsx).
   The only CSS layer left is a safety: ensure the `.card` wrapper +
   `.data-table` fill the full-width canvas. No alignment overrides. */
.pf-canvas .card{
  width: 100%;
  box-sizing: border-box;
}
.pf-canvas .data-table{
  width: 100%;
  table-layout: auto;
}
.pf-canvas--chart{ padding: 10px; }
/* Overview tab — medical chips + record tiles + recent activity */
.pf-overview{
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.pf-overview__section{
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-subtle);
  padding: 14px 16px;
}
.pf-overview__head{
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.pf-overview__head h3{
  margin: 2px 0 0;
  color: var(--text-primary);
  font-size: 15px;
  font-weight: 900;
}
.pf-overview__eyebrow{
  color: var(--text-tertiary);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0;
}
.pf-overview__mchips{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}
.pf-mchip{
  display: flex;
  gap: 10px;
  align-items: center;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  transition:
    transform var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.pf-mchip:hover{
  transform: translateY(var(--lift-1));
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}
.pf-mchip__icon{
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  flex-shrink: 0;
}
.pf-mchip__body{ min-width: 0; }
.pf-mchip__body span{
  display: block;
  color: var(--text-tertiary);
  font-size: 10px;
  font-weight: 900;
}
.pf-mchip__body strong{
  display: block;
  margin-top: 2px;
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 900;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pf-mchip--danger{ border-inline-start-color: var(--danger); }
.pf-mchip--danger .pf-mchip__icon{ background: var(--danger-soft); color: var(--danger); }
.pf-mchip--warning{ border-inline-start-color: var(--warning); }
.pf-mchip--warning .pf-mchip__icon{ background: var(--warning-soft); color: color-mix(in srgb, var(--warning) 80%, #000); }
.pf-mchip--success{ border-inline-start-color: var(--success); }
.pf-mchip--success .pf-mchip__icon{ background: var(--success-soft); color: var(--success); }
.pf-mchip--info{ border-inline-start-color: var(--info); }
.pf-mchip--info .pf-mchip__icon{ background: var(--info-soft); color: var(--info); }
.pf-overview__notes{
  display: flex;
  gap: 8px;
  margin: 12px 0 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--warning) 10%, var(--bg-elevated));
  color: color-mix(in srgb, var(--warning) 80%, #000);
  font-size: 12px;
  font-weight: 800;
}
.pf-overview__tiles{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}
.pf-record-tile{
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  cursor: pointer;
  text-align: start;
  transition:
    transform var(--duration-fast) var(--ease-spring),
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.pf-record-tile:hover{
  transform: translateY(var(--lift-2));
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}
.pf-record-tile__icon{
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--bg-subtle);
  color: var(--accent);
}
.pf-record-tile__body{ min-width: 0; }
.pf-record-tile__body span{
  display: block;
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 900;
}
.pf-record-tile__body em{
  display: block;
  margin-top: 2px;
  color: var(--text-tertiary);
  font-size: 11px;
  font-weight: 700;
  font-style: normal;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pf-record-tile__count{
  color: var(--text-primary);
  font-size: 16px;
  font-weight: 900;
  min-width: 24px;
  text-align: center;
}
.pf-overview__timeline{
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pf-timeline-row{
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  gap: 12px;
  align-items: flex-start;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth);
}
.pf-timeline-row:hover{
  background: var(--bg-hover);
  border-color: var(--border-strong);
}
.pf-timeline-row__icon{
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--bg-subtle);
  color: var(--accent);
}
.pf-timeline-row__body{ min-width: 0; }
.pf-timeline-row__body span{
  color: var(--text-tertiary);
  font-size: 10px;
  font-weight: 900;
}
.pf-timeline-row__body strong{
  display: block;
  margin-top: 2px;
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 900;
}
.pf-timeline-row__body p{
  margin: 4px 0 0;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
}
.pf-overview__empty{
  padding: 20px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  color: var(--text-tertiary);
  text-align: center;
  font-size: 13px;
  font-weight: 800;
}
/* DentalChart inside pf-canvas — tooth spring on hover/selection */
.pf-canvas--chart .tooth{
  transition:
    transform var(--duration-base) var(--ease-spring),
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.pf-canvas--chart .tooth:hover{
  transform: translateY(var(--lift-1)) scale(1.06);
}
.pf-canvas--chart .tooth.selected{
  transform: scale(1.1);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}
/* Responsive */
@media (max-width: 980px){
  .pf-hero-alerts{ gap: 6px; }
  .pf-overview__mchips,
  .pf-overview__tiles{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px){
  .pf-overview__mchips,
  .pf-overview__tiles{ grid-template-columns: 1fr; }
  .pf-canvas{ padding: 10px; }
}
/* Honour prefers-reduced-motion — kill the candy, keep the layout */
@media (prefers-reduced-motion: reduce){
  .pf-canvas__inner{ animation: none; }
  .pf-alert--danger{ animation: none; }
  .pf-alert,
  .pf-mchip,
  .pf-record-tile,
  .pf-canvas--chart .tooth{ transition: none; }
}
/* ── Pre-V-PatientFile (pf3-*) layout — REMOVED. Replaced by .pf-* above.
   The full pre-V audit + removal rationale is in DECISIONS.md ADR-055. ── */
/* (pf3-* layout block deleted in V-PatientFile / ADR-055 — see .pf-* CSS above) */
/* ════════════════════════════════════════════════════════════════════
   ✨ PREMIUM UX/UI POLISH — Phase 1 (additive, safe to revert)
   ════════════════════════════════════════════════════════════════════ */
/* ── Design tokens: spacing + motion ─────────────────────────────── */
:root {
  --space-1:  4px;
  --space-2:  8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;

  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);

  --duration-fast: 120ms;
  --duration-base: 200ms;
  --duration-slow: 320ms;
}
/* ── Smooth, premium scrollbars (everywhere) ─────────────────────── */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 99px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background var(--duration-fast) var(--ease-smooth);
}
*::-webkit-scrollbar-thumb:hover {
  background: var(--text-tertiary);
  background-clip: padding-box;
}
/* ── Card hover lift (premium feel on interactive cards) ─────────── */
.card {
  transition:
    box-shadow var(--duration-base) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-base) var(--ease-smooth),
    background-color var(--duration-fast) var(--ease-smooth);
}
.card.kpi {
  cursor: default;
}
.card.kpi:hover {
  transform: translateY(var(--lift-2));
  box-shadow: var(--shadow);
  border-color: color-mix(in srgb, var(--accent) 18%, var(--border));
}
.card.interactive:hover,
.card[role="button"]:hover {
  transform: translateY(var(--lift-2));
  box-shadow: var(--shadow-lg);
  cursor: pointer;
}
.card.interactive:active,
.card[role="button"]:active {
  transform: translateY(0);
  transition-duration: 60ms;
}
/* ── Button micro-interactions ───────────────────────────────────── */
.btn {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.btn:hover:not(:disabled) {
  transform: translateY(var(--lift-1));
}
.btn:active:not(:disabled) {
  transform: translateY(0);
  transition-duration: 60ms;
}
.btn.primary:hover:not(:disabled) {
  box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 28%, transparent);
}
/* ── U-10/3: Loading state for async buttons ──────────────────────
   Trigger:  add aria-busy="true" alongside disabled:<state> at the
             call site (mirrors data-table.jsx's aria-busy idiom).
   Visual:   currentColor spinner via ::before, caller's icon child
             hidden, full color preserved (overrides the .55 dim
             from the generic .btn:disabled rule so the loading
             button stays clearly the same primary/danger/etc).
   Animates: reuses the existing @keyframes spin from L1653 — no
             new keyframes block. */
.btn[aria-busy="true"] {
  cursor: progress;
}
.btn[aria-busy="true"]:disabled {
  opacity: 1;
  cursor: progress;
}
.btn[aria-busy="true"] > svg {
  display: none;
}
.btn[aria-busy="true"]::before {
  content: '';
  display: inline-block;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
.btn.sm[aria-busy="true"]::before {
  width: 12px;
  height: 12px;
  border-width: 1.5px;
}
@media (prefers-reduced-motion: reduce) {
  .btn[aria-busy="true"]::before { animation: none; }
}
/* ── Unified focus rings (accessibility + premium) ─────────────────
   U-10/2: uses the canonical --ring-shadow / --ring-shadow-soft
   tokens from U-1 (tokens.css) instead of inline color-mix. Adds
   .icon-btn + .nav-item to the selector list — they were previously
   covered by a legacy `outline: 2px solid` rule that's now removed
   to eliminate the double-ring inconsistency on those primitives. */
button:focus-visible,
a:focus-visible,
.tab:focus-visible,
.btn:focus-visible,
.icon-btn:focus-visible,
.nav-item:focus-visible,
[role="button"]:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow);
  border-radius: var(--radius);
}
.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring-shadow-soft);
}
/* ── Tab active indicator: smooth slide ──────────────────────────── */
.tabs .tab {
  position: relative;
  transition: color var(--duration-fast) var(--ease-smooth);
}
.tabs .tab:hover:not(.active) {
  color: var(--text-secondary);
}
/* ── Premium animations library ──────────────────────────────────── */
@keyframes slideUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes slideDown {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes slideInStart {
  from { opacity: 0; transform: translateX(-12px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
@keyframes pulseSoft {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.65; }
}
@keyframes lift {
  from { transform: translateY(0); }
  to   { transform: translateY(var(--lift-1)); }
}
.slide-up   { animation: slideUp   var(--duration-slow) var(--ease-out); }
.slide-down { animation: slideDown var(--duration-base) var(--ease-out); }
.slide-in   { animation: slideInStart var(--duration-base) var(--ease-out); }
.pulse-soft { animation: pulseSoft 2s ease-in-out infinite; }
/* ── Skeleton shimmer (V-1/5 refresh — accent-tinted, ADR-048) ──── */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--shimmer-base) 25%,
    var(--shimmer-highlight) 50%,
    var(--shimmer-base) 75%
  );
  background-size: 200% 100%;
  animation: shimmer var(--shimmer-duration) ease-in-out infinite;
  border-radius: var(--radius);
  color: transparent !important;
  user-select: none;
}
/* ── KPI numeric polish (tabular figures align nicely) ───────────── */
.kpi .value,
.kpi-value,
[data-numeric] {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.025em;
}
/* ── Grid + flex tighter alignment helpers (additive) ───────────── */
.stack { display: flex; flex-direction: column; }
.stack.gap-2 { gap: var(--space-2); }
.stack.gap-3 { gap: var(--space-3); }
.stack.gap-4 { gap: var(--space-4); }
.stack.gap-6 { gap: var(--space-6); }
.row { display: flex; align-items: center; }
.row.gap-2 { gap: var(--space-2); }
.row.gap-3 { gap: var(--space-3); }
.row.gap-4 { gap: var(--space-4); }
/* ── RTL/LTR direction support via logical properties ───────────── */
html[dir="ltr"],
[dir="ltr"] {
  text-align: left;
}
[dir="ltr"] body,
[dir="ltr"] button,
[dir="ltr"] input,
[dir="ltr"] select,
[dir="ltr"] textarea {
  direction: ltr;
  text-align: left;
}
/* ── Selection color (matches accent) ────────────────────────────── */
::selection {
  background: color-mix(in srgb, var(--accent) 25%, transparent);
  color: var(--text-primary);
}
/* ── Image rendering polish ──────────────────────────────────────── */
img {
  -webkit-user-drag: none;
  user-select: none;
}
/* ── Table row hover polish ──────────────────────────────────────── */
.data-table tbody tr {
  transition: background-color var(--duration-fast) var(--ease-smooth);
}
.data-table tbody tr:hover {
  background-color: var(--bg-hover);
}
/* ── Inputs feel premium ─────────────────────────────────────────── */
.input,
.select,
.textarea {
  transition:
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow   var(--duration-fast) var(--ease-smooth),
    background   var(--duration-fast) var(--ease-smooth);
}
.input:hover:not(:focus),
.select:hover:not(:focus),
.textarea:hover:not(:focus) {
  border-color: var(--border-strong);
}
/* ── Soft entrance for screen content ────────────────────────────── */
main [data-screen],
main > section,
.screen-root {
  animation: slideUp var(--duration-slow) var(--ease-out);
}
/* ── Respect users who prefer reduced motion ─────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* ── Mobile spacing tweaks ───────────────────────────────────────── */
@media (max-width: 720px) {
  .card { border-radius: var(--radius); }
  .btn { padding: 9px 14px; }
}
/* ════════════════════════════════════════════════════════════════════
   ✨ PREMIUM UX/UI POLISH — Phase 2 (Sidebar + Topbar)
   ════════════════════════════════════════════════════════════════════ */
/* ── Sidebar: subtle depth gradient ──────────────────────────────── */
.sidebar {
  position: relative;
  background-image:
    linear-gradient(180deg,
      var(--bg-sidebar) 0%,
      color-mix(in srgb, var(--bg-sidebar) 92%, var(--bg-subtle)) 100%);
}
/* ── Nav items: active indicator stripe + slide on hover ─────────── */
.nav-item {
  position: relative;
  overflow: visible;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color      var(--duration-fast) var(--ease-smooth),
    transform  var(--duration-base) var(--ease-smooth);
}
/* Active accent stripe — animated in via scaleY */
.nav-item::before {
  content: '';
  position: absolute;
  inset-inline-start: -10px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  background: var(--accent);
  border-radius: 0 3px 3px 0;
  transform: scaleY(0);
  transform-origin: center;
  transition: transform var(--duration-base) var(--ease-spring);
  pointer-events: none;
}
.nav-item.active::before {
  transform: scaleY(1);
}
/* Subtle slide on hover (RTL-aware) */
.nav-item:hover:not(.active) {
  transform: translateX(-2px);
}
[dir="ltr"] .nav-item:hover:not(.active) {
  transform: translateX(2px);
}
/* Icon-box gets accent tint + soft scale when active */
.nav-item .icon-box {
  border-radius: 8px;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color      var(--duration-fast) var(--ease-smooth),
    transform  var(--duration-base) var(--ease-spring);
}
.nav-item.active .icon-box {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent);
  transform: scale(1.06);
}
.nav-item:hover:not(.active) .icon-box {
  color: var(--text-primary);
}
/* Badge count: soft glow + scale on hover */
.nav-item .badge-count {
  box-shadow: 0 2px 6px color-mix(in srgb, var(--accent) 32%, transparent);
  transition: transform var(--duration-base) var(--ease-spring);
}
.nav-item:hover .badge-count {
  transform: scale(1.08);
}
/* ── Avatar: premium polish ──────────────────────────────────────── */
.avatar {
  position: relative;
  overflow: hidden;
  box-shadow:
    0 4px 12px color-mix(in srgb, var(--accent) 22%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: transform var(--duration-base) var(--ease-spring);
}
.avatar::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255,255,255,0.18), transparent 55%);
  pointer-events: none;
}
.sidebar-footer:hover .avatar {
  transform: scale(1.05);
}
/* ── Sidebar footer logout button: danger on hover ───────────────── */
.sidebar-footer .icon-btn {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color      var(--duration-fast) var(--ease-smooth);
}
.sidebar-footer .icon-btn:hover {
  background: var(--danger-soft);
  color: var(--danger);
}
/* ── Logo: gentle scale on hover ─────────────────────────────────── */
.logo-wrap {
  transition:
    transform var(--duration-base) var(--ease-smooth),
    opacity   var(--duration-fast) var(--ease-smooth);
}
.logo-wrap:hover {
  transform: scale(1.025);
}
.logo-wrap:active {
  opacity: 0.85;
}
/* ── Topbar: glassy premium look ─────────────────────────────────── */
.topbar {
  backdrop-filter: blur(14px) saturate(180%);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
  position: sticky;
  top: 0;
  z-index: 50;
}
/* ── Search bar premium feel ─────────────────────────────────────── */
.topbar .search input {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.topbar .search input:hover:not(:focus) {
  background: var(--bg-elevated);
  border-color: var(--border);
}
.topbar .search input:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
/* ── Topbar icon buttons polished ────────────────────────────────── */
.icon-btn {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color      var(--duration-fast) var(--ease-smooth),
    transform  var(--duration-fast) var(--ease-smooth);
}
.icon-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
  transform: scale(1.06);
}
.icon-btn:active {
  transform: scale(0.96);
}
/* ── Page title polish ───────────────────────────────────────────── */
.page-title {
  letter-spacing: -0.015em;
}
/* ── Sidebar nav: stagger entry animation (subtle) ──────────────── */
.sidebar .nav-item {
  animation: slideInStart var(--duration-base) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 25ms);
}
.sidebar .nav-items:nth-of-type(1) .nav-item:nth-child(1) { --i: 1; }
.sidebar .nav-items:nth-of-type(1) .nav-item:nth-child(2) { --i: 2; }
.sidebar .nav-items:nth-of-type(1) .nav-item:nth-child(3) { --i: 3; }
.sidebar .nav-items:nth-of-type(2) .nav-item:nth-child(1) { --i: 4; }
.sidebar .nav-items:nth-of-type(2) .nav-item:nth-child(2) { --i: 5; }
.sidebar .nav-items:nth-of-type(3) .nav-item:nth-child(1) { --i: 6; }
.sidebar .nav-items:nth-of-type(3) .nav-item:nth-child(2) { --i: 7; }
.sidebar .nav-items:nth-of-type(4) .nav-item:nth-child(1) { --i: 8; }
/* ════════════════════════════════════════════════════════════════════
   ✨ PREMIUM UX/UI POLISH — Phase 3 (Dashboard + Reception)
   ════════════════════════════════════════════════════════════════════ */
/* ── Dashboard: KPI cards stagger entry ──────────────────────────── */
[data-screen="dashboard"] .grid.cols-4 > div {
  animation: slideUp var(--duration-slow) var(--ease-out) both;
}
.page-content > .grid.cols-4 > div:nth-child(1) { animation-delay: 0ms; }
.page-content > .grid.cols-4 > div:nth-child(2) { animation-delay: 60ms; }
.page-content > .grid.cols-4 > div:nth-child(3) { animation-delay: 120ms; }
.page-content > .grid.cols-4 > div:nth-child(4) { animation-delay: 180ms; }
/* ── Page header polish ──────────────────────────────────────────── */
.page-header {
  animation: slideDown var(--duration-slow) var(--ease-out);
}
/* ── Dashboard cards subtle entry stagger ────────────────────────── */
.page-content > .grid > .card,
.page-content > div > .card {
  animation: slideUp var(--duration-slow) var(--ease-out) both;
}
/* ── Section headers: better typographic hierarchy ───────────────── */
.card > div:first-child[style*="text-transform"] {
  letter-spacing: 0.05em;
}
/* ── Kanban board: premium polish ────────────────────────────────── */
.kanban-board {
  scroll-snap-type: x proximity;
  gap: var(--space-3);
}
.kanban-col {
  position: relative;
  transition:
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-base) var(--ease-smooth);
  scroll-snap-align: start;
  animation: slideUp var(--duration-slow) var(--ease-out) both;
}
.kanban-col:nth-child(1) { animation-delay: 0ms; }
.kanban-col:nth-child(2) { animation-delay: 60ms; }
.kanban-col:nth-child(3) { animation-delay: 120ms; }
.kanban-col:nth-child(4) { animation-delay: 180ms; }
.kanban-col:nth-child(5) { animation-delay: 240ms; }
.kanban-col:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}
/* Top accent stripe via header bg-elevated tint */
.kanban-col-hdr {
  position: relative;
  letter-spacing: 0.02em;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg,
    var(--bg-elevated) 0%,
    color-mix(in srgb, var(--bg-elevated) 92%, var(--bg-subtle)) 100%);
}
.kanban-col-hdr::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: currentColor;
  opacity: 0.4;
}
/* Kanban cards premium hover */
.kanban-card {
  transition:
    box-shadow var(--duration-base) var(--ease-smooth),
    transform var(--duration-base) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth);
  will-change: transform;
}
.kanban-card:hover {
  box-shadow: var(--shadow);
  transform: translateY(var(--lift-2));
  border-color: color-mix(in srgb, var(--accent) 25%, var(--border));
}
/* Empty state subtle pulse */
.kanban-empty {
  animation: pulseSoft 3s ease-in-out infinite;
}
/* ── Chip enhancements (status badges) ──────────────────────────── */
.chip {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
.chip:hover {
  transform: scale(1.04);
}
.chip:active {
  transform: scale(0.98);
  transition-duration: 60ms;
}
/* ── Avatar small variant: premium gradient feel ──────────────── */
.avatar.sm {
  position: relative;
  overflow: hidden;
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.avatar.sm::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255,255,255,0.12), transparent 55%);
  pointer-events: none;
  border-radius: inherit;
}
/* ── Mini bar chart bars: subtle entry ───────────────────────────── */
.card .grid + div > div > div[style*="height:"],
[data-chart-bar] {
  transition: opacity var(--duration-base) var(--ease-out);
}
/* ── Progress bar premium ────────────────────────────────────────── */
.progress {
  background: var(--bg-subtle);
  border-radius: 99px;
  overflow: hidden;
  height: 6px;
  position: relative;
}
.progress::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    transparent,
    rgba(255, 255, 255, 0.18),
    transparent);
  animation: shimmer 2.5s ease-in-out infinite;
  pointer-events: none;
}
.progress-bar {
  height: 100%;
  border-radius: 99px;
  transition: width var(--duration-slow) var(--ease-out);
}
/* ── Walk-In modal patient list polish ───────────────────────────── */
.modal-backdrop .gm-box .input:focus + div,
.gm-box [style*="overflowY"] > div {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
/* ── Selectable option-card pattern (used in modals) ─────────────── */
button.card[style*="border"] {
  transition:
    border-color var(--duration-fast) var(--ease-smooth),
    background var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
button.card[style*="border"]:hover {
  transform: translateY(var(--lift-1));
}
/* ── Reception kanban: mobile horizontal scroll ──────────────────── */
@media (max-width: 900px) {
  .kanban-board {
    grid-template-columns: repeat(5, minmax(180px, 1fr));
    overflow-x: auto;
    padding-bottom: 12px;
  }
  .kanban-col {
    min-width: 180px;
  }
}
/* ── Wave 5h: Frameless ResponsiveModal variant for wrapper modals ──
   The 3 "wrapper" modals (NewAppointment host in appointments + reception,
   QuickAddPatient modal-variant in new-appointment-screen) host whole
   self-contained components that already render their own header,
   body, and actions. ResponsiveModal's default rm-body padding would
   double-pad those — and showCloseButton would compete with the
   inner's own close affordance. The .rm-card--frameless modifier
   strips both so the inner UI fills the modal card edge-to-edge. */
.rm-card--frameless > .rm-body {
  padding: 0;
}
/* ── Wave 5e fix: EditInvoiceModal 2-panel body (2:1 desktop, stack phone) ──
   The original inline `2fr 1fr` grid kept the items table panel ~2x
   wider than the summary panel on desktop so the 5-col table (service
   select + qty + price + total + delete) had room to breathe. The
   first Wave 5e attempt swapped it for .l-grid--fixed-2 (always 50/50)
   which left the items table cramped on desktop. This class restores
   the 2:1 ratio on tablet+ and stacks to 1-col on phones via the
   720px breakpoint, matching the rest of the modal-body responsive
   pattern. */
/* V-Phase2 Wave 4b (ADR-134): `.edit-invoice-2col` retired.
   EditInvoiceModal now uses the unified vertical card-stack
   pattern (no 2fr+1fr split), so this class has no JSX
   consumers and the desktop 2:1 ratio is no longer needed.
   The new layout matches AddSessionModal + LabOrderModal +
   EditPurchaseInvoiceModal: header row → items cards →
   summary card → notes textarea. */
/* ── Wave 5c: Appointments WeekView 7-col stack on phones (<=480px) ──
   The original repeat(7, 1fr) lets 7 day columns share the viewport,
   which works on tablet+ but on a 360px phone gives each day cell
   ~51px - not enough room for the appointment pills (fontSize 10,
   patient name + time) to be readable. Stacking to 1 col makes each
   day a full sheet-width card; appointment lists inside stay readable.
   The 7-col fallback stays for the 481-768px tablet range.

   Override carries the inline `grid-template-columns` set in
   appointments.jsx (the WeekView grid is inline-styled), so the rule
   needs the same specificity (class + style attr selector). The
   element also carries `display: grid` inline, so we only need to
   change `grid-template-columns`. */
@media (max-width: 480px) {
  .appt-week-grid {
    grid-template-columns: 1fr !important;
  }
}
/* ── Wave 5c: Marketing calendar mk-cal-grid stack on phones (<=480px) ──
   Same pattern as the appointments week grid above. The marketing
   calendar is a 7-col x 4-row month view of scheduled posts; on
   <=720px we already shrink the font, but the 7 columns at 360px
   give each post card too little width. Stack the 28 cells vertically
   so each scheduled-post pill gets full width. */
@media (max-width: 480px) {
  .mk-cal-grid {
    grid-template-columns: 1fr;
  }
}
/* ── Wave 5b: Reception kanban vertical stack on phones (<=480px) ──
   At 5 columns x 180px min the horizontal-scroll board needs ~900px
   to show one column comfortably, which means a 360px phone shows
   roughly two columns at once and the user has to swipe sideways a
   lot to scan the workflow. On true phone widths we flip the board
   to a single-column vertical stack so each stage gets the full
   viewport width and reading order matches the workflow order
   (top to bottom). Drag-drop still works because the source-to-
   target gesture is still a directional drag; the browser handles
   vertical drag the same way it handled horizontal drag.

   Column headers are sticky so the stage label stays visible while
   the user scrolls long card lists inside the stage. Max-width is
   released to none so the column expands to the full sheet width. */
@media (max-width: 480px) {
  .kanban-board {
    grid-template-columns: 1fr;
    overflow-x: visible;
    scroll-snap-type: none;
    gap: 14px;
  }
  .kanban-col {
    min-width: 0;
    max-width: none;
    width: 100%;
  }
  .kanban-col-hdr {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--border);
  }
}
/* ════════════════════════════════════════════════════════════════════
   V-Reception (Phase 5 Wave 2) — hero + chip-tone count + per-stage
   empty + terminal-state softening. Touches:
     • .reception-hero-clock  → live clock pill in ReceptionHero
     • .kanban-count          → tighter chip sizing for the column tally
     • .kanban-empty-rich     → 3-line per-stage empty state body
     • .kanban-col-hdr        → +2px vertical padding (better hit area)
     • .kanban-col[data-stage="done"|"cancelled"] → terminal opacity
   The legacy `.reception-insight-strip` wrapper for the surfaced
   "نصيحة Modirify" Dashboard InsightCard was retired on 2026-06-02
   (owner direction: advice strip read as noise on the busiest screen).
   ──────────────────────────────────────────────────────────────────── */
.reception-hero-clock {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-elevated));
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  border: 1px solid color-mix(in srgb, var(--accent) 12%, transparent);
}
/* Tighten the chip when it lives in the kanban column header — the
   default chip padding feels chunky at this scale. tabular-nums keeps
   the digit width stable as cards.length crosses single → double. */
.kanban-col-hdr .chip.kanban-count {
  padding: 1px 8px;
  font-size: 11px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
}
/* Slightly taller header — old 8px 10px felt cramped vs the new chip. */
.kanban-col-hdr {
  padding: 10px 12px;
}
/* Terminal stages: done + cancelled are "settled" states, soften their
   header to imply finished work without losing readability. */
.kanban-col[data-stage="done"] .kanban-col-hdr,
.kanban-col[data-stage="cancelled"] .kanban-col-hdr {
  opacity: 0.92;
}
/* Rich per-stage empty state — replaces the legacy "icon + لا يوجد
   مرضى" with a 3-line layout (icon → title → hint). The .kanban-empty
   wrapper still owns padding + dashed border + pulseSoft animation;
   .kanban-empty-rich just structures the inner content. */
.kanban-empty-rich {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.kanban-empty-rich .kanban-empty-icon {
  font-size: 22px;
  opacity: 0.55;
  line-height: 1;
}
.kanban-empty-rich .kanban-empty-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
}
.kanban-empty-rich .kanban-empty-hint {
  font-size: 10px;
  color: var(--text-tertiary);
  text-align: center;
  max-width: 170px;
  line-height: 1.5;
}
/* When the column is a drop target, the parent .kanban-empty swaps to
   the "↓ اسحب هنا ↓" literal — kill the rich-empty animation noise so
   the drop affordance reads as a single beat. */
.kanban-empty.drop-active .kanban-empty-rich {
  display: none;
}
/* ════════════════════════════════════════════════════════════════════
   V-Appointments (Phase 5 Wave 2) — premium polish on Day/Week/Month
   + Reception-Dashboard merge surface (4 dashboard cards inline).
   ──────────────────────────────────────────────────────────────────── */
/* Today's calendar cell — kanban-style ring + accent-tinted bg so the
   "you are here" beacon is visible even on busy months. The existing
   .calendar-day.today rules in the original block carry the base
   styling; this override strengthens the visual beat. */
.calendar-day.today {
  background: color-mix(in srgb, var(--accent) 5%, var(--bg-elevated));
  box-shadow: inset 0 0 0 2px var(--accent);
}
.calendar-day.today .day-num {
  color: var(--accent);
  font-weight: 900;
}
/* Reception quick-row — 4-card grid hosting the surfaced Dashboard
   cards (Doctors / LowStock / RecentPatients / Outstanding). Grid
   collapses to 2 cols on tablet, 1 col on mobile. */
.reception-quick-row {
  /* layout is inline-styled; CSS hook for future surface adjustments. */
}
@media (max-width: 768px) {
  .reception-quick-row {
    grid-template-columns: 1fr !important;
  }
}
/* Appointments controls row — view toggle + filter dropdown + export.
   Just a hook for future adjustments; the row is laid out via inline
   flex styles. */
.appt-controls {
  /* hook */
}
/* ── Dashboard: doctor status row & list-item hovers (CSS-driven) ─ */
.card [style*="cursor:"][style*="pointer"]:not(.btn):not(.icon-btn) {
  border-radius: var(--radius-sm);
}
/* ── Empty state visual ──────────────────────────────────────────── */
.empty-state {
  animation: slideUp var(--duration-slow) var(--ease-out);
}
/* ════════════════════════════════════════════════════════════════════
   ✨ PREMIUM UX/UI POLISH — Phase 4 (Patients + Patient File)
   ════════════════════════════════════════════════════════════════════ */
/* ── Data tables: premium polish ─────────────────────────────────── */
.data-table {
  border-collapse: separate;
  border-spacing: 0;
}
.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-elevated);
  font-weight: 700;
  font-size: 12px;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
  border-bottom: 1px solid var(--border);
  transition: background var(--duration-fast) var(--ease-smooth);
}
.data-table tbody tr {
  transition:
    background-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-base) var(--ease-smooth);
  position: relative;
}
.data-table tbody tr:hover td {
  background-color: var(--bg-hover);
}
.data-table tbody tr td {
  transition: background-color var(--duration-fast) var(--ease-smooth);
}
/* ── Clickable table rows: hover indicator stripe (opt-in) ───────── */
.data-table.clickable tbody tr,
.data-table tbody tr[onclick],
.data-table tbody tr[role="button"] {
  cursor: pointer;
}
/* ADR-055 amendment #3: hover stripe is hosted on td:first-child, not
   on the tr itself. A ::before pseudo-element on <tr> with
   position: absolute (and tr position: relative) gets counted as an
   anonymous cell by Chrome's table column-width algorithm in
   direction: rtl, which shifts every tbody td by one column relative
   to the thead — breaking column alignment in .pf-canvas Invoices +
   Sessions tables. Hosting the pseudo on the first td keeps the
   stripe visible at the row's start edge without polluting column
   counting. Same visual; correct layout. */
.data-table.clickable tbody tr > td:first-child,
.data-table tbody tr[onclick] > td:first-child,
.data-table tbody tr[role="button"] > td:first-child {
  position: relative;
}
.data-table.clickable tbody tr > td:first-child::before,
.data-table tbody tr[onclick] > td:first-child::before,
.data-table tbody tr[role="button"] > td:first-child::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform var(--duration-base) var(--ease-spring);
  pointer-events: none;
}
.data-table.clickable tbody tr:hover > td:first-child::before,
.data-table tbody tr[onclick]:hover > td:first-child::before,
.data-table tbody tr[role="button"]:hover > td:first-child::before {
  transform: scaleY(0.7);
}
/* (pf3-* polish premium block deleted in V-PatientFile / ADR-055) */
/* ── Patients listing: stat tiles on top ─────────────────────────── */
.page-content > .grid > .card[style*="borderInlineStart"],
.page-content > .grid > div[style*="borderInlineStart"] {
  animation: slideUp var(--duration-slow) var(--ease-out) both;
}
/* ── Search input premium polish (used in patients filter) ───────── */
.search-input,
input[type="search"] {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
input[type="search"]:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
}
/* ── Filter chips/pills (used on patients & lists) ───────────────── */
.filter-chip,
.pill {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth);
  cursor: pointer;
}
.filter-chip:hover,
.pill:hover {
  transform: translateY(var(--lift-1));
  border-color: var(--border-strong);
}
.filter-chip.active,
.pill.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-text);
}
/* ── Patient avatars in lists (consistent visual) ────────────────── */
.avatar {
  position: relative;
  transition: transform var(--duration-base) var(--ease-spring);
}
tr:hover .avatar,
[role="row"]:hover .avatar {
  transform: scale(1.05);
}
/* (pf3-subscreen stagger + pf3-med-alert animation deleted in V-PatientFile / ADR-055) */
/* ── Modal polish for patient quick-add etc. ─────────────────────── */
.modal-backdrop {
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
}
/* ── Loading spinner premium ─────────────────────────────────────── */
[style*="animation: spin"] {
  filter: drop-shadow(0 2px 4px color-mix(in srgb, var(--accent) 30%, transparent));
}
/* ── Table cell numeric alignment ────────────────────────────────── */
.data-table td[data-numeric],
.data-table td.numeric {
  font-variant-numeric: tabular-nums;
  text-align: end;
}
/* ── Mobile patient file polish (safe overrides) ─────────────────── */
@media (max-width: 720px) {
  .data-table {
    font-size: 12px;
  }
}
/* ════════════════════════════════════════════════════════════════════
   ✨ PHASE 4.5 — UNIFIED CARD DESIGN SYSTEM
   ════════════════════════════════════════════════════════════════════
   5 variants. Use them everywhere. Replace inline JS hover handlers.

   .card                — base container, no hover
   .card.kpi            — stat card with hover lift + accent border
   .card.interactive    — clickable card, stronger hover lift + cursor
   .card.section        — content container, gentle hover on border only
   .card.feature        — hero/highlight card with accent stripe
   ──────────────────────────────────────────────────────────────────── */
/* ── .card.section: content container, subtle ───────────────────── */
.card.section {
  cursor: default;
}
.card.section:hover {
  border-color: var(--border-strong);
  /* no transform, no shadow change — keeps lists/tables stable */
}
/* ── .card.interactive: clickable, stronger hover ────────────────── */
.card.interactive {
  cursor: pointer;
  position: relative;
}
.card.interactive:hover {
  transform: translateY(var(--lift-2));
  box-shadow: var(--shadow-lg);
  border-color: color-mix(in srgb, var(--accent) 25%, var(--border));
}
/* ── .card.feature: hero with accent stripe ──────────────────────── */
.card.feature {
  position: relative;
  border-inline-start: 4px solid var(--accent);
  background:
    linear-gradient(135deg,
      color-mix(in srgb, var(--accent) 4%, var(--bg-card)) 0%,
      var(--bg-card) 60%);
  transition:
    box-shadow var(--duration-base) var(--ease-smooth),
    transform var(--duration-base) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth);
}
.card.feature:hover {
  transform: translateY(var(--lift-2));
  box-shadow: var(--shadow);
}
/* Feature variants by tone */
.card.feature.success { border-inline-start-color: var(--success); }
.card.feature.success { background: linear-gradient(135deg, color-mix(in srgb, var(--success) 4%, var(--bg-card)) 0%, var(--bg-card) 60%); }
.card.feature.danger  { border-inline-start-color: var(--danger); }
.card.feature.danger  { background: linear-gradient(135deg, color-mix(in srgb, var(--danger) 4%, var(--bg-card)) 0%, var(--bg-card) 60%); }
.card.feature.warning { border-inline-start-color: var(--warning); }
.card.feature.warning { background: linear-gradient(135deg, color-mix(in srgb, var(--warning) 4%, var(--bg-card)) 0%, var(--bg-card) 60%); }
.card.feature.info    { border-inline-start-color: var(--info); }
.card.feature.info    { background: linear-gradient(135deg, color-mix(in srgb, var(--info) 4%, var(--bg-card)) 0%, var(--bg-card) 60%); }
.card.feature.purple  { border-inline-start-color: var(--purple); }
.card.feature.purple  { background: linear-gradient(135deg, color-mix(in srgb, var(--purple) 4%, var(--bg-card)) 0%, var(--bg-card) 60%); }
/* ── .card.kpi: enhance — ensure consistent icon-box treatment ──── */
.card.kpi .kpi-icon,
.card.kpi [class*="icon-"]:not(.icon-btn) {
  transition: transform var(--duration-base) var(--ease-spring);
}
.card.kpi:hover .kpi-icon,
.card.kpi:hover [class*="icon-"]:not(.icon-btn) {
  transform: scale(1.08) rotate(-2deg);
}
/* ── Universal card entry animation (auto-stagger in grids) ──────── */
.grid > .card,
.grid > .card.kpi,
.grid > .card.interactive,
.grid > .card.feature,
.grid > .card.section {
  animation: slideUp var(--duration-slow) var(--ease-out) both;
}
.grid > *:nth-child(1) { animation-delay: 0ms; }
.grid > *:nth-child(2) { animation-delay: 50ms; }
.grid > *:nth-child(3) { animation-delay: 100ms; }
.grid > *:nth-child(4) { animation-delay: 150ms; }
.grid > *:nth-child(5) { animation-delay: 200ms; }
.grid > *:nth-child(6) { animation-delay: 250ms; }
/* ── Make sure hover lift never clips children visually ─────────── */
.card.kpi,
.card.interactive,
.card.feature {
  will-change: transform;
}
/* ════════════════════════════════════════════════════════════════════
   PHASE 5 -- Billing + Finance premium polish
   ════════════════════════════════════════════════════════════════════ */
/* -- Invoice/transaction rows: cursor + hover ---------------------- */
.data-table tbody tr[style*="cursor"]:hover td,
.data-table.invoices tbody tr:hover td,
.data-table.transactions tbody tr:hover td {
  background-color: var(--bg-hover);
}
/* -- Status chips: subtle pulse for unpaid/overdue ----------------- */
.chip.danger,
.chip.warning {
  position: relative;
}
.chip.danger::after,
.chip.warning::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  z-index: -1;
  animation: chipGlow 2s ease-in-out infinite;
}
@keyframes chipGlow {
  0%, 100% { opacity: 0; }
  50%      { opacity: 0.08; }
}
/* -- Tab bar buttons (finance/billing): unified active feel -------- */
button[style*="borderBottom"][style*="var(--accent)"] {
  position: relative;
  transition:
    color var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth);
}
/* -- Finance overview KPI icon box: scale on card hover ------------ */
.card.kpi:hover [style*="borderRadius: 8"][style*="background"][style*="display"]:not(.kpi-icon) {
  transform: scale(1.08) rotate(-2deg);
  transition: transform var(--duration-base) var(--ease-spring);
}
/* -- Lab orders / clickable KPI buttons: outline polish ------------ */
.card.interactive[style*="outline"] {
  transition:
    outline var(--duration-fast) var(--ease-smooth),
    transform var(--duration-base) var(--ease-smooth),
    box-shadow var(--duration-base) var(--ease-smooth);
}
/* ════════════════════════════════════════════════════════════════════
   V-1/4 (ADR-048) — Numeric typography utilities (Hybrid Stripe layer)
   ════════════════════════════════════════════════════════════════════
   Canonical hook for "numbers are the product" surfaces (Billing /
   Finance / Analytics / KPI values). Two utility classes:

     .num-tabular  — apply to ANY element displaying digits in a
                     column or grid where column-alignment matters
                     (table cells, KPI deltas, count badges).
     .num-currency — like .num-tabular plus right-alignment via
                     text-align: end (RTL-aware: end = visual right
                     in RTL too because the cell box itself is RTL-
                     anchored). Use on currency display elements
                     (invoice totals, expense amounts, balances).

   Both classes set font-variant-numeric: tabular-nums for modern
   browsers AND font-feature-settings: 'tnum' 1 as the older-browser
   fallback. Effective on Latin numerals (0-9) — Arabic-Indic digits
   (٠-٩) already have uniform width natively.

   Existing scattered inline declarations (lines 4691, 5391, 5565,
   5596, 5804, 6427, 7214) stay as legacy patterns until Wave 2
   V-Billing / V-Finance / V-Analytics tracks migrate them to these
   utility classes. The .data-table td.numeric pattern is the most
   important pre-existing hook (line 5389-5393); .num-tabular on
   the wrapper is the new alternative when a cell isn't inside a
   .data-table primitive.

   If Cairo's Latin numerals look insufficient in production
   tabular columns (subjective owner check during V-Billing), a
   V-1/4 follow-up can add `--font-num-stack: Inter, ...` as a token
   + apply it on .num-tabular. Not shipped now to avoid the extra
   Google Fonts network request without proof-of-need.
   ════════════════════════════════════════════════════════════════════ */
.num-tabular {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}
.num-currency {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  text-align: end;
}
/* ════════════════════════════════════════════════════════════════════
   V-1/5 (ADR-048) — Hero card soft gradient (Hybrid Stripe layer)
   ════════════════════════════════════════════════════════════════════
   Stripe's signature: a barely-there diagonal accent tint on hero
   surfaces (Finance Overview's `+12,400 ج.م` card, Analytics
   waterfall hero, Dashboard greeting card). Goes from accent-tinted
   in the corner to transparent at midpoint — adds depth without
   ornamentation.

   Strength controlled by --tint-hero-strength token (default 4%).
   V-1/3 dark themes may override the token if 4% is invisible on
   dark surfaces.

   Compose with existing .card classes — .tint-hero only sets the
   background-image, so .card.section + .tint-hero stacks bg + tint.
   ════════════════════════════════════════════════════════════════════ */
.tint-hero {
  background-image: linear-gradient(135deg,
    color-mix(in srgb, var(--accent) var(--tint-hero-strength), transparent) 0%,
    transparent 50%);
}
/* -- Money/numeric values: tabular-nums everywhere ----------------- */
.card.kpi [style*="fontWeight: 900"],
.card.kpi [style*="fontWeight:900"],
[style*="fontWeight: 900"][style*="fontSize: 2"],
[style*="fontWeight:900"][style*="fontSize:2"] {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
}
/* -- Invoice summary boxes (billing right rail) -------------------- */
.card.section[style*="height:'fit-content'"],
.card[style*="height:'fit-content'"] {
  position: sticky;
  top: 14px;
}
/* -- Aging buckets / progress visualization ------------------------ */
[data-aging-bar],
.aging-bar {
  transition: width var(--duration-slow) var(--ease-out);
}
/* -- Filter date preset pills (Finance Overview) ------------------- */
button[style*="DATE_PRESETS"],
.date-preset {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
/* -- Payment status badges (paid/partial/unpaid/overdue) ----------- */
.chip.success,
.chip.danger,
.chip.warning,
.chip.info {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}
/* -- Empty states inside cards (billing/finance lists) ------------- */
.card .empty-state,
.card [style*="padding: 40"][style*="textAlign"][style*="center"] {
  padding: var(--space-8) !important;
  color: var(--text-tertiary);
}
/* -- Mobile billing/finance: tighter spacing ----------------------- */
@media (max-width: 720px) {
  .grid.cols-4 {
    grid-template-columns: repeat(2, 1fr);
  }
  .grid.cols-5 {
    grid-template-columns: repeat(2, 1fr);
  }
}
/* ════════════════════════════════════════════════════════════════════
   PHASE 6 -- Settings + Admin + WhatsApp premium polish
   ════════════════════════════════════════════════════════════════════ */
/* -- Settings sub-tabs (general/staff/etc) ------------------------- */
[class*="settings-tab"],
.settings-nav button {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
/* -- Doctor profile cards: gentle interactive feel ----------------- */
.card[style*="textAlign: 'center'"]:has(.avatar.lg),
.card[style*='textAlign: "center"']:has(.avatar.lg) {
  transition:
    transform var(--duration-base) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-base) var(--ease-smooth);
}
.card[style*="textAlign: 'center'"]:has(.avatar.lg):hover,
.card[style*='textAlign: "center"']:has(.avatar.lg):hover {
  transform: translateY(var(--lift-2));
  box-shadow: var(--shadow);
  border-color: color-mix(in srgb, var(--accent) 18%, var(--border));
}
/* -- Avatar large (used in settings doctor cards) ------------------ */
.avatar.lg {
  width: 64px;
  height: 64px;
  font-size: 22px;
  border-radius: 18px;
  position: relative;
  overflow: hidden;
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: transform var(--duration-base) var(--ease-spring);
}
.avatar.lg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.16), transparent 55%);
  pointer-events: none;
  border-radius: inherit;
}
.card:hover .avatar.lg {
  transform: scale(1.05);
}
/* -- Admin clinics list rows ---------------------------------------- */
[data-clinic-row],
.clinic-row {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
[data-clinic-row]:hover,
.clinic-row:hover {
  background: var(--bg-hover);
}
/* -- WhatsApp message preview bubble polish ------------------------ */
.whatsapp-bubble,
[data-whatsapp-preview] {
  background: linear-gradient(135deg, #dcf8c6 0%, #d4f3b8 100%);
  border-radius: 12px;
  padding: 12px 16px;
  position: relative;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
/* -- WhatsApp template variable chips ------------------------------ */
[data-tmpl-var],
.template-var {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 6px;
  background: color-mix(in srgb, #25D366 12%, transparent);
  color: #128C7E;
  font-weight: 700;
  font-size: 11px;
  font-family: monospace;
  margin: 0 2px;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
[data-tmpl-var]:hover,
.template-var:hover {
  background: color-mix(in srgb, #25D366 22%, transparent);
  transform: scale(1.05);
}
/* -- Settings form fields: focus polish ---------------------------- */
.settings-form .input:focus,
.settings-form .select:focus,
.settings-form .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
/* -- Toggle/switch components polish ------------------------------- */
input[type="checkbox"] + label,
.toggle-switch {
  transition:
    background var(--duration-fast) var(--ease-smooth);
}
/* -- Admin permission grid items ----------------------------------- */
[data-permission-grid] > label,
.permission-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-smooth);
}
[data-permission-grid] > label:hover,
.permission-item:hover {
  background: var(--bg-hover);
}
/* -- Mobile settings/admin: card stacking -------------------------- */
@media (max-width: 720px) {
  .grid.cols-4 .card.kpi,
  .grid.cols-3 .card.kpi {
    padding: 12px !important;
  }
}
/* ════════════════════════════════════════════════════════════════════
   PHASE 7 -- Appointments + Marketing + Inventory + Patient-file
   ════════════════════════════════════════════════════════════════════ */
/* -- Appointments: calendar day cells polish ----------------------- */
[data-day-cell],
.mk-cal-cell,
.cal-cell {
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
.mk-cal-cell:hover,
.cal-cell:hover {
  border-color: var(--accent);
  transform: translateY(var(--lift-1));
}
/* -- Appointment row in calendar pill ------------------------------ */
.mk-cal-pill,
.cal-pill {
  transition:
    transform var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth);
}
.mk-cal-pill:hover,
.cal-pill:hover {
  transform: scale(1.02);
  box-shadow: var(--shadow-sm);
}
/* -- Marketing post cards -------------------------------------------- */
[class*="mk-post"],
[class*="mk-card"] {
  transition:
    transform var(--duration-base) var(--ease-smooth),
    box-shadow var(--duration-base) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth);
}
[class*="mk-post"]:hover,
[class*="mk-card"]:hover {
  transform: translateY(var(--lift-2));
  box-shadow: var(--shadow);
}
/* -- Marketing status chips ---------------------------------------- */
.mk-cal-pill-status,
[class*="mk-status"] {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth);
}
/* -- Inventory: progress bar with shimmer animation ---------------- */
[data-inventory-progress] .progress-bar,
.inventory-bar {
  position: relative;
  transition: width var(--duration-slow) var(--ease-out);
}
/* -- Inventory: low/critical stock rows ---------------------------- */
[data-stock-row][data-status="critical"] {
  background: color-mix(in srgb, var(--danger) 6%, var(--bg-card));
  animation: pulseSoft 3s ease-in-out infinite;
}
[data-stock-row][data-status="low"] {
  background: color-mix(in srgb, var(--warning) 6%, var(--bg-card));
}
/* -- Inventory: status badges (در stock / out / low) --------------- */
.inventory-status,
[data-stock-status] {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 99px;
  font-size: 11px;
  font-weight: 700;
  transition: transform var(--duration-fast) var(--ease-spring);
}
.inventory-status:hover,
[data-stock-status]:hover {
  transform: scale(1.04);
}
/* (pf3-subscreen + pf3-rx-card + pf3-note transitions deleted in V-PatientFile / ADR-055 — tooth animations folded into .pf-canvas--chart .tooth rules above) */
/* -- New appointment modal: time slot picker ----------------------- */
[data-time-slot] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-card);
  cursor: pointer;
  font-weight: 600;
  font-size: 13px;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
[data-time-slot]:hover {
  border-color: var(--accent);
  transform: translateY(var(--lift-1));
}
[data-time-slot].selected,
[data-time-slot][aria-pressed="true"] {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
/* -- Universal: all .card.kpi outline highlight on active filter --- */
.card.kpi[style*="boxShadow"] {
  transform: translateY(var(--lift-2));
}
/* -- Mobile: marketing calendar full-width ------------------------- */
@media (max-width: 720px) {
  .mk-cal-grid {
    font-size: 11px;
  }
}
/* ════════════════════════════════════════════════════════════════════
   PHASE 8A -- Premium Skeleton Loaders
   ════════════════════════════════════════════════════════════════════
   Replace blank/"..." loading states with shimmering placeholders.

   Usage:
     <div class="skeleton-text">    -> single line text placeholder
     <div class="skeleton-title">   -> bold title placeholder
     <div class="skeleton-number">  -> KPI value placeholder
     <div class="skeleton-circle">  -> avatar/icon placeholder
     <div class="skeleton-bar">     -> button/bar placeholder
     <div class="skeleton-block">   -> larger block placeholder
     <div class="skeleton-kpi">     -> full KPI card placeholder
     <div class="skeleton-row">     -> table row placeholder
   ──────────────────────────────────────────────────────────────────── */
.skeleton-text,
.skeleton-title,
.skeleton-number,
.skeleton-circle,
.skeleton-bar,
.skeleton-block,
.skeleton-kpi,
.skeleton-row {
  /* V-1/5 (ADR-048) — accent-tinted shimmer via §7 tokens */
  background: linear-gradient(
    90deg,
    var(--shimmer-base) 0%,
    var(--shimmer-highlight) 50%,
    var(--shimmer-base) 100%
  );
  background-size: 200% 100%;
  animation: shimmer var(--shimmer-duration) ease-in-out infinite;
  border-radius: var(--radius-sm);
  color: transparent !important;
  user-select: none;
  pointer-events: none;
  display: inline-block;
}
/* Variants */
.skeleton-text   { height: 12px; width: 70%;  border-radius: 4px; }
.skeleton-title  { height: 18px; width: 50%;  border-radius: 5px; }
.skeleton-number { height: 28px; width: 110px; border-radius: 6px; }
.skeleton-circle { height: 40px; width: 40px; border-radius: 50%; }
.skeleton-bar    { height: 32px; width: 100%; border-radius: var(--radius-sm); }
.skeleton-block  { height: 80px; width: 100%; border-radius: var(--radius); }
.skeleton-kpi    { height: 90px; width: 100%; border-radius: var(--radius-lg); display: block; }
.skeleton-row    { height: 48px; width: 100%; border-radius: var(--radius-sm); display: block; margin-bottom: 8px; }
/* Group: skeleton stack for a fake "list" */
.skeleton-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* When inside a card, skeletons inherit the card's padding */
.card .skeleton-text,
.card .skeleton-title,
.card .skeleton-number {
  display: block;
  margin-bottom: 8px;
}
/* V-9/2: Kanban-shape skeleton (Reception Suspense fallback). 3 columns
   side-by-side, each with a title shimmer + N card shimmers. Reads from
   --shimmer-base / --shimmer-highlight via inherited .skeleton-* classes. */
.skeleton-kanban {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  width: 100%;
}
.skeleton-kanban-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius);
  border: 1px solid var(--border);
}
.skeleton-kanban-card {
  height: 72px;
  width: 100%;
  border-radius: var(--radius-sm);
  display: block;
  background-color: var(--shimmer-base);
  background-image: linear-gradient(90deg, transparent, var(--shimmer-highlight), transparent);
  background-size: 200% 100%;
  animation: skeleton-shimmer var(--shimmer-duration) infinite linear;
}
@media (max-width: 768px) {
  .skeleton-kanban { grid-template-columns: 1fr; }
}
/* V-9/2: Form-shape skeleton (NewAppointment / NewInvoice fallback). Two-
   column responsive grid of label+input pairs. */
.skeleton-form {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  width: 100%;
}
.skeleton-form-field {
  display: flex;
  flex-direction: column;
}
@media (max-width: 768px) {
  .skeleton-form { grid-template-columns: 1fr; }
}
/* Subtle skeleton in dark mode (Luxe theme) */
[data-theme="luxe"] .skeleton-text,
[data-theme="luxe"] .skeleton-title,
[data-theme="luxe"] .skeleton-number,
[data-theme="luxe"] .skeleton-circle,
[data-theme="luxe"] .skeleton-bar,
[data-theme="luxe"] .skeleton-block,
[data-theme="luxe"] .skeleton-kpi,
[data-theme="luxe"] .skeleton-row {
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.04) 0%,
    rgba(255, 255, 255, 0.10) 50%,
    rgba(255, 255, 255, 0.04) 100%
  );
  background-size: 200% 100%;
}
/* Reduced motion: stop shimmer */
@media (prefers-reduced-motion: reduce) {
  .skeleton,
  .skeleton-text,
  .skeleton-title,
  .skeleton-number,
  .skeleton-circle,
  .skeleton-bar,
  .skeleton-block,
  .skeleton-kpi,
  .skeleton-row {
    animation: none;
    background: var(--bg-subtle);
  }
}
/* ════════════════════════════════════════════════════════════════════
   PHASE 8B -- Custom Confirm Dialog (replaces native confirm())
   ════════════════════════════════════════════════════════════════════ */
.confirm-dialog {
  /* Centering via the parent .modal-backdrop grid (display: grid + place-
     items: center). The earlier manual fixed-positioning pattern was
     clobbered by the modalIn keyframe ending in `transform: translateY(0)
     scale(1)` (animation-fill-mode: both), which overrode the centering
     transform and offset the dialog by half its size. Matches the
     .modal/.modal-box pattern at L980. ADR-064 amendment. */
  width: min(420px, calc(100vw - 32px));
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 24px 22px 20px;
  text-align: center;
  position: relative; /* z-index honoured without escaping the grid layout */
  z-index: 1001;
  animation: modalIn var(--duration-slow) var(--ease-out) both;
  will-change: transform, opacity;
}
.confirm-dialog__icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  margin: 0 auto 14px;
  display: grid;
  place-items: center;
  font-size: 28px;
  font-weight: 900;
  font-family: 'Cairo', sans-serif;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15);
  animation: scaleIn var(--duration-base) var(--ease-spring) both;
  animation-delay: 80ms;
}
.confirm-dialog__title {
  font-size: 18px;
  font-weight: 900;
  color: var(--text-primary);
  margin-bottom: 8px;
  letter-spacing: -0.01em;
}
.confirm-dialog__message {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  margin-bottom: 20px;
}
.confirm-dialog__actions {
  display: flex;
  gap: 10px;
  justify-content: stretch;
}
.confirm-dialog__actions .btn {
  flex: 1;
  min-height: 40px;
  font-weight: 700;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth),
    box-shadow var(--duration-fast) var(--ease-smooth),
    filter var(--duration-fast) var(--ease-smooth);
}
.confirm-dialog__actions .btn:hover:not(:disabled) {
  filter: brightness(1.06);
  transform: translateY(var(--lift-1));
}
.confirm-dialog__actions .btn:active:not(:disabled) {
  transform: translateY(0);
}
/* Backdrop blur enhancement for confirm */
.modal-backdrop:has(.confirm-dialog) {
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  background: rgba(0, 0, 0, 0.4);
}
/* Mobile */
@media (max-width: 480px) {
  .confirm-dialog {
    width: calc(100vw - 24px);
    padding: 20px 18px 16px;
  }
  .confirm-dialog__title { font-size: 16px; }
  .confirm-dialog__message { font-size: 12.5px; }
}
/* ════════════════════════════════════════════════════════════════════
   PHASE 8C -- Premium Toast Notification (top-center, clean look)
   U-10/1: ToastHost stacks up to MAX_VISIBLE toasts in a flex column;
   the .toast-stack wrapper owns positioning + centering, .toast items
   are flow-laid inside.
   ════════════════════════════════════════════════════════════════════ */
/* The stack wrapper handles fixed positioning + RTL-agnostic centering.
   Explicit left/right (not inset-inline-*) per the Phase 8C hot-fix
   reasoning: in RTL the logical pair resolves opposite to what
   centering needs and breaks the centered alignment. */
.toast-stack {
  position: fixed;
  top: 20px;
  left: 50%;
  right: auto;
  bottom: auto;
  transform: translateX(-50%);
  z-index: 3000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  pointer-events: none;
  max-width: 100vw;
}
/* Reset legacy Phase 1 .toast positioning (line ~1432 block, dead but
   still cascades — was previously suppressed by Phase 8C !important
   rules; without those it leaks fixed/bottom/inset-inline-end into the
   stack). Toasts inside the stack are flow-laid. */
.toast-stack > .toast {
  position: static;
  inset: auto;
  pointer-events: auto;
  max-width: 100%;
}
.toast {
  min-width: 280px;
  max-width: 480px;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow:
    0 10px 30px rgba(0, 0, 0, 0.12),
    0 4px 12px rgba(0, 0, 0, 0.06);
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  color: var(--text-primary);
  animation: toastSlideIn 320ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes toastSlideIn {
  from { opacity: 0; transform: translateY(-16px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)      scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}
/* V-9/4: Type variants — subtle tint (color-mix) + colored left-border
   + colored icon chip. Stronger visual differentiation than icon-only;
   left-border survives at-a-glance scanning even when message is long.
   border-inline-start picks the right edge in RTL automatically. */
.toast.success {
  background: color-mix(in srgb, var(--success) 5%, var(--bg-elevated));
  border-inline-start: 3px solid var(--success);
}
.toast.danger {
  background: color-mix(in srgb, var(--danger) 6%, var(--bg-elevated));
  border-inline-start: 3px solid var(--danger);
}
.toast.warning {
  background: color-mix(in srgb, var(--warning) 6%, var(--bg-elevated));
  border-inline-start: 3px solid var(--warning);
}
.toast.info {
  background: color-mix(in srgb, var(--info) 5%, var(--bg-elevated));
  border-inline-start: 3px solid var(--info);
}
.toast.success .toast-icon { background: var(--success-soft); color: var(--success); }
.toast.danger  .toast-icon { background: var(--danger-soft);  color: var(--danger); }
.toast.warning .toast-icon { background: var(--warning-soft); color: var(--warning); }
.toast.info    .toast-icon { background: var(--info-soft);    color: var(--info); }
/* Icon sized down, cleaner */
.toast-icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.toast-msg {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--text-primary);
  padding-inline: 2px;
}
.toast-close {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  background: transparent;
  border: none;
  color: var(--text-tertiary);
  cursor: pointer;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth);
}
.toast-close:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}
/* Toast action button — Undo / retry / view (U-3, foundation for U-10) */
.toast-action {
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 999px;
  padding: 5px 12px;
  cursor: pointer;
  flex-shrink: 0;
  white-space: nowrap;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
.toast-action:hover {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.toast-action:active {
  transform: scale(0.96);
}
.toast-action:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus, 0 0 0 3px var(--ring-color, color-mix(in srgb, var(--accent) 35%, transparent)));
}
/* Mobile: full width minus margins (applied to the stack wrapper now;
   individual toasts inherit width via the flex column). */
@media (max-width: 480px) {
  .toast-stack {
    top: 12px;
    width: calc(100vw - 24px);
  }
  .toast-stack > .toast {
    width: 100%;
    min-width: 0;
    max-width: none;
  }
}
/* ════════════════════════════════════════════════════════════════════
   WHATSAPP SCREEN -- premium redesign
   ════════════════════════════════════════════════════════════════════ */
/* V-WhatsApp/1 (ADR-059): bespoke .wa-header + .wa-pulse-dot + waPulse
   keyframe deleted. The WhatsApp screen now uses the canonical
   .dash-hero shell (ninth instance) — see WhatsAppHero in
   screens/patients/whatsapp-reminders-screen.jsx. Removing ~85 lines
   of legacy gradient-header CSS that duplicated dash-hero's role. */
/* -- Premium Status Card -------------------------------------------- */
.wa-status-card {
  display: flex;
  align-items: center;
  gap: 16px;
  background: linear-gradient(135deg,
    color-mix(in srgb, #25D366 6%, var(--bg-card)) 0%,
    var(--bg-card) 60%);
  border: 1px solid color-mix(in srgb, #25D366 30%, var(--border));
  border-radius: var(--radius-lg);
  padding: 18px 22px;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--duration-base) var(--ease-smooth),
              transform var(--duration-base) var(--ease-smooth);
}
.wa-status-card:hover {
  transform: translateY(var(--lift-1));
  box-shadow: var(--shadow);
}
.wa-status-icon-wrap {
  flex-shrink: 0;
}
.wa-status-icon-circle {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: linear-gradient(135deg, #25D366 0%, #128C7E 100%);
  display: grid;
  place-items: center;
  font-size: 26px;
  color: #fff;
  box-shadow: 0 6px 14px color-mix(in srgb, #25D366 35%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.wa-status-body {
  flex: 1;
  min-width: 0;
}
.wa-status-title {
  font-size: 15px;
  font-weight: 900;
  color: var(--text-primary);
  margin-bottom: 4px;
  letter-spacing: -0.01em;
}
.wa-status-sub {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: 500;
}
.wa-status-quota {
  flex-shrink: 0;
  min-width: 140px;
  text-align: left;
}
.wa-status-quota-label {
  font-size: 10px;
  color: var(--text-tertiary);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 4px;
}
.wa-status-quota-value {
  font-size: 16px;
  font-weight: 900;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  margin-bottom: 6px;
}
.wa-status-quota-bar {
  height: 6px;
  background: var(--bg-subtle);
  border-radius: 99px;
  overflow: hidden;
}
.wa-status-quota-fill {
  height: 100%;
  background: linear-gradient(90deg, #25D366, #128C7E);
  border-radius: 99px;
  transition: width var(--duration-slow) var(--ease-out);
}
.wa-status-quota-fill.is-warning {
  background: linear-gradient(90deg, #f59e0b, #d97706);
}
.wa-status-quota-fill.is-full {
  background: linear-gradient(90deg, #ef4444, #b91c1c);
}
/* Status card variants */
.wa-status-card.wa-quota-exceeded {
  border-color: color-mix(in srgb, var(--danger) 40%, var(--border));
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--danger) 5%, var(--bg-card)) 0%,
    var(--bg-card) 60%);
}
.wa-status-card.wa-quota-exceeded .wa-status-icon-circle {
  background: linear-gradient(135deg, var(--danger), #b91c1c);
  box-shadow: 0 6px 14px color-mix(in srgb, var(--danger) 35%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
/* V-WhatsApp/2 (ADR-059): bespoke .wa-tabs + .wa-tab-badge deleted.
   The WhatsApp screen now uses the shared <Tabs> primitive (.tabs +
   .tab + .tab-count classes) — see WhatsAppRemindersV2's wa-tabs-wrap
   render in screens/patients/whatsapp-reminders-screen.jsx. */
/* -- Quick Action button -------------------------------------------- */
.wa-quick-action {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
  text-align: start;
  font-family: inherit;
  width: 100%;
}
.wa-quick-action:hover {
  background: var(--bg-hover);
  border-color: color-mix(in srgb, #25D366 30%, var(--border));
  transform: translateY(var(--lift-1));
}
.wa-quick-action-icon {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: color-mix(in srgb, #25D366 12%, transparent);
  display: grid;
  place-items: center;
  font-size: 20px;
  flex-shrink: 0;
}
/* -- Activity row --------------------------------------------------- */
.wa-activity-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--ease-smooth);
}
.wa-activity-row:hover {
  background: var(--bg-hover);
}
/* -- Automation Rule Card -------------------------------------------- */
.wa-rule-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
.wa-rule-card:hover {
  transform: translateY(var(--lift-1));
}
.wa-rule-card.active {
  background: color-mix(in srgb, #25D366 6%, var(--bg-card));
  border-color: #25D366;
  box-shadow: 0 0 0 3px color-mix(in srgb, #25D366 12%, transparent);
}
.wa-rule-icon {
  font-size: 24px;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: color-mix(in srgb, #25D366 8%, var(--bg-subtle));
  flex-shrink: 0;
}
.wa-rule-card.active .wa-rule-icon {
  background: color-mix(in srgb, #25D366 18%, transparent);
}
.wa-rule-body {
  flex: 1;
  min-width: 0;
}
.wa-rule-title {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-primary);
  margin-bottom: 2px;
}
.wa-rule-sub {
  font-size: 11.5px;
  color: var(--text-tertiary);
}
/* -- Per-rule edit button (auto-rule template customization) ---------- */
.wa-rule-edit-btn {
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: 16px;
  cursor: pointer;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  margin-inline-end: 8px;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
.wa-rule-edit-btn:hover {
  background: var(--bg-hover);
  border-color: #25D366;
  color: #128C7E;
  transform: translateY(var(--lift-1));
}
.wa-rule-edit-dot {
  position: absolute;
  top: 4px;
  inset-inline-end: 4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #25D366;
  box-shadow: 0 0 0 2px var(--bg-card);
}
/* -- Toggle Switch (premium) ----------------------------------------- */
.wa-toggle {
  width: 44px;
  height: 24px;
  border-radius: 99px;
  background: var(--border);
  position: relative;
  cursor: pointer;
  transition: background var(--duration-base) var(--ease-smooth);
  flex-shrink: 0;
}
.wa-toggle.on {
  background: #25D366;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.15);
}
.wa-toggle-knob {
  position: absolute;
  top: 2px;
  inset-inline-start: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
  transition: inset-inline-start var(--duration-base) var(--ease-spring);
}
.wa-toggle.on .wa-toggle-knob {
  inset-inline-start: 22px;
}
/* -- WhatsApp-Style Preview (manual tab) ----------------------------- */
.wa-preview-bg {
  background:
    repeating-linear-gradient(45deg, rgba(0,0,0,0.015) 0 1px, transparent 1px 14px),
    #dfe7d8;
  border-radius: 12px;
  padding: 16px 14px;
  min-height: 80px;
}
.wa-bubble {
  background: #fff;
  border-radius: 0 12px 12px 12px;
  padding: 10px 14px;
  max-width: 92%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.13);
  display: inline-block;
}
[dir="ltr"] .wa-bubble {
  border-radius: 12px 0 12px 12px;
}
.wa-bubble-text {
  font-size: 13.5px;
  line-height: 1.65;
  color: #111;
  white-space: pre-wrap;
  word-break: break-word;
}
.wa-bubble-meta {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 4px;
  margin-top: 5px;
  font-size: 10px;
  color: #999;
}
.wa-bubble-ticks {
  color: #53bdeb;
  font-size: 13px;
}
/* -- Reduced motion: stop pulse -------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .wa-pulse-dot::after {
    animation: none;
  }
}
/* -- Mobile responsive ----------------------------------------------- */
@media (max-width: 720px) {
  .wa-status-card {
    flex-direction: column;
    align-items: flex-start;
    text-align: center;
  }
  .wa-status-quota {
    text-align: center;
    width: 100%;
  }
  .wa-header {
    padding: 12px 16px;
  }
  .wa-tabs .tab {
    font-size: 12px;
    padding: 10px 12px;
  }
}
/* ════════════════════════════════════════════════════════════════════
   WHATSAPP INBOX -- WhatsApp-style chat UI
   ════════════════════════════════════════════════════════════════════ */
.wa-inbox-grid {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 16px;
  align-items: start;
  height: calc(100vh - 280px);
  min-height: 540px;
}
/* -- Conversations list (left) -------------------------------------- */
.wa-inbox-list {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}
.wa-inbox-list-header {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-elevated);
}
.wa-inbox-list-body {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}
.wa-inbox-list-footer {
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.wa-inbox-unread-badge {
  background: #25D366;
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  padding: 3px 9px;
  border-radius: 99px;
  box-shadow: 0 2px 6px color-mix(in srgb, #25D366 35%, transparent);
}
/* -- Thread row -------------------------------------------------------- */
.wa-thread-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  border: none;
  background: transparent;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  text-align: start;
  font-family: inherit;
  transition:
    background var(--duration-fast) var(--ease-smooth);
}
.wa-thread-row:hover {
  background: var(--bg-hover);
}
.wa-thread-row.active {
  background: color-mix(in srgb, #25D366 8%, var(--bg-card));
  border-inline-start: 3px solid #25D366;
}
.wa-thread-row.unread {
  background: color-mix(in srgb, var(--accent) 4%, var(--bg-card));
}
.wa-thread-row.unread.active {
  background: color-mix(in srgb, #25D366 12%, var(--bg-card));
}
.wa-thread-name {
  font-weight: 700;
  font-size: 13.5px;
  color: var(--text-primary);
  margin-bottom: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wa-thread-row.unread .wa-thread-name {
  font-weight: 900;
}
.wa-thread-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #25D366;
  box-shadow: 0 0 0 2px color-mix(in srgb, #25D366 25%, transparent);
  flex-shrink: 0;
  display: inline-block;
}
.wa-thread-preview {
  font-size: 12px;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wa-thread-row.unread .wa-thread-preview {
  color: var(--text-secondary);
  font-weight: 600;
}
.wa-thread-time {
  font-size: 10px;
  color: var(--text-tertiary);
  white-space: nowrap;
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 2px;
}
/* -- Chat thread (right) ---------------------------------------------- */
.wa-inbox-thread {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}
.wa-thread-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  background: var(--bg-elevated);
}
/* WhatsApp chat background pattern */
.wa-thread-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background:
    repeating-linear-gradient(45deg, rgba(0,0,0,0.012) 0 1px, transparent 1px 14px),
    #e5ddd5;
  min-height: 0;
}
[data-theme="luxe"] .wa-thread-body {
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,0.02) 0 1px, transparent 1px 14px),
    #0a1117;
}
.wa-msg-wrap {
  display: flex;
  width: 100%;
}
.wa-msg-wrap.sent {
  justify-content: flex-end;
}
.wa-msg-wrap.received {
  justify-content: flex-start;
}
.wa-msg-bubble {
  max-width: 75%;
  padding: 8px 12px 6px;
  font-size: 13.5px;
  line-height: 1.55;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.13);
  position: relative;
  word-break: break-word;
  animation: waBubbleIn 220ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.wa-msg-bubble.sent {
  background: #dcf8c6;
  color: #111;
  border-radius: 12px 0 12px 12px;
}
[dir="ltr"] .wa-msg-bubble.sent {
  border-radius: 0 12px 12px 12px;
}
.wa-msg-bubble.received {
  background: #fff;
  color: #111;
  border-radius: 0 12px 12px 12px;
}
[dir="ltr"] .wa-msg-bubble.received {
  border-radius: 12px 0 12px 12px;
}
@keyframes waBubbleIn {
  from { opacity: 0; transform: translateY(6px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.wa-msg-text {
  white-space: pre-wrap;
  word-break: break-word;
}
.wa-msg-meta {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 4px;
  margin-top: 3px;
  font-size: 10px;
  color: rgba(0, 0, 0, 0.45);
}
.wa-msg-ticks {
  font-size: 13px;
  color: rgba(0, 0, 0, 0.4);
  letter-spacing: -2px;
}
.wa-msg-ticks.delivered {
  color: #53bdeb;
}
.wa-msg-ticks.sending {
  color: rgba(0, 0, 0, 0.3);
}
/* -- Suggestions row -------------------------------------------------- */
.wa-thread-suggestions {
  padding: 8px 14px;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
  flex-shrink: 0;
}
.wa-suggestion-chip {
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 99px;
  background: var(--bg-card);
  font-size: 11.5px;
  cursor: pointer;
  font-family: inherit;
  color: var(--text-secondary);
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    border-color var(--duration-fast) var(--ease-smooth);
  white-space: nowrap;
}
.wa-suggestion-chip:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-text);
}
/* -- Reply box -------------------------------------------------------- */
.wa-thread-reply {
  padding: 12px 14px;
  display: flex;
  gap: 8px;
  align-items: flex-end;
  flex-shrink: 0;
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
}
.wa-send-btn {
  background: #25D366;
  color: #fff;
  border-color: #25D366;
  min-width: 100px;
  height: 44px;
  font-weight: 800;
}
.wa-send-btn:hover:not(:disabled) {
  background: #128C7E;
  border-color: #128C7E;
  box-shadow: 0 4px 12px color-mix(in srgb, #25D366 30%, transparent);
}
.wa-thread-reply-hint {
  padding: 4px 14px 10px;
  font-size: 10px;
  color: var(--text-tertiary);
  background: var(--bg-elevated);
  flex-shrink: 0;
  border-bottom-left-radius: var(--radius-lg);
  border-bottom-right-radius: var(--radius-lg);
}
/* -- Mobile inbox layout --------------------------------------------- */
@media (max-width: 900px) {
  .wa-inbox-grid {
    grid-template-columns: 1fr;
    height: auto;
  }
  .wa-inbox-list {
    max-height: 320px;
  }
  .wa-inbox-thread {
    height: 60vh;
  }
}
/* ════════════════════════════════════════════════════════════════════
   WhatsApp Confirmation Link Realtime Highlights
   When a patient confirms/cancels/reschedules via a Modirify link,
   the matching appointment card in Reception/Appointments briefly
   highlights to alert the staff.
   ════════════════════════════════════════════════════════════════════ */
.wa-just-changed {
  animation: waChangedPulse 1.6s ease-out 3, waChangedFade 8s ease-out forwards;
  position: relative;
}
.wa-just-changed--confirm {
  --wa-action-color: #25D366;
  --wa-action-soft: rgba(37, 211, 102, 0.16);
}
.wa-just-changed--cancel {
  --wa-action-color: #ef4444;
  --wa-action-soft: rgba(239, 68, 68, 0.16);
}
.wa-just-changed--reschedule {
  --wa-action-color: #f59e0b;
  --wa-action-soft: rgba(245, 158, 11, 0.16);
}
@keyframes waChangedPulse {
  0%   { box-shadow: 0 0 0 0    var(--wa-action-soft, rgba(37,211,102,.20)); }
  50%  { box-shadow: 0 0 0 8px  transparent; }
  100% { box-shadow: 0 0 0 0    transparent; }
}
@keyframes waChangedFade {
  0%   { background-color: var(--wa-action-soft, rgba(37,211,102,.12)); }
  60%  { background-color: var(--wa-action-soft, rgba(37,211,102,.06)); }
  100% { background-color: inherit; }
}
/* Kanban card variant: leans on existing card styles */
.kanban-card.wa-just-changed {
  border-color: var(--wa-action-color, #25D366) !important;
  border-width: 2px;
}
/* Table row variant for appointments list */
tr.wa-just-changed > td {
  background-color: var(--wa-action-soft, rgba(37,211,102,.10)) !important;
}
/* Confirmation badge displayed inside the affected card */
.wa-confirm-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: 99px;
  background: var(--wa-action-color, #25D366);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  margin-bottom: 8px;
  letter-spacing: 0.01em;
  animation: slideDown 360ms cubic-bezier(.16,1,.3,1) both;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--wa-action-color, #25D366) 35%, transparent);
}
/* Small tag for table rows (less intrusive) */
.wa-modirify-tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 99px;
  background: var(--wa-action-soft, rgba(37,211,102,.16));
  color: var(--wa-action-color, #25D366);
  letter-spacing: 0.01em;
  white-space: nowrap;
  animation: slideDown 280ms cubic-bezier(.16,1,.3,1) both;
}
@media (prefers-reduced-motion: reduce) {
  .wa-just-changed { animation: none; }
}
/* ═══════════════════════════════════════════════════════════════
   SPRINT 1 — DASHBOARD 2.0 + FOUNDATION COMPONENTS
═══════════════════════════════════════════════════════════════ */
/* Dashboard Hero — the morning greeting card */
.dash-hero {
  position: relative;
  overflow: hidden;
  border-radius: 22px;
  padding: 28px 32px;
  background:
    radial-gradient(at 80% 0%, color-mix(in srgb, var(--accent) 18%, transparent) 0%, transparent 50%),
    radial-gradient(at 20% 100%, color-mix(in srgb, var(--accent) 10%, transparent) 0%, transparent 55%),
    linear-gradient(135deg, var(--bg-elevated) 0%, var(--bg-card) 100%);
  border: 1px solid var(--border);
  box-shadow: 0 4px 24px color-mix(in srgb, var(--accent) 6%, transparent);
  margin-bottom: 24px;
}
.dash-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--text-primary) 5%, transparent) 1px, transparent 0);
  background-size: 24px 24px;
  opacity: 0.4;
  pointer-events: none;
}
.dash-hero-inner {
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
.dash-hero-greet { font-size: 13px; font-weight: 700; color: var(--text-tertiary); letter-spacing: 0.02em; margin-bottom: 6px; }
.dash-hero-title { font-size: 28px; font-weight: 900; color: var(--text-primary); line-height: 1.2; letter-spacing: -0.02em; }
.dash-hero-title .accent-name {
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 70%, #0ea5e9 30%));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.dash-hero-sub { font-size: 14px; color: var(--text-secondary); margin-top: 8px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dash-hero-sub .date-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px; border-radius: 99px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  color: var(--accent);
  font-size: 12px; font-weight: 700;
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
}
.dash-hero-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* Primary metric tile — 3 large cards under the hero */
.metric-tile {
  position: relative;
  padding: 22px 24px;
  border-radius: 18px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base), border-color var(--duration-base);
  cursor: pointer;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.metric-tile::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(135deg, var(--tile-tint, transparent) 0%, transparent 60%);
  opacity: 0.6;
  pointer-events: none;
}
.metric-tile:hover {
  transform: translateY(var(--lift-3));
  box-shadow: 0 12px 32px color-mix(in srgb, var(--tile-color, var(--accent)) 14%, transparent);
  border-color: color-mix(in srgb, var(--tile-color, var(--accent)) 40%, var(--border));
}
.metric-tile-head { display: flex; align-items: center; gap: 10px; }
.metric-tile-icon {
  width: 36px; height: 36px; border-radius: 12px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--tile-color, var(--accent)) 12%, var(--bg-elevated));
  color: var(--tile-color, var(--accent));
  font-size: 18px;
  flex-shrink: 0;
}
.metric-tile-label {
  font-size: 12px; font-weight: 700; color: var(--text-tertiary);
  letter-spacing: 0.04em; text-transform: uppercase;
}
.metric-tile-value {
  /* V-Mobile/KpiTypo (MOBILE_ARCHITECTURE §8.2) — fluid clamp scales
     the KPI number with viewport instead of an abrupt step at the
     mobile breakpoint. Mobile 22px → tablet ~28px → desktop 36px.
     The owner reported the previous fixed 28px on mobile felt too
     big for single-digit / 4-digit currency values. */
  font-size: clamp(1.375rem, 2vw + 1rem, 2.25rem);  /* 22px → 36px */
  font-weight: 900; color: var(--text-primary); line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.metric-tile-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.metric-tile-trend {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; font-weight: 800;
  padding: 3px 10px; border-radius: 99px;
}
.metric-tile-trend.up    { background: color-mix(in srgb, var(--success) 12%, transparent); color: var(--success); }
.metric-tile-trend.down  { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger); }
.metric-tile-trend.flat  { background: color-mix(in srgb, var(--text-tertiary) 10%, transparent); color: var(--text-tertiary); }
.metric-tile-hint { font-size: 11px; color: var(--text-tertiary); font-weight: 600; }
/* Section header */
.section-head {
  display: flex; align-items: center; justify-content: space-between;
  margin: 28px 0 12px;
  gap: 10px;
}
.section-head h2 { font-size: 14px; font-weight: 800; color: var(--text-primary); letter-spacing: 0.02em; margin: 0; }
.section-head .section-sub { font-size: 12px; color: var(--text-tertiary); font-weight: 500; }
.section-head .section-actions { display: flex; gap: 6px; align-items: center; }
/* Polished empty state with action button */
.empty-state.v2 {
  display: flex; flex-direction: column; align-items: center;
  padding: 36px 20px; text-align: center; gap: 12px;
}
.empty-state.v2 .empty-state-icon {
  width: 64px; height: 64px; border-radius: 18px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  color: var(--accent);
  display: grid; place-items: center; font-size: 28px;
  margin-bottom: 4px;
}
.empty-state.v2 .empty-state-title { font-size: 15px; font-weight: 800; color: var(--text-primary); }
.empty-state.v2 .empty-state-text { font-size: 13px; color: var(--text-tertiary); max-width: 320px; line-height: 1.5; }
.empty-state.v2 .empty-state-action { margin-top: 6px; }
/* Smooth staggered fade-in */
@keyframes dash-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.dash-rise   { animation: dash-rise 420ms cubic-bezier(.16,1,.3,1) both; }
.dash-rise.d1 { animation-delay: 40ms; }
.dash-rise.d2 { animation-delay: 90ms; }
.dash-rise.d3 { animation-delay: 140ms; }
.dash-rise.d4 { animation-delay: 200ms; }
.dash-rise.d5 { animation-delay: 250ms; }
/* Mobile responsiveness */
@media (max-width: 768px) {
  .dash-hero { padding: 20px 18px; border-radius: 18px; }
  .dash-hero-title { font-size: 22px; }
  .dash-hero-inner { flex-direction: column; align-items: flex-start; }
  .metric-tile { padding: 18px 18px; }
  /* V-Mobile/KpiTypo (§8.2): mobile-specific override removed — the
     fluid clamp on .metric-tile-value handles mobile scaling now
     (22px at <= 480px viewport). The compact variant uses the same
     fluid scaling so both stay visually aligned across screens. */
}
/* ═══════════════════════════════════════════════════════════════
   SPRINT 1.2 — RECEPTION 2.0 (Drag-drop kanban polish)
═══════════════════════════════════════════════════════════════ */
/* Drag affordance: cursor + subtle indicator on hover */
.kanban-card[draggable="true"] {
  cursor: grab;
  user-select: none;
}
.kanban-card[draggable="true"]:active { cursor: grabbing; }
/* While the card is being dragged */
.kanban-card.dragging {
  opacity: 0.4;
  transform: scale(0.97);
  cursor: grabbing;
  box-shadow: 0 12px 28px color-mix(in srgb, var(--accent) 22%, transparent);
  transition: opacity var(--duration-fast), transform var(--duration-fast), box-shadow var(--duration-fast);
}
/* The column where a card can be dropped (hovered over) */
.kanban-col.drop-target {
  background: color-mix(in srgb, var(--accent) 6%, var(--bg-elevated));
  outline: 2px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: -2px;
  transition: background var(--duration-fast), outline-color var(--duration-fast);
}
.kanban-col.drop-target .kanban-col-hdr {
  background: color-mix(in srgb, var(--accent) 14%, var(--bg-subtle)) !important;
}
/* Forbidden drop target (same column or invalid transition) */
.kanban-col.drop-forbidden {
  background: color-mix(in srgb, var(--danger) 5%, var(--bg-elevated));
  outline: 2px dashed color-mix(in srgb, var(--danger) 45%, transparent);
  outline-offset: -2px;
}
/* Drag-handle dot shown in top-right corner of card on hover */
.kanban-card .drag-hint {
  position: absolute;
  top: 6px; inset-inline-end: 8px;
  font-size: 12px; color: var(--text-tertiary);
  opacity: 0;
  transition: opacity var(--duration-fast);
  pointer-events: none;
}
.kanban-card:hover .drag-hint { opacity: 0.55; }
/* Smooth kanban col animation when cards rearrange */
.kanban-col .kanban-cards-stack {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px; min-height: 90px;
  transition: background var(--duration-fast);
}
/* Drop-into-column hint shown when column is empty + targeted */
.kanban-empty.drop-active {
  border: 2px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  color: var(--accent);
  font-weight: 700;
}
/* Reception KPI row uses the metric-tile system but a compact variant.
   V-Mobile/KpiTypo (§8.2) — compact also uses fluid clamp so the
   single-digit values (e.g., "1 مرضى جدد") don't dominate the card
   on mobile. Mobile 18px → tablet ~22px → desktop 28px. */
.metric-tile.compact { padding: 14px 16px; }
.metric-tile.compact .metric-tile-value {
  font-size: clamp(1.125rem, 1.5vw + 0.75rem, 1.75rem);  /* 18px → 28px */
}
.metric-tile.compact .metric-tile-icon { width: 30px; height: 30px; font-size: 15px; }
.metric-tile.compact .metric-tile-label { font-size: 11px; }
/* Spring landing animation — applied to a card for 350ms after it's
   dropped into a new column. The cubic-bezier y-value > 1 produces
   the overshoot bounce (scale peaks ~1.04 around 60% of the duration
   before settling at 1). Reception toggles `.is-just-landed` via
   justLandedId state in onDropCol. */
@keyframes kanban-card-land {
  from { transform: scale(0.94); }
  to   { transform: scale(1); }
}
.kanban-card.is-just-landed {
  animation: kanban-card-land 350ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  .kanban-card.dragging { transform: none; }
  .kanban-card.is-just-landed { animation: none; }
  .kanban-col.drop-target { transition: none; }
}
/* ════════════════════════════════════════════════════════════════════
   U-2 PRIMITIVE SUPPLEMENT — Tabs
   ════════════════════════════════════════════════════════════════════
   Adds the count badge, size, and full-width variants consumed by
   the Tabs JSX primitive in app/src/ui/tabs.jsx. The base .tab /
   .tabs styles from earlier in this file remain canonical and are
   not touched. New tokens (--text-sm, --text-2xs) come from
   tokens.css (ADR-017).
*/
.tabs-full { width: 100%; }
.tabs-full .tab { flex: 1 1 0; justify-content: center; }
.tabs-sm .tab,
.tab.sm {
  min-height: 36px;
  padding: 7px 12px;
  font-size: var(--text-sm);
}
.tab .tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  margin-inline-start: 6px;
  border-radius: 999px;
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.tab.active .tab-count {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.tab.is-disabled,
.tab[aria-disabled="true"],
.tab:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
/* ════════════════════════════════════════════════════════════════════
   U-2 PRIMITIVE SUPPLEMENT — Tooltip
   ════════════════════════════════════════════════════════════════════
   Styles for app/src/ui/tooltip.jsx. The tooltip portal-renders into
   <body> so this class doesn't need to coexist with screen layouts.
   Uses tokens for z-index (--z-tooltip), type (--text-xs), radius,
   and motion easing (--ease-out). High-contrast colour-inverts on
   dark themes.
*/
.ui-tooltip {
  z-index: var(--z-tooltip);
  max-width: 280px;
  padding: 7px 11px;
  border-radius: var(--radius-sm);
  background: rgba(15, 23, 42, 0.92);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: var(--leading-snug);
  letter-spacing: 0;
  pointer-events: none;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.22), 0 2px 4px rgba(0, 0, 0, 0.12);
  animation: tooltipIn 160ms var(--ease-out) both;
}
[data-theme="luxe"] .ui-tooltip,
[data-theme="midnight"] .ui-tooltip {
  background: rgba(241, 245, 251, 0.96);
  color: #0b1020;
}
@keyframes tooltipIn       { from { opacity: 0; transform: translateY(2px);  } to { opacity: 1; transform: translateY(0); } }
@keyframes tooltipInBottom { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: translateY(0); } }
@keyframes tooltipInLeft   { from { opacity: 0; transform: translateX(2px);  } to { opacity: 1; transform: translateX(0); } }
@keyframes tooltipInRight  { from { opacity: 0; transform: translateX(-2px); } to { opacity: 1; transform: translateX(0); } }
.ui-tooltip--bottom { animation-name: tooltipInBottom; }
.ui-tooltip--left   { animation-name: tooltipInLeft;   }
.ui-tooltip--right  { animation-name: tooltipInRight;  }
@media (prefers-reduced-motion: reduce) {
  .ui-tooltip { animation: none; }
}
/* ════════════════════════════════════════════════════════════════════
   U-2 PRIMITIVE SUPPLEMENT — EmptyState
   ════════════════════════════════════════════════════════════════════
   Tone + size variants for app/src/ui/empty-state.jsx. The base
   .empty-state.v2 styles (defined earlier in SPRINT 1) are not
   touched — this block only adds the new combinator classes so any
   existing consumer of .empty-state.v2 keeps rendering identically.
*/
.empty-state.v2.tone-danger  .empty-state-icon { background: var(--danger-soft);  color: var(--danger);  }
.empty-state.v2.tone-success .empty-state-icon { background: var(--success-soft); color: var(--success); }
.empty-state.v2.tone-warning .empty-state-icon { background: var(--warning-soft); color: var(--warning); }
.empty-state.v2.tone-info    .empty-state-icon { background: var(--info-soft);    color: var(--info);    }
.empty-state.v2.is-lg {
  padding: 56px 28px;
  gap: 16px;
}
.empty-state.v2.is-lg .empty-state-icon {
  width: 80px;
  height: 80px;
  border-radius: 22px;
}
.empty-state.v2.is-lg .empty-state-title { font-size: var(--text-lg); }
.empty-state.v2.is-lg .empty-state-text  { font-size: var(--text-md); max-width: 420px; line-height: var(--leading-relaxed); }
/* ════════════════════════════════════════════════════════════════════
   U-2 PRIMITIVE SUPPLEMENT — MetricTile
   ════════════════════════════════════════════════════════════════════
   Adds the .is-readonly modifier for non-interactive tiles rendered
   by app/src/ui/metric-tile.jsx. Base .metric-tile styles (SPRINT 1,
   line ~7050) remain canonical — this rule just removes the pointer
   cursor when the JSX wrapper isn't given an onClick handler.
*/
.metric-tile.is-readonly {
  cursor: default;
}
/* V-Appointments owner polish: subtle hover for readonly tiles. The
   original rule killed all hover effects on is-readonly to prevent
   misreading a non-clickable tile as a button. But that left
   Reception's 5 KPI tiles feeling dead next to the dashboard cards
   (which hover). Keep the shape of the interactive hover but soften
   it — half the lift, lighter shadow,
   muted border tint — so the tile reads as "alive, info display"
   rather than "alive, click me". The cursor stays default (no
   pointer affordance), so the visual cue maps to "this is data, not
   an action." */
.metric-tile.is-readonly:hover {
  transform: translateY(var(--lift-1));
  box-shadow: 0 4px 12px color-mix(in srgb, var(--tile-color, var(--accent)) 6%, transparent);
  border-color: color-mix(in srgb, var(--tile-color, var(--accent)) 20%, var(--border));
}
.metric-tile[role="button"]:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow);
}
/* ════════════════════════════════════════════════════════════════════
   U-2 PRIMITIVE SUPPLEMENT — DataTable
   ════════════════════════════════════════════════════════════════════
   Adds the striped / compact / no-sticky modifiers + the empty-wrap
   container for app/src/ui/data-table.jsx. Base .data-table styles
   (defined at line ~1067 and the Phase 4 polish at line ~5109) are
   not touched.
*/
.data-table.is-striped tbody tr:nth-child(even) td {
  background: color-mix(in srgb, var(--bg-subtle) 55%, transparent);
}
.data-table.is-compact thead th { padding: 8px 12px;  font-size: var(--text-xs); }
.data-table.is-compact tbody td { padding: 9px 12px;  font-size: var(--text-sm); }
.data-table.no-sticky thead th { position: static; }
.data-table tbody tr[role="button"]:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--accent);
}
.data-table-empty-wrap {
  display: grid;
  place-items: center;
  min-height: 200px;
  padding: 24px;
}
/* U-4 — DataTable pagination footer
   Rendered by data-table.jsx when pageSize is set AND rows exceed
   it. Sits flush below the <table> inside the host card. */
.data-table-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
}
.data-table-pagination__indicator {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-weight: 600;
  font-feature-settings: 'tnum';
  letter-spacing: 0.01em;
}
/* ════════════════════════════════════════════════════════════════════
   U-6 — Command Palette (Cmd+K / Ctrl+K)
   ════════════════════════════════════════════════════════════════════
   Modal-style overlay: full-screen backdrop, top-aligned glass panel,
   search input + scrollable grouped results + keyboard hints footer.
   Reuses `.modal-backdrop` for the dim/blur layer; the panel itself
   lives on its own `.cmdk-panel` class so it can size + position
   independently from the standard `.modal`.
   ════════════════════════════════════════════════════════════════════ */
.cmdk-backdrop {
  /* Sit above standard modals so Cmd+K can open over a sub-modal.
     Inherits the modal-backdrop blur from styles.css line ~955. */
  z-index: var(--z-modal);
  align-items: flex-start;
  padding-top: clamp(48px, 12vh, 120px);
}
.cmdk-panel {
  width: min(640px, calc(100vw - 32px));
  max-height: min(560px, calc(100vh - 160px));
  display: flex;
  flex-direction: column;
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--glass-shadow);
  overflow: hidden;
  animation: cmdkPanelIn 0.18s cubic-bezier(0.34, 1.32, 0.64, 1);
}
@keyframes cmdkPanelIn {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}
/* ── Input row ─────────────────────────────────────────────────────── */
.cmdk-input-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.cmdk-input-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
  flex-shrink: 0;
}
.cmdk-input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  font-size: var(--text-md);
  color: var(--text-primary);
  padding: 4px 0;
}
.cmdk-input::placeholder { color: var(--text-tertiary); }
.cmdk-input-kbd {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: var(--text-xs);
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-tertiary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 6px;
  flex-shrink: 0;
}
/* ── Results list ──────────────────────────────────────────────────── */
.cmdk-results {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px;
  scrollbar-width: thin;
}
.cmdk-group + .cmdk-group { margin-top: 4px; }
.cmdk-group-title {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px 4px;
  font-size: var(--text-xs);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-tertiary);
}
.cmdk-group-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
}
.cmdk-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 12px;
  background: transparent;
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  color: var(--text-primary);
  text-align: start;
  font: inherit;
  transition: background var(--duration-fast) var(--ease-smooth);
}
.cmdk-item.is-active {
  background: var(--accent-soft);
  color: var(--accent);
}
.cmdk-item.is-active .cmdk-item-sub { color: var(--accent); opacity: 0.78; }
.cmdk-item.is-active .cmdk-item-icon { color: var(--accent); }
.cmdk-item-icon {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-subtle);
  border-radius: 8px;
  color: var(--text-secondary);
}
.cmdk-item.is-active .cmdk-item-icon {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.cmdk-item-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cmdk-item-label {
  font-size: var(--text-md);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmdk-item-sub {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmdk-item-kbd {
  display: inline-flex;
  align-items: center;
  padding: 2px 6px;
  font-size: var(--text-xs);
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-tertiary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 6px;
  flex-shrink: 0;
}
.cmdk-item.is-active .cmdk-item-kbd {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border-color: color-mix(in srgb, var(--accent) 24%, var(--border));
}
/* ── Empty state ───────────────────────────────────────────────────── */
.cmdk-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 36px 16px;
  text-align: center;
}
.cmdk-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--bg-subtle);
  border-radius: 50%;
  color: var(--text-tertiary);
  margin-bottom: 4px;
}
.cmdk-empty-text {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-secondary);
}
.cmdk-empty-sub {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
/* ── Footer (keyboard hints) ───────────────────────────────────────── */
.cmdk-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  padding: 8px 16px;
  border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg-subtle) 60%, transparent);
  flex-shrink: 0;
}
.cmdk-footer-group {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.cmdk-footer-label {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.cmdk-footer kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  padding: 1px 5px;
  font-size: var(--text-xs);
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-tertiary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 4px;
}
/* Reduced motion: skip the entrance animation */
@media (prefers-reduced-motion: reduce) {
  .cmdk-panel { animation: none; }
}
/* ── Topbar launcher button (U-6/3) ────────────────────────────────
   Small pill-style button sitting at the start of .topbar-actions,
   showing a search icon + "بحث سريع" label + kbd hint (⌘K on Mac,
   Ctrl K elsewhere). Clicking it dispatches the imperative opener
   exposed by CommandPaletteHost. Provides the discoverability
   affordance — most users won't know about the global shortcut
   without a visible hint.
   ──────────────────────────────────────────────────────────────── */
.cmdk-launch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 10px 0 8px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-tertiary);
  font: inherit;
  font-size: var(--text-xs);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-smooth), border-color var(--duration-fast) var(--ease-smooth), color var(--duration-fast) var(--ease-smooth);
  flex-shrink: 0;
}
.cmdk-launch:hover {
  background: var(--bg-elevated);
  border-color: var(--accent);
  color: var(--accent);
}
.cmdk-launch:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.cmdk-launch-label {
  white-space: nowrap;
}
.cmdk-launch kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-size: var(--text-xs);
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-tertiary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 6px;
  flex-shrink: 0;
}
.cmdk-launch:hover kbd,
.cmdk-launch:focus-visible kbd {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
}
/* Hide the label on narrow viewports — keep just the icon + kbd */
@media (max-width: 900px) {
  .cmdk-launch-label { display: none; }
  .cmdk-launch { gap: 6px; }
}
@media (max-width: 640px) {
  .cmdk-launch kbd { display: none; }
}
/* ───────────────────────────────────────────────────────────────────
   Breadcrumbs (U-7/1)
   Sticky navigation strip rendered between Topbar and main-content
   by Router.jsx (only on authenticated screens via ScreenRouter).
   Layout: <nav class="breadcrumbs"><ol class="breadcrumbs-list">
     <li class="breadcrumbs-item">
       [<span class="breadcrumbs-sep">›</span>]
       <button class="breadcrumbs-link">...</button>
         or <span class="breadcrumbs-current is-section|is-current">
     </li> ...
   </ol></nav>
   Tokens: --glass-bg / --glass-blur / --glass-border (U-1) for the
   sticky surface; --text-tertiary / --text-primary / --accent for
   the typography hierarchy (section + parent crumbs muted, current
   crumb bold and primary).
   ──────────────────────────────────────────────────────────────── */
.breadcrumbs {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky, 50);
  background: var(--glass-bg, var(--bg-elevated));
  -webkit-backdrop-filter: blur(var(--glass-blur, 8px));
  backdrop-filter: blur(var(--glass-blur, 8px));
  border-bottom: 1px solid var(--glass-border, var(--border));
  padding: 8px 24px;
  font-size: var(--text-xs, 12px);
  line-height: 1.4;
  flex-shrink: 0;
}
.breadcrumbs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.breadcrumbs-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.breadcrumbs-sep {
  color: var(--text-tertiary);
  opacity: 0.6;
  font-weight: 700;
  user-select: none;
  /* In RTL the chevron points the right direction visually as-is — › */
}
.breadcrumbs-link {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 2px 6px;
  border-radius: 8px;
  font: inherit;
  font-size: inherit;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-smooth), background var(--duration-fast) var(--ease-smooth);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.breadcrumbs-link:hover {
  color: var(--accent);
  background: var(--accent-soft, var(--bg-subtle));
}
.breadcrumbs-link:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow-soft);
  color: var(--accent);
}
.breadcrumbs-current {
  padding: 2px 4px;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.breadcrumbs-current.is-section {
  color: var(--text-tertiary);
  font-weight: 600;
}
.breadcrumbs-current.is-current {
  color: var(--text-primary);
  font-weight: 800;
}
@media (max-width: 1024px) {
  .breadcrumbs { padding: 7px 16px; }
}
@media (max-width: 768px) {
  .breadcrumbs {
    padding: 6px 12px;
    font-size: var(--text-2xs, 11px);
  }
  .breadcrumbs-link,
  .breadcrumbs-current { max-width: 160px; }
}
@media (max-width: 480px) {
  /* On the smallest screens only show the current crumb so the row
     doesn't wrap to two lines and steal vertical space. */
  .breadcrumbs-item:not(:last-child) { display: none; }
  .breadcrumbs-sep { display: none; }
}
/* ───────────────────────────────────────────────────────────────────
   Mobile bottom-sheet navigation (U-7/2)
   Hamburger button lives in the Topbar; tapping it calls the
   window.openMobileNav() opener exposed by app/shell/mobile-nav.jsx,
   which portals a backdrop + sheet hosting the existing <Sidebar />.
   The desktop sidebar is hidden at ≤768px by the @media block above —
   this section only adds the new mobile surfaces.
   ──────────────────────────────────────────────────────────────── */
.topbar-hamburger {
  display: none; /* desktop default — only the @media block reveals it */
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elevated);
  color: var(--text-primary);
  cursor: pointer;
  font: inherit;
  transition: background var(--duration-fast) var(--ease-smooth), border-color var(--duration-fast) var(--ease-smooth);
}
.topbar-hamburger:hover {
  background: var(--bg-hover);
  border-color: var(--accent);
}
.topbar-hamburger:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow-soft);
  border-color: var(--accent);
}
/* V-Mobile/BackStack (MOBILE_ARCHITECTURE §8.1) — back-arrow button in
   the topbar. Hidden on desktop (breadcrumbs cover that); the @media
   block below at the mobile breakpoint reveals it. In RTL, the
   ChevronRight icon visually points toward the previous screen
   (since "right" in RTL is the direction of reading flow's start). */
.topbar-back {
  display: none; /* desktop default — only the @media block reveals it */
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elevated);
  color: var(--text-primary);
  cursor: pointer;
  font: inherit;
  transition: background var(--duration-fast) var(--ease-smooth), border-color var(--duration-fast) var(--ease-smooth);
}
.topbar-back:hover {
  background: var(--bg-hover);
  border-color: var(--accent);
}
.topbar-back:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow-soft);
  border-color: var(--accent);
}
@media (max-width: 47.99em) {
  .topbar > .topbar-back { display: inline-flex; }
}
.topbar-hamburger-bars {
  position: relative;
  display: block;
  width: 18px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}
.topbar-hamburger-bars::before,
.topbar-hamburger-bars::after {
  content: '';
  position: absolute;
  left: 0;
  width: 18px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}
.topbar-hamburger-bars::before { top: -6px; }
.topbar-hamburger-bars::after  { top:  6px; }
.mobile-nav-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: var(--z-modal-backdrop, 1000);
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  align-items: flex-end;
  justify-content: stretch;
  animation: mobileNavBackdropFade 220ms ease-out;
}
.mobile-nav-backdrop.is-exiting {
  animation: mobileNavBackdropFadeOut 200ms ease-out forwards;
}
[data-theme="luxe"] .mobile-nav-backdrop,
[data-theme="midnight"] .mobile-nav-backdrop {
  background: rgba(0, 0, 0, 0.6);
}
.mobile-nav-sheet {
  width: 100%;
  max-height: 92dvh;
  min-height: 320px;
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  color: var(--text-primary);
  border: 1px solid var(--glass-border);
  border-bottom: 0;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: var(--glass-shadow);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: mobileNavSheetSlideUp 320ms cubic-bezier(0.34, 1.32, 0.64, 1);
}
.mobile-nav-backdrop.is-exiting .mobile-nav-sheet {
  animation: mobileNavSheetSlideDown 200ms ease-in forwards;
}
.mobile-nav-chrome {
  position: relative;
  flex-shrink: 0;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
  background: color-mix(in srgb, var(--bg-subtle) 55%, transparent);
}
.mobile-nav-handle {
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--text-tertiary) 38%, transparent);
}
.mobile-nav-close {
  position: absolute;
  inset-inline-end: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: color-mix(in srgb, var(--bg-elevated) 78%, transparent);
  color: var(--text-secondary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-smooth),
    color var(--duration-fast) var(--ease-smooth),
    transform var(--duration-fast) var(--ease-smooth);
}
.mobile-nav-close:hover {
  background: var(--bg-subtle);
  color: var(--text-primary);
}
.mobile-nav-close:active {
  transform: translateY(-50%) scale(0.96);
}
.mobile-nav-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: env(safe-area-inset-bottom, 0);
}
/* Sidebar rendered inside the sheet: full width, no rail border,
   no overflow clipping — the .mobile-nav-body handles scrolling. */
.mobile-nav-sheet .sidebar {
  width: 100%;
  height: auto;
  border: 0;
  background: transparent;
  overflow: visible;
  flex-shrink: 0;
}
/* V-Phase2 Wave 2 hotfix: the desktop .logo-wrap caps height at 88px
   with overflow:hidden plus the 2px upward translate calibrated for
   the desktop rail gutter, but the size=lg logo (220px wide) has a
   natural height greater than 88px so the top of the wordmark (the
   "M" spire and the "i" dot) gets clipped inside the mobile
   bottom-sheet where there's plenty of vertical room. Reset the cap
   plus the transform here, let the image render at its natural
   aspect ratio, and center it horizontally so it reads as a brand
   header for the sheet. */
.mobile-nav-sheet .sidebar .sidebar-logo {
  justify-content: center;
  padding: 12px 16px 14px;
}
.mobile-nav-sheet .sidebar .logo-wrap {
  height: auto;
  overflow: visible;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.mobile-nav-sheet .sidebar .logo-wrap .modirify-logo {
  transform: none;
  margin: 0 auto;
}
/* ============================================================
   V-Phase2 Wave 3a — Date range popover mobile (ADR-132)
   ============================================================
   Owner audit on phone reported the date-range filter popover
   extending past the trailing edge of the viewport, clipping
   the preset chips ("الشهر السابق" => "...بر السابق", "السنة
   الحالية" => "...نة الحالية") and the "مسح الفترة" action.
   Root cause: the popover anchors to `left: 0` of its
   .date-range-trigger wrapper, which inside the .l-cluster
   controls row can sit anywhere horizontally on a phone after
   wrap. Once the trigger sits in the right half of the row,
   the popover (311px wide on 375px viewport) extends past
   the inline-end edge.

   Fix: at <=480px, promote the popover to a fixed-position
   bottom-sheet anchored to the viewport edges with 12px gutter.
   The popover already has all its internal layout (presets +
   date inputs + actions); only the outer position needs
   reframing for mobile. */
@media (max-width: 480px) {
  .date-range-trigger > .date-range-popover {
    position: fixed !important;
    top: auto !important;
    bottom: 16px !important;
    left: 12px !important;
    right: 12px !important;
    width: auto !important;
    max-width: none !important;
    max-height: calc(100dvh - 32px);
    overflow-y: auto;
    z-index: 200;
    box-shadow: 0 -8px 32px rgba(15, 23, 42, 0.18);
  }
  /* Make the inner preset grid 2-col on phones — 3-col at 311px
     is too cramped for the longer labels like "السنة السابقة". */
  .date-range-trigger > .date-range-popover > div:nth-of-type(2) {
    grid-template-columns: 1fr 1fr !important;
  }
}
/* ADR-141 (2026-05-29): on desktop LTR the dashboard date filters sit at
   the right edge of the header, so the popover's inline `left:0` anchor
   overflows the viewport (owner caught it clipping in English). Right-
   anchor it in LTR so it opens inward. RTL (primary) keeps the inline
   left:0; the mobile bottom-sheet rule above still wins under 480px. */
@media (min-width: 481px) {
  [dir="ltr"] .date-range-trigger > .date-range-popover {
    left: auto !important;
    right: 0 !important;
  }
}
/* ============================================================
   V-Phase2 Wave 3b — Patient File mobile polish (ADR-132)
   ============================================================
   Owner audit reported on the patient-file screen:
     - 9 inner tabs with no visible scroll affordance
     - The PatientHeader's 7 actions (4 icons + 3 text buttons +
       1 primary CTA) stack one-per-row on phones, eating ~150px
       of chrome
     - الفواتير + الجلسات render their DataTables as raw tables,
       so 7-8 columns get squeezed to ~50px each on a 375px
       viewport and the actions column is clipped
   Wave 3b fixes:
     A. PatientHeader actions compressed for phones
     B. .pf-tab-strip edge gradient hint that scroll is possible
     C. mobileCard enabled on Invoices + Sessions (JSX-side)
*/
@media (max-width: 480px) {
  /* A — PatientHeader actions: pack icons into a tight row, drop
     the "السجل الطبى" + "اشرح للمريض" labels to icon-only so the
     primary "حجز موعد جديد" CTA gets its own full-width row at
     the end. flex-wrap stays on so the icons stay readable when
     the row gets narrow.

     Text-hiding strategy: font-size: 0 on the button collapses
     the bare text-node children (the labels are written as direct
     text nodes after the SVG, not wrapped in spans). The lucide
     SVG icons set width + height via attributes (the size prop),
     so font-size: 0 doesn't shrink the glyph — it stays at 16px.
     title + aria-label on each button keep the long form available
     for screen readers and hover tooltips. */
  /* width: auto overrides the existing
     `.dash-hero-actions .btn { width: 100%; }` at the same media
     query (line ~10597). Without this the icon-only-on-mobile
     buttons would still stretch to the full row width. */
  .pf-hero-actions .btn:not(.primary) {
    flex: 0 0 auto;
    width: auto;
    padding: 8px 10px;
    min-height: 38px;
    gap: 0;
  }
  .pf-hero-actions .btn.outline:not(.icon):not(.primary) {
    font-size: 0;
  }
  /* The primary CTA "حجز موعد جديد" takes the whole row so it
     reads as the dominant action. */
  .pf-hero-actions .btn.primary {
    flex: 1 1 100%;
    order: 99;
    margin-top: 4px;
  }

  /* B — Patient File tab strip edge gradient hint. The 9 tabs
     overflow to horizontal scroll on phones; without a visual
     fade at the trailing edge users don't realize they can swipe.
     The gradient + an inline 12px scroll-padding-inline reveal
     hidden tabs slightly so the affordance is obvious. */
  .pf-tab-strip {
    position: relative;
    padding: 6px 0;
  }
  .pf-tab-strip::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    inset-inline-start: 0;
    width: 32px;
    background: linear-gradient(to var(--phase2-fade-dir, left),
      color-mix(in srgb, var(--bg-elevated) 96%, transparent), transparent);
    pointer-events: none;
    z-index: 1;
  }
  [dir="rtl"] .pf-tab-strip {
    --phase2-fade-dir: right;
  }
  .pf-tab-strip .tabs {
    scroll-padding-inline-end: 24px;
    padding-inline-end: 24px;
  }
}
/* ============================================================
   V-Phase2 Wave 3c — WhatsApp Reminders mobile (ADR-132)
   ============================================================
   Owner audit on the WhatsApp Reminders screen reported three
   sub-tabs broken at phone widths:

   1. نظرة عامة: a desktop 1.5fr:1fr grid (Activity feed + Quick
      actions) crammed into 375px — each column collapsed to
      ~150px and patient names wrapped to 4 lines per row.

   2. إرسال يدوى: a desktop 220px+1fr+400px grid (source sidebar +
      recipient list + template editor/preview) all crammed into
      375px. Each column ~120px, the preview bubble wrapped to
      8+ lines per message.

   3. الواردة: 2-col grid (conversations list 320px + chat 1fr)
      stacked vertically below 900px via Wave 5c — both panels
      were visible at the same time, eating ~400px before the
      chat started. Native messaging apps use master-detail:
      tap a conversation, list hides, chat goes full-screen,
      "←" back arrow brings the list back.

   Fixes:
     1. .wa-overview-grid stacks vertically at <=768px
     2. .wa-manual-grid stacks vertically at <=768px with a
        gap that doubles as a wizard-step affordance
     3. .wa-inbox-grid--has-selected hides the list + shows the
        thread full-width on <=768px; the new .wa-thread-back
        button (rendered only when a thread is selected) clears
        the selection and brings the list back. Visibility of
        the back button itself is mobile-only via display rule.
*/
/* Desktop base — both grids use their original column templates */
.wa-overview-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 16px;
}
.wa-manual-grid {
  display: grid;
  grid-template-columns: 220px 1fr 400px;
  gap: 16px;
  align-items: start;
}
/* The back-button is rendered inside every selected-thread header.
   On desktop the master-detail dance isn't needed (both panels are
   side-by-side) so we hide the button by default and reveal it at
   <=768px in the media block below. */
.wa-thread-back {
  display: none;
  flex-shrink: 0;
}
@media (max-width: 768px) {
  /* 1 — Overview activity + quick actions stack vertically */
  .wa-overview-grid {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  /* 2 — Manual send: three sections stack as a wizard. Slightly
     larger gap so the visual rhythm of step-by-step is clear. */
  .wa-manual-grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }

  /* 3 — Inbox master-detail. When a thread is selected the list
     collapses + the chat goes full-width. When nothing is
     selected the chat panel doesn't render (the JSX already
     skips it when !selectedThread), so the list takes the
     whole screen by default — no extra rule needed. */
  .wa-inbox-grid--has-selected .wa-inbox-list {
    display: none;
  }
  .wa-inbox-grid--has-selected .wa-inbox-thread {
    height: calc(100dvh - 220px);
    min-height: 420px;
  }
  /* Reveal the back button on phones. Sits at the leading edge of
     the thread header so the chevron points naturally towards the
     list it returns to. */
  .wa-inbox-grid--has-selected .wa-thread-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    min-height: 38px;
    padding: 0;
    font-size: 18px;
    font-weight: 700;
  }
}
/* ============================================================
   V-Phase2 Wave 3b-extras — Dental chart + X-ray lightbox mobile
   ============================================================
   Owner audit on the Patient File flagged two remaining mobile
   issues that didn't fit in Wave 3b:

   1. Dental chart at 375px:
      - The outer 1fr+320px split forced the chart pane into ~23px
        of content width while the side detail panel ate 320px.
      - Tooth row at repeat(16, 1fr) gave ~21px per tooth — well
        below the 44px touch-target floor; doctors mis-tapped
        adjacent teeth constantly.
      Fix: at <=768px, collapse the shell to a single column so
      the chart gets the full width; switch the tooth row to a
      flex layout with min-content per tooth (36px) + horizontal
      scroll. The doctor swipes the row to reach distant teeth
      rather than hunting tiny targets.

   2. ImageLightbox at 375px:
      - Fixed 600x450 frame overflowed the viewport.
      - No native zoom on the x-ray image (touch-action default).
      Fix: at <=768px, stretch the frame to calc(100vw - 24px)
      x calc(100vh - 180px) so the chrome stays accessible. Add
      touch-action: pinch-zoom on the <img> (JSX-side) so doctors
      can natively zoom into x-ray details.
*/
@media (max-width: 768px) {
  /* 1a — Stack the chart + detail panel vertically so the chart
     gets the full content width. The detail panel (selected
     tooth info + state assignment) drops below. */
  .dc-shell {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }
  /* 1b — Tooth row: min-content flex with horizontal scroll.
     Each tooth gets 36px min-width which keeps the SVG legible
     and the touch target safe; gap shrinks slightly to fit a
     few more teeth on-screen per scroll position. !important
     needed because the inline grid-template-columns sets the
     equal-fraction layout at the same specificity level. */
  .dc-tooth-row {
    display: flex !important;
    grid-template-columns: none !important;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 8px;
    gap: 4px !important;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }
  .dc-tooth-row > * {
    flex: 0 0 36px;
    min-width: 36px;
    scroll-snap-align: center;
  }
  /* Surround the tooth rows in their parent .dc-chart-surface so
     the upper-jaw + lower-jaw labels still center over the
     scrollable strips and a subtle scroll affordance hints that
     the row continues beyond the viewport. */
  .dc-chart-surface {
    position: relative;
  }

  /* 2 — Lightbox: stretch to viewport. Keep small margins on
     each side so the close button stays in a reachable corner
     and a sliver of backdrop is visible (helps users dismiss
     by tapping outside). */
  .image-lightbox-frame {
    width: calc(100vw - 24px) !important;
    height: calc(100dvh - 180px) !important;
    max-height: calc(100dvh - 180px);
  }
}
/* ADR-170 Fix #5 (2026-06-05): tighter floor for phone-class viewports.
   The Wave 3b-extras 36px tooth size at <=768px keeps 16 teeth visible
   on a 7-inch tablet, but at <=600px (phones + 6-inch tablets) doctors
   were still mis-tapping. Per WCAG 2.1 the touch-target floor is 44px;
   this block raises every tooth to that floor at small viewports and
   widens the gap slightly so adjacent teeth never share an edge. The
   horizontal scroll the parent block already enables continues to let
   the doctor reach distant teeth. */
@media (max-width: 600px) {
  .dc-tooth-row > * {
    flex: 0 0 44px;
    min-width: 44px;
    min-height: 44px;
  }
  .dc-tooth-row { gap: 6px !important; }
}
/* ─────────────────────────────────────────────────────────────────────
   V-Phase2 Wave 4 (ADR-133) — TopBar + Billing mobile polish
   ─────────────────────────────────────────────────────────────────────
   Wave 4 closes three live overflow bugs the owner reported on
   2026-05-27:

   1. TopBar title clipped behind the search icon.
      Cause: `.cmdk-launch` was the first child of `.topbar-actions`
      (visually right-most in RTL, directly adjacent to the title
      block). The icon plus the chevron-shaped focus ring left the
      title (`ملف المريض`, `الفواتير والمدفوعات`, etc.) with no room
      to render its tail letters, so it always wrapped or clipped
      to a 2-letter stub.
      Fix: push `.cmdk-launch` to `order: 99` so it visually swaps
      to the LEFT end of `.topbar-actions` (where the avatar used
      to sit). Hide the avatar + its preceding divider on mobile —
      the user/clinic identity is already surfaced in the mobile
      nav sheet that the hamburger opens, so the topbar real estate
      is reclaimed entirely for navigation + key actions.

   2. DentalChart still overflowed at ≤768px after Wave 3b-extras.
      Cause: the previous `grid-template-columns: 1fr !important`
      didn't actually stop the track from expanding — `1fr` in CSS
      Grid resolves to `max(min-content, available-space)`, and the
      tooth row's intrinsic min-content (16 teeth × 36px + gaps =
      ~636px) bled UP through the chart card and forced the 1fr
      track to expand to 700px+, overflowing the 375px viewport.
      Fix: use `minmax(0, 1fr)` which clamps the track's minimum
      to 0, AND add `min-width: 0` + `overflow: hidden` to the two
      child cards so their internal layouts stop dictating the
      outer track size. Equivalent change applied to the New /
      Edit Invoice modal 2fr+1fr grids for the same reason — their
      5-column items tables were similarly bleeding intrinsic width
      into the outer grid.

   3. Billing KPI tiles felt oversized on phones.
      Cause: V-Mobile/KpiTypo's clamp (22→36px) does scale by
      viewport, but at 375px it still resolves to 22-24px which
      reads larger than the surrounding density. Padding + icon
      sizes were also still at desktop scale.
      Fix: tighten value to 20px, label to 10px, icon to 28px,
      padding to 12px on phones. Matches the tile chrome density
      already used on the inventory hub. */
@media (max-width: 768px) {
  /* W4-A — TopBar: hide avatar + divider, push search to LEFT end. */
  .topbar-actions > .topbar-divider,
  .topbar-actions > .avatar.sm {
    display: none !important;
  }
  .topbar-actions > .cmdk-launch {
    order: 99;
  }

  /* W4-B — DentalChart: stop the 1fr column from expanding to fit
     the inner tooth row's min-content. minmax(0, ...) plus the
     child min-width: 0 are needed together — neither alone is
     enough because the inline grid-template-columns ships with
     `1fr 320px` (specificity tie that requires !important on the
     replacement). */
  .dc-shell {
    grid-template-columns: minmax(0, 1fr) !important;
  }
  .dc-chart-card,
  .dc-detail-card {
    min-width: 0;
    overflow: hidden;
  }

  /* W4-C — Billing KPI density: tighter padding + smaller value
     font so the four tiles read as compact metrics rather than
     hero panels. !important on the value font because the fluid
     clamp upstream (V-Mobile/KpiTypo) ships at the same
     specificity (a single class selector) and would otherwise
     win the cascade through source-order. */
  .metric-tile {
    padding: 12px 12px;
    gap: 6px;
  }
  .metric-tile-value {
    font-size: 20px !important;
  }
  .metric-tile-icon {
    width: 28px;
    height: 28px;
    font-size: 14px;
  }
  .metric-tile-label {
    font-size: 10px;
  }
  .metric-tile-hint {
    font-size: 10px;
  }
}
/* V-Phase2 Wave 4b (ADR-134) — Wave 4 D rules removed.
   The invoice modals no longer use a 2fr+1fr layout or 5-column
   items table — they now follow the unified vertical card-stack
   pattern shared by AddSessionModal + LabOrderModal +
   EditPurchaseInvoiceModal, so the @media (max-width: 720px) rules
   for `.new-invoice-2col`, `.new-invoice-items-table`,
   `.edit-invoice-items-table`, and `.ni-page-header--in-modal` are
   no longer needed and have been deleted. The items now wrap
   naturally via flex-wrap with min-widths per field. */
@keyframes mobileNavBackdropFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes mobileNavBackdropFadeOut {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes mobileNavSheetSlideUp {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
@keyframes mobileNavSheetSlideDown {
  from { transform: translateY(0); }
  to   { transform: translateY(28px); opacity: 0; }
}
@media (max-width: 768px) {
  /* Reveal the hamburger and the bottom-sheet on phone-sized viewports.
     The sheet/backdrop only ever mount when window.openMobileNav() flips
     state in mobile-nav.jsx (returns null otherwise) — the display:flex
     here just unlocks the layout when they DO mount. */
  .topbar-hamburger { display: inline-flex; }
  .mobile-nav-backdrop { display: flex; }
}
/* Respect prefers-reduced-motion — skip the slide-up + fade-in for users
   with vestibular conditions or motion sensitivity. The sheet still
   appears (essential), just without the entrance animation. */
@media (prefers-reduced-motion: reduce) {
  .mobile-nav-backdrop,
  .mobile-nav-sheet {
    animation: none;
  }
}
/* =====================================================================
   V-Inventory (ADR-058) — eighth Wave 2 polish track
   ===================================================================== */
/* ─── .inv-alert — refined low/out stock banner (V-Inventory/4) ─────
   Drops hardcoded #fef2f2/#fffbeb/#dc2626/#d97706 hex in favor of the
   shared danger-soft/warning-soft tokens. The borderInlineStart
   accent stripe mirrors V-Billing/5 aging viz polish so all "you
   need to look at this" banners read with one visual language. */
.inv-alert {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  border-inline-start: 3px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 6%, var(--bg-elevated));
}
.inv-alert.is-warning {
  border-inline-start-color: var(--warning);
  background: color-mix(in srgb, var(--warning) 6%, var(--bg-elevated));
}
.inv-alert-body { display: flex; align-items: center; gap: 10px; }
.inv-alert-icon { font-size: 20px; line-height: 1; }
.inv-alert-title { font-weight: 700; font-size: 13px; color: var(--danger); }
.inv-alert.is-warning .inv-alert-title { color: var(--warning); }
.inv-alert-hint { font-size: 11px; color: var(--text-secondary); margin-top: 2px; }
.inv-alert-actions { display: flex; gap: 8px; }
/* ─── .inv-empty — V-Inventory/5 rich empty-state shell ─────────────
   Sixth rich-empty-state CSS block after .kanban-empty-rich,
   .invoice-empty, .appt-empty, .mk2-col-empty, .fin-empty. Same
   shape: dashed-border card + tone-tinted icon circle + title +
   hint + optional action button. Tone variants share the same
   dimensions so consumers can switch tone via class without
   layout shift. */
.inv-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 36px 24px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  gap: 6px;
}
.inv-empty-icon {
  width: 56px;
  height: 56px;
  border-radius: 999px;
  display: inline-grid;
  place-items: center;
  font-size: 28px;
  background: color-mix(in srgb, var(--text-tertiary) 10%, transparent);
  margin-bottom: 6px;
}
.inv-empty-title { font-weight: 800; font-size: 15px; color: var(--text-primary); }
.inv-empty-hint  { font-size: 12px; color: var(--text-secondary); max-width: 480px; line-height: 1.7; }
.inv-empty-action { margin-top: 12px; }
.inv-empty.is-accent  .inv-empty-icon { background: var(--accent-soft);  }
.inv-empty.is-success .inv-empty-icon { background: var(--success-soft); }
.inv-empty.is-warning .inv-empty-icon { background: var(--warning-soft); }
.inv-empty.is-danger  .inv-empty-icon { background: var(--danger-soft);  }
.inv-empty.is-muted   .inv-empty-icon { background: color-mix(in srgb, var(--text-tertiary) 10%, transparent); }
/* ─── .wf-* — WaterfallChart mobile stacked cards ────────────────────
   ADR-140 W4b (2026-05-28): below 768px the WaterfallChart swaps from
   SVG to a vertical card list because SVG fonts become 4-5 CSS px
   (unreadable). Each row carries icon + label + percent header,
   proportional horizontal fill bar, then value + sublabel footer. */
.wf-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 8px 0 12px;
}
.wf-row {
  background: var(--bg-subtle);
  border-radius: 10px;
  padding: 10px 12px;
  border-inline-start: 4px solid var(--border);
}
.wf-row--total {
  background: color-mix(in srgb, var(--accent-soft) 50%, var(--bg-subtle));
  border-inline-start-width: 5px;
}
.wf-row__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.wf-row__icon { font-size: 14px; flex-shrink: 0; }
.wf-row__label {
  font-size: 13px;
  font-weight: 800;
  color: var(--text-primary);
  flex: 1;
}
.wf-row__pct  { font-size: 11px; font-weight: 700; }
.wf-row__bar  {
  height: 8px;
  background: var(--border);
  border-radius: 99px;
  overflow: hidden;
}
.wf-row__fill {
  height: 100%;
  border-radius: 99px;
  transition: width .3s ease;
}
.wf-row__foot {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  gap: 8px;
}
.wf-row__value { font-size: 13px; font-weight: 900; }
.wf-row__sub   { font-size: 11px; color: var(--text-tertiary); }
/* ─── .btc-* — BusinessTrendChart mobile polish (W4b) ────────────────
   Split mode + frame toggles into 2 separate clusters with nowrap
   labels. Add scroll-hint pulsing chevron + edge fade matching the
   W2.4 pattern used for variance tables. */
.btc-toggles { white-space: nowrap; }
.btc-toggles .btn { white-space: nowrap; }
@media (max-width: 720px) {
  .btc-scroll-wrap { position: relative; }
  .btc-scroll-wrap::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 8px;
    left: 0;
    width: 24px;
    pointer-events: none;
    background: linear-gradient(to right, var(--bg), transparent);
    z-index: 1;
  }
  .btc-scroll-wrap::before {
    content: '◂';
    position: absolute;
    top: 12px;
    left: 6px;
    font-size: 14px;
    color: var(--text-tertiary);
    z-index: 2;
    pointer-events: none;
    animation: varScrollPulse 1.6s ease-in-out infinite;
  }
}
/* ─── .pm-* — ProfitabilityMatrix mobile disclosure (W4b) ────────────
   On phones (≤540px) the matrix is hidden behind a <details>
   disclosure because the 1120x430 viewBox with padX=245 budgets
   44% of width to side labels — useless after scale-down. The
   legend grid below the matrix already gives a clean phone
   experience; the disclosure preserves SVG access for power users. */
.pm-mobile-disclosure summary {
  cursor: pointer;
  padding: 12px 14px;
  background: var(--bg-subtle);
  border-radius: 10px;
  font-weight: 800;
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 12px;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.pm-mobile-disclosure summary::-webkit-details-marker { display: none; }
.pm-mobile-disclosure[open] summary { background: var(--accent-soft); color: var(--accent); }
.pm-mobile-disclosure summary::after {
  content: '▾';
  margin-inline-start: auto;
  transition: transform .2s;
}
.pm-mobile-disclosure[open] summary::after { transform: rotate(180deg); }
/* ─── .spp-* — Service-profit table sticky tfoot + mobile hint (W4b)
   ADR-140 W4b: the 7-col profitability table previously had a tfoot
   that scrolled out of view inside the 440px maxHeight container.
   .spp-table tfoot tr sticks to the bottom so totals stay visible.
   .spp-scroll-wrap provides the mobile scroll-hint pattern matching
   the W2.4 variance / W4b BusinessTrend wrappers — visible only on
   ≤720px so desktop stays pristine. */
.spp-table table tfoot tr {
  position: sticky;
  bottom: 0;
  background: var(--bg-subtle);
  z-index: 1;
}
.spp-table table tfoot td {
  border-top: 2px solid var(--border);
}
@media (max-width: 720px) {
  .spp-scroll-wrap { position: relative; }
  .spp-scroll-wrap::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 8px;
    left: 0;
    width: 24px;
    pointer-events: none;
    background: linear-gradient(to right, var(--bg), transparent);
    z-index: 1;
  }
  .spp-scroll-wrap::before {
    content: '◂';
    position: absolute;
    top: 12px;
    left: 6px;
    font-size: 14px;
    color: var(--text-tertiary);
    z-index: 2;
    pointer-events: none;
    animation: varScrollPulse 1.6s ease-in-out infinite;
  }
}
/* ─── @media print — clean Analytics print output ────────────────────
   ADR-140 W3.3 (2026-05-28): "طباعة" button calls window.print().
   Before this block the printed page included sidebar + topbar +
   tabs + buttons + boot splash, wasting paper and producing
   unreadable charts. This hides chrome, flattens the colour
   palette, and lets cards / tables fit the page width. */
@media print {
  /* hide chrome */
  .sidebar,
  aside.sidebar,
  .topbar,
  .boot-splash,
  .modal-backdrop,
  [role="dialog"],
  .toast,
  .toast-stack,
  nav,
  [role="tablist"] {
    display: none !important;
  }
  /* expand main to full page */
  body, html, #root, main, .app-main {
    background: #fff !important;
    color: #111 !important;
    margin: 0 !important;
    padding: 0 !important;
    min-height: 0 !important;
  }
  main {
    padding: 8px 12px !important;
    margin-inline-start: 0 !important;
  }
  /* flatten card backgrounds for print */
  .card,
  .kpi-tile,
  .metric-tile {
    background: #fff !important;
    box-shadow: none !important;
    border: 1px solid #d4d4d8 !important;
    page-break-inside: avoid;
    break-inside: avoid;
  }
  /* hide action buttons (طباعة + نسخ + الاستيراد + similar) */
  button {
    display: none !important;
  }
  /* keep hero subtitle (date range + summary) — primary value */
  .breadcrumb {
    display: none !important;
  }
  /* tables keep readable */
  table, .data-table {
    page-break-inside: auto;
  }
  tr {
    page-break-inside: avoid;
    break-inside: avoid;
  }
  /* keep currency Black */
  * {
    color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
  /* SVG charts: keep colours but cap size */
  svg {
    max-width: 100% !important;
  }
}
/* ─── .rep-day-row — Analytics daily tab day-summary row ──────────────
   ADR-140 W2.2 (2026-05-28): the previous inline grid
   '1fr repeat(5, auto)' crammed 6 columns into 342px on phones
   (each auto column landed at 20-33px — unreadable, ignored). New
   structure: 2-column grid (label + metrics cluster) at desktop,
   stacks to 1 column at ≤540px so the 5 metrics flow as flex-wrap
   chips below the label. */
.rep-day-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 20px;
}
.rep-day-row__metrics {
  display: grid;
  grid-template-columns: repeat(5, auto);
  gap: 0 20px;
  align-items: center;
}
@media (max-width: 540px) {
  .rep-day-row {
    grid-template-columns: 1fr;
    gap: 6px 0;
  }
  .rep-day-row__metrics {
    grid-template-columns: repeat(5, 1fr);
    gap: 4px;
    width: 100%;
  }
  .rep-day-row__metrics > div {
    font-size: 11px !important;
    padding: 2px 4px;
    background: var(--bg-subtle);
    border-radius: 6px;
    text-align: center !important;
  }
}
/* ─── .var-* family — Variance tab responsive primitives ─────────────
   ADR-140 W4a (2026-05-28): the variance tab on phones had three
   independent layout failures:
   1. Header card 3-col grid wrapped subtitle to 6+ short lines
   2. Wizard 4-step flex row crammed 40px circles + 12px labels into
      ~80px cells with vertical dividers — looked like icon-soup
   3. Form rows (actual/physical/close) had 2/3-col grids that crushed
      the help text and shrunk the save button below thumb-tap width
   This block defines per-section primitives so the JSX uses semantic
   classNames + the responsive behaviour lives in CSS. Breakpoint:
   ≤720px (small tablet + phones). */
.var-header-grid {
  display: grid;
  grid-template-columns: minmax(180px, 240px) 1fr auto;
  gap: 16px;
  align-items: center;
}
@media (max-width: 720px) {
  .var-header-grid {
    grid-template-columns: 1fr;
    gap: 12px;
    text-align: center;
  }
  .var-header-grid > :nth-child(3) {
    border-top: 1px solid var(--border);
    padding-top: 10px;
  }
}
.var-form-row {
  display: grid;
  gap: 14px;
  align-items: end;
}
.var-form-row--with-helper { grid-template-columns: minmax(200px, 260px) 1fr auto; }
.var-form-row--two         { grid-template-columns: 1fr auto; }
.var-form-row.var-form-row--two[class*='ai-c'] { align-items: center; }
@media (max-width: 720px) {
  .var-form-row--with-helper,
  .var-form-row--two {
    grid-template-columns: 1fr;
  }
  .var-form-row--with-helper > :last-child,
  .var-form-row--two > :last-child {
    width: 100%;
  }
}
.var-kpi-row { /* default: inherit .l-grid--fixed-4 behaviour */ }
@media (max-width: 720px) {
  .var-kpi-row .card.kpi { padding: 12px; min-height: auto; }
  .var-kpi-row .card.kpi > div:nth-child(2) { font-size: 22px; }
}
/* Wizard primitive ─── horizontal 4-step strip with vertical dividers
   on desktop. On phones collapses to a 4-col equal grid without
   dividers, circles shrink to 32px, sub-text hides. */
.var-wizard {
  display: flex;
  gap: 0;
  align-items: stretch;
}
.var-wizard-step {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  padding: 10px 8px;
  border-radius: 10px;
  background: transparent;
  transition: background .15s;
  outline: 1.5px solid transparent;
}
.var-wizard-step:hover { background: var(--bg-subtle); }
.var-wizard-step.is-active {
  background: var(--accent-soft);
  outline-color: var(--accent);
}
.var-wizard-step__num {
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 1px;
  margin-bottom: 1px;
}
.var-wizard-step__circle {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}
.var-wizard-step__label {
  font-size: 12px;
  font-weight: 600;
  text-align: center;
  margin-top: 2px;
}
.var-wizard-step.is-active .var-wizard-step__label { font-weight: 800; }
.var-wizard-step__sub {
  font-size: 10px;
  color: var(--text-tertiary);
  text-align: center;
}
.var-wizard-divider {
  width: 2px;
  background: var(--border);
  align-self: stretch;
  margin: 18px 0;
  border-radius: 2px;
  flex-shrink: 0;
}
@media (max-width: 720px) {
  .var-wizard {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
  }
  .var-wizard-divider { display: none; }
  .var-wizard-step { padding: 8px 2px; }
  .var-wizard-step__circle { width: 32px; height: 32px; font-size: 14px; }
  .var-wizard-step__label  { font-size: 10px; line-height: 1.25; }
  .var-wizard-step__sub    { display: none; }
}
.var-qty-input {
  width: 120px;
  text-align: center;
}
@media (max-width: 720px) {
  .var-qty-input { width: 96px; }
}
.var-close-card {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 20px;
  align-items: center;
}
@media (max-width: 720px) {
  .var-close-card {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .var-close-card > :last-child {
    width: 100%;
    padding: 14px 16px;
  }
}
/* ─── .var-scroll-wrap — Variance tab table wrapper ──────────────────
   ADR-140 W6 (2026-05-28): the W2.4 chevron + gradient hint was
   creating visible artifacts the owner reported as bugs:
   - The ::before chevron pulsed indefinitely even when no more
     scroll was available, looking like a UI glitch
   - The ::after `linear-gradient(to right, var(--bg), transparent)`
     showed as a soft shadow at the left edge of the card that
     persisted at every scroll position
   - At full scroll the table content sat flush against the visible
     edge leaving an "empty white area" where the gradient still rendered
   The keyframe + pseudo-elements are now retired. Horizontal scroll
   remains (per A2 owner choice) but without any visual decoration —
   the native scrollbar at the bottom is the only affordance. */
.var-scroll-wrap {
  position: relative;
}
/* ADR-140 W7 partial (2026-05-28): the global mobile rule on
   `.data-table { display: block; overflow-x: auto; white-space:
   nowrap; }` turns the inner table into a SECOND horizontal
   scroller nested inside .var-scroll-wrap. This override resets
   the variance tables to normal table layout so only the wrapper
   scrolls. Note: the matching JSX fix (remove inline minWidth:
   900/820/860 on the three variance tables) is still pending — until
   that lands the inline min-width keeps the table 900px wide and
   the empty strip can still appear. The CSS override is harmless
   either way. Other .data-table consumers (patients, billing,
   sessions, inventory main) keep the global rule untouched. */
@media (max-width: 720px) {
  .var-scroll-wrap > table.data-table {
    display: table !important;
    overflow-x: visible !important;
    width: auto !important;
  }
}
/* varScrollPulse keyframe kept (still referenced by .btc-scroll-wrap
   and .spp-scroll-wrap in other surfaces). */
@keyframes varScrollPulse {
  0%, 100% { opacity: .35; transform: translateX(0); }
  50%      { opacity: 1;   transform: translateX(-3px); }
}
/* ─── .bom-split — Inventory BOM tab split panel ──────────────────────
   ADR-140 W1.3 (2026-05-28): the original layout was inline-style with
   `display: flex` + `width: 270` sidebar + `flex: 1` detail. On phones
   (375px) the 270px sidebar swallowed 70%+ of the screen, leaving the
   detail panel squeezed to ~85px — "إدارة المكونات" was truncated to
   "إد" and price values were cut off. This block stacks the panel
   vertically below 720px so each part gets the full width. The
   sidebar caps at 240px tall (with internal scroll) to keep the
   detail visible without scrolling past a long service list. */
.bom-split {
  display: flex;
  gap: 0;
  align-items: stretch;
}
.bom-sidebar {
  width: 270px;
  flex-shrink: 0;
}
@media (max-width: 720px) {
  .bom-split {
    flex-direction: column;
  }
  .bom-sidebar {
    width: 100%;
    max-height: 240px;
    border-left: 0 !important;
    border-bottom: 1px solid var(--border);
  }
}
/* ─── .metric-tile.is-active — clicked filter highlight (V-Inventory/3)
   Subtle 1.5px accent outline + soft glow replaces the previous
   bespoke boxShadow override. Stays consistent with the primitive's
   hover discipline. */
.metric-tile.is-active {
  outline: 1.5px solid var(--tile-color);
  outline-offset: -1px;
  box-shadow: 0 6px 16px color-mix(in srgb, var(--tile-color) 14%, transparent);
}
/* ─── .wa-empty — V-WhatsApp/4 (ADR-059) rich empty-state shell ─────
   Seventh rich-empty CSS block after .kanban-empty-rich,
   .invoice-empty, .appt-empty, .mk2-col-empty, .fin-empty,
   .inv-empty. Mirrors .inv-empty exactly so consumers in
   overview-tab + inbox-tab + manual-tab render with identical
   dimensions regardless of host card padding. */
.wa-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 32px 20px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  gap: 6px;
}
.wa-empty-icon {
  width: 56px;
  height: 56px;
  border-radius: 999px;
  display: inline-grid;
  place-items: center;
  font-size: 28px;
  background: color-mix(in srgb, var(--text-tertiary) 10%, transparent);
  margin-bottom: 6px;
}
.wa-empty-title { font-weight: 800; font-size: 15px; color: var(--text-primary); }
.wa-empty-hint  { font-size: 12px; color: var(--text-secondary); max-width: 480px; line-height: 1.7; }
.wa-empty.is-accent  .wa-empty-icon { background: var(--accent-soft);  }
.wa-empty.is-success .wa-empty-icon { background: var(--success-soft); }
.wa-empty.is-warning .wa-empty-icon { background: var(--warning-soft); }
.wa-empty.is-danger  .wa-empty-icon { background: var(--danger-soft);  }
.wa-empty.is-info    .wa-empty-icon { background: var(--info-soft);    }
.wa-empty.is-muted   .wa-empty-icon { background: color-mix(in srgb, var(--text-tertiary) 10%, transparent); }
/* ─── .wa-schedule-bar — V-WhatsApp/3 (ADR-059) info strip ──────────
   Pure informational schedule summary in automation-tab. The compact
   "⚙ الإعدادات والمواعيد" CTA that used to anchor this bar moved
   into the hero's tab-aware actions row, so the bar is now a
   single-line summary without an embedded button. */
.wa-schedule-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 16px;
  margin-bottom: 14px;
  background: var(--bg-subtle);
  border-radius: var(--radius);
  border: 1px solid var(--border);
}
.wa-schedule-reviews {
  color: var(--success);
  font-weight: 700;
  margin-inline-start: 8px;
}
/* ─── Settings shell + sidebar nav polish — V-Settings/4 (ADR-060) ──
   Replaces the inline `gridTemplateColumns: '220px 1fr'` from the
   Settings() return. The nav card stays vertical (the 7-tab depth
   doesn't fit a horizontal Tabs primitive comfortably); active item
   gets a 3px accent borderInlineStart stripe + soft accent bg so
   the current tab is scannable without color noise. */
.settings-shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 20px;
  align-items: start;
}
.settings-nav {
  padding: 10px;
  position: sticky;
  top: 20px;
}
.settings-nav-item {
  position: relative;
  border-inline-start: 3px solid transparent;
  transition: background var(--duration-fast) var(--ease-smooth),
              border-inline-start-color var(--duration-fast) var(--ease-smooth);
}
.settings-nav-item.active {
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-elevated));
  border-inline-start-color: var(--accent);
  font-weight: 800;
}
.settings-nav-item.active .icon-box {
  color: var(--accent);
}
/* Wave 6: mobile-only horizontal Tabs strip for Settings. Default hidden
   on desktop+ where the vertical sidebar reads better; flipped on
   <=768px where the sidebar wastes ~350px of vertical space before the
   content. Sticky at top so the active-tab indicator stays visible
   while scrolling through the form. */
.settings-tabs-mobile {
  display: none;
}
@media (max-width: 768px) {
  .settings-shell { grid-template-columns: 1fr; }
  .settings-nav { display: none; }
  .settings-tabs-mobile {
    display: block;
    margin-bottom: 14px;
    position: sticky;
    top: 0;
    z-index: 60;
    background: var(--bg);
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
  }
}
/* ════════════════════════════════════════════════════════════════════
   V-Interaction amendment #3 (ADR-064) — backdrop-filter prefix
   survival via @supports query.

   ROOT CAUSE (confirmed via owner's Chrome DevTools snapshot on
   modirify.com: `backdrop_filter:'none', webkit_backdrop_filter:undefined`):
   Vite/esbuild's CSS minifier dedupes adjacent vendor-prefix pairs
   (treats `-webkit-backdrop-filter` and `backdrop-filter` as the same
   logical property, keeps only the last). With source order
   `backdrop-filter` first then `-webkit-` second, the bundle ends with
   ONLY `-webkit-backdrop-filter` — which modern Chrome (114+) no longer
   recognizes, so backdrop-filter computes to `none` → no blur.

   FIX: Re-declare every backdrop-filter target inside an `@supports`
   block. esbuild can't merge across @supports boundaries, so the
   unprefixed declaration survives. Modern Chrome (Chrome 76+ supports
   unprefixed) resolves via the @supports rule; iOS Safari < 18 (which
   doesn't recognize unprefixed) skips the @supports block and falls
   back to the `-webkit-backdrop-filter` declaration that survives in
   the primary rules above. Both browser tracks get blur.

   Each declaration mirrors the EFFECTIVE cascade value from the primary
   rules above (e.g. .modal-backdrop's primary rule L962 has
   blur(var(--glass-blur-sm)) but a later override at L5024 wins with
   blur(8px) saturate(140%), so this block uses the override value).
   ════════════════════════════════════════════════════════════════════ */
/* ────────────────────────────────────────────────────────────────────
   V-Interaction amendment #4 — suppress nested .fade-in animation
   when a screen wrapper is rendered INSIDE a .gm-box modal.

   Many screens (NewAppointment, NewInvoice, etc.) wrap their root in
   `<div className="fade-in">` so they get a soft entrance animation
   when used as a standalone route. The same screens are ALSO used
   as modal children (Reception's "موعد جديد" mounts NewAppointment
   inside .gm-box, etc.). In the modal case, the outer .gm-box already
   runs its own modalIn animation (translateY 18px → 0 + scale 0.97 → 1
   over 280ms). Nesting the inner .fade-in's translateY 4px → 0 (250ms)
   compounds the transforms — the child briefly sits 4px lower than its
   parent and finishes 30ms earlier, producing a visible "stretch" / "امتداد"
   glitch the owner reported.

   Fix: drop the inner animation entirely when wrapped in .gm-box. The
   outer modalIn handles entrance opacity + position. Standalone-route
   usage of the same screens is untouched.
   ──────────────────────────────────────────────────────────────────── */
.gm-box .fade-in {
  animation: none;
}
@supports (backdrop-filter: blur(0)) {
  .modal-backdrop                       { backdrop-filter: blur(8px) saturate(140%); }
  .modal-backdrop:has(.confirm-dialog)  { backdrop-filter: blur(8px) saturate(140%); }
  .modal, .modal-box                    { backdrop-filter: blur(var(--glass-blur)); }
  .accounting-modal                     { backdrop-filter: blur(var(--glass-blur)) !important; }
  .gm-bd                                { backdrop-filter: blur(var(--glass-blur-sm)) !important; }
  .gm-box                               { backdrop-filter: blur(var(--glass-blur)) !important; }
  .pf-tab-strip                         { backdrop-filter: blur(8px) saturate(140%); }
  .topbar                               { backdrop-filter: blur(14px) saturate(180%); }
  .cmdk-panel                           { backdrop-filter: blur(var(--glass-blur)); }
  .breadcrumbs                          { backdrop-filter: blur(var(--glass-blur, 8px)); }
}
/* ════════════════════════════════════════════════════════════════════
   V-Mobile (ADR-065) — Wave 3 third track (Phase 5 closer).

   Closes the "mobile coverage only at shell layer (U-7)" finding from
   ADR-047 by filling per-screen + primitive responsive gaps:

   /1 — Primitives at phone widths (≤480px): .dash-hero + .metric-tile
        padding/font-size compression + .dash-hero-actions stretch-to-
        full-width. (.insight-card was retired 2026-06-02.)
   /2 — Rich-empty maps padding compression (≤480px) — 5 maps share the
        recipe: .wa-empty / .fin-empty / .inv-empty / .mk2-col-empty /
        .kanban-empty-rich. ADR-060 §2 formalized .wa-empty as the
        de-facto shell; here we add its first cross-map phone-padding
        ruleset.
   /3 — PatientFile fills the 980→640 gap at 768 + 480. .pf-hero +
        .pf-tab-strip + .pf-canvas + .pf-hero-actions touch targets.
   /4 — WhatsApp adds phone rules below the existing 900 breakpoint
        (.wa-stats + .wa-template-editor already covered at 900):
        .wa-rule-card + .wa-status-card + .wa-schedule-bar.
   /5 — Touch targets WCAG AA (44×44) on phones (≤768px). The existing
        .btn min-height: 40px at L2036 was 4px short; .icon-btn + .tab
        had no explicit phone height. Lifts all interactive primitives
        to WCAG minimum on phones; desktop unchanged.

   Phone-breakpoint convention is 480px (phone) + 768px (compact /
   tablet portrait) per ADR-024 Decision F. NO new breakpoints. Each
   sub-block stacks AFTER existing rules so the cascade resolves on
   our values for matching media.

   Why a single appended block (instead of editing in place near each
   primitive): mirrors V-Interaction's appended @supports block —
   keeps the V-X provenance auditable in one place + avoids cascade
   ordering surprises if a future audit reverts a sub-section.
   ════════════════════════════════════════════════════════════════════ */
/* V-Mobile/1 — Primitive phone polish (≤480px) */
@media (max-width: 480px) {
  .dash-hero {
    padding: 16px 14px;
    border-radius: 14px;
    margin-bottom: 16px;
  }
  .dash-hero-title { font-size: 20px; }
  .dash-hero-greet { font-size: 12px; }
  .dash-hero-sub { font-size: 13px; gap: 8px; }
  .dash-hero-sub .date-pill { padding: 3px 9px; font-size: 11px; }
  .dash-hero-actions { width: 100%; gap: 6px; }
  .dash-hero-actions .btn { flex: 1 1 auto; min-width: 0; }

  .metric-tile { padding: 14px 14px; gap: 8px; }
  .metric-tile-value { font-size: 24px; }
  .metric-tile-icon { width: 32px; height: 32px; font-size: 16px; }
  .metric-tile-label { font-size: 11px; }
}
/* V-Mobile/2 — Rich-empty maps phone padding (≤480px) */
@media (max-width: 480px) {
  .wa-empty,
  .fin-empty,
  .inv-empty,
  .mk2-col-empty,
  .kanban-empty-rich {
    padding: 22px 14px;
    gap: 10px;
  }
  .wa-empty-icon,
  .fin-empty-icon,
  .inv-empty-icon,
  .mk2-col-empty-icon,
  .kanban-empty-rich .kanban-empty-icon {
    width: 44px;
    height: 44px;
    font-size: 20px;
  }
  .wa-empty-title,
  .fin-empty-title,
  .inv-empty-title,
  .mk2-col-empty-title,
  .kanban-empty-rich .kanban-empty-title {
    font-size: 14px;
  }
  .wa-empty-hint,
  .fin-empty-hint,
  .inv-empty-hint,
  .mk2-col-empty-hint,
  .kanban-empty-rich .kanban-empty-hint {
    font-size: 12px;
    max-width: none;
  }
}
/* V-Mobile/3 — PatientFile fills the 980→640 gap at 768 + adds phone refinements */
@media (max-width: 768px) {
  .pf-hero .dash-hero-title { font-size: 20px; }
  .pf-hero-alerts {
    gap: 6px;
    padding-top: 10px;
    margin-top: 12px;
  }
  .pf-hero-alerts__label {
    width: 100%;
    font-size: 11px;
    margin-bottom: 4px;
  }
  .pf-hero-notes { padding: 8px 12px; }
  .pf-hero-notes__body { font-size: 12px; }
  .pf-hero-actions .btn.outline.icon {
    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
  }
  .pf-tab-strip { padding: 4px 6px; }
  .pf-canvas { padding: 10px; }
  .pf-canvas--chart { padding: 6px; }
}
/* V-Mobile/4 — WhatsApp phone polish (fills below the existing 900 rules) */
@media (max-width: 768px) {
  .wa-rule-card {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .wa-status-card { padding: 14px; }
  .wa-schedule-bar { font-size: 12px; padding: 8px 12px; }
}
/* V-Mobile/5 — Touch targets WCAG AA (44×44) on phones */
@media (max-width: 768px) {
  .btn {
    min-height: 44px;
    padding: 10px 14px;
  }
  .btn.icon,
  .icon-btn {
    min-width: 44px;
    min-height: 44px;
  }
  .tabs .tab {
    min-height: 44px;
    padding: 12px 14px;
  }
}
/* ============================================================
   V-Mobile/6 (Phase 1.5 — 2026-05-26) — Comprehensive mobile coverage
   ============================================================
   STATUS (Wave 7 closer 2026-05-27): Phase 1.5 fully shipped. Most
   of the rules below are now SAFETY NETS for legacy code paths that
   haven't been migrated to the V-Responsive primitives yet (or that
   intentionally keep the legacy CSS classes like .data-table). The
   Wave 5/5b/5c/5d/5e/5f/5g/5h/6 runs added explicit class-based
   responsive rules elsewhere in this file that supersede most of the
   broad selectors here. Per-rule supersession notes inline below.

   Original audit found that V-Mobile/1-5 covered the shell +
   primitives but missed screen-level patterns. This block fills the
   gaps:
   /1 — Tables on phones: parent gets horizontal scroll via :has(),
        table itself stays readable with reduced padding/font.
        SUPERSEDED for Wave 2 list screens (they use DataTable +
        mobileCard now). Still active as a safety net for any
        remaining raw .data-table consumers.
   /2 — Grid KPI tiles (.grid.cols-N) collapse one step on tablets
        and fully on phones.
        SUPERSEDED for Wave 4a/4c grids that migrated to
        .l-grid--fixed-N (which has its own breakpoint behavior).
        Still active for any remaining .grid.cols-N consumers.
   /3 — REMOVED in 2026-05-26 (see /3 comment below).
   /4 — Modals/forms: full-width on phones with 0 margin so the
        usable area maximises. .modal already does 100vw-40px on
        desktop; phone shrinks the margin to 0 + corners squared.
        SUPERSEDED for Wave 3 + Wave 5d-5h modals that migrated to
        ResponsiveModal (which is bottom-sheet on phones). Still
        active for the legacy shell Modal primitive (used in 2
        places still — feature comparison + upgrade flow migrated
        in Wave 5g, but ResponsiveModal preserves the CSS class
        names for backward compat with any future raw consumer).
   /5 — Reception kanban: .kanban-full-width 5-column row becomes
        vertically scrolling on tablet (<=980px) and vertically
        stacked on phone (<=480px). EXTENDED by Wave 5b which adds
        a more direct .kanban-board stack rule + sticky col headers.
   /6 — Appointments calendar: tighter cells + smaller text.
        EXTENDED by Wave 5c (.appt-week-grid stack at <=480px) +
        Wave 5c (.mk-cal-grid stack at <=480px).
   /7 — Patient list / Billing list / Lab orders / Inventory:
        See /1 above (same DataTable migration applies).
   /8 — Marketing screen + Settings tabs.
        Wave 6 SUPERSEDED the Settings sub-rule with the new
        .settings-tabs-mobile pattern (horizontal Tabs strip).
        The .settings-tabs selector below now matches nothing
        and is kept only as a placeholder for future use.
   ============================================================ */
/* /1 + /7 — Tables: parent becomes horizontally scrollable.
   Uses :has() which is Chrome 105+ (Win 7 / Chrome 109 = OK). */
@media (max-width: 768px) {
  *:has(> .data-table) {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .data-table {
    min-width: 560px;
    font-size: 13px;
  }
  .data-table thead th,
  .data-table tbody td {
    padding: 10px 10px;
    white-space: nowrap;
  }
}
@media (max-width: 480px) {
  .data-table {
    font-size: 12px;
    min-width: 480px;
  }
  .data-table thead th,
  .data-table tbody td {
    padding: 8px 8px;
  }
}
/* /2 — Grid KPI / card tiles collapse one step. */
@media (max-width: 768px) {
  .grid.cols-3,
  .grid.cols-4 {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px !important;
  }
}
@media (max-width: 480px) {
  .grid.cols-2,
  .grid.cols-3,
  .grid.cols-4 {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
}
/* /3 — REMOVED (2026-05-26).
   Originally used [style*="grid-template-columns: ..."] !important to
   force inline grid templates to collapse on mobile. Removed because:
   (a) too broad — hit unintended elements with similar inline styles.
   (b) anti-pattern — fighting React inline styles with CSS !important
       is symptom-fix; the real fix is to refactor screens to use the
       Layout Primitives (.l-grid / .l-sidebar / .l-switcher — see
       V-Responsive section below). Migration plan in MOBILE_ARCHITECTURE.md.
   Screens that depended on /3 will be migrated one-by-one. Until a
   given screen is migrated, mobile users see the desktop inline grid
   (which IS suboptimal but not broken — the grid wraps via flex-wrap
   or scrolls within its container in most cases). */
/* /4 — Modals: maximise usable area on phones. */
@media (max-width: 480px) {
  .modal,
  .modal-box,
  .modal-lg,
  .modal-xl {
    width: 100vw !important;
    max-width: 100vw !important;
    max-height: 100dvh !important;
    height: 100dvh;
    border-radius: 0 !important;
    margin: 0 !important;
  }
  .modal-header,
  .modal-footer { padding: 14px 16px; }
  .modal-body { padding: 16px; }
  .modal-footer .btn { flex: 1 1 auto; }
}
/* /5 — Reception kanban: 5 columns turn into a horizontally
   scrolling row instead of stacking (preserves the workflow
   visual model). On <480px, falls back to single column. */
@media (max-width: 980px) {
  .kanban-full-width {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
  }
  .kanban-full-width > .kanban-col {
    min-width: 280px;
    scroll-snap-align: start;
  }
}
@media (max-width: 480px) {
  .kanban-full-width { display: flex; flex-direction: column; overflow-x: visible; }
  .kanban-full-width > .kanban-col { min-width: 0; }
}
/* /6 — Appointments calendar: tighter cells + smaller text.
   Day/week/month views all need to shrink. */
@media (max-width: 768px) {
  .calendar-grid .day-cell,
  .calendar-grid > * {
    min-height: 80px;
    padding: 6px 4px;
    font-size: 11px;
  }
  /* Week view: 7 columns is OK, but pills become tiny */
  [style*="repeat(7, 1fr)"] .appt-pill,
  .week-view .appt-pill {
    font-size: 10px;
    padding: 3px 5px;
  }
}
@media (max-width: 480px) {
  /* Day view: rooms grid scrolls horizontally instead of squishing */
  [style*="80px repeat("] {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}
/* /8 — Marketing screen + Settings tabs.
   Wave 7 cleanup: .settings-tabs selector removed because Wave 6
   shipped a different pattern (.settings-tabs-mobile, horizontal
   Tabs strip via the Tabs primitive). No DOM element carries the
   .settings-tabs class anymore. The .sub-tabs scroll rule stays
   because some sub-navigation surfaces still use it. */
@media (max-width: 768px) {
  .sub-tabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    scrollbar-width: thin;
  }
  .sub-tabs > * { flex-shrink: 0; }

  /* Marketing hero stepper: already at 1 col below 560 — fine */
  .mk-stepper { gap: 8px; }
}
/* /9 — Universal: any flex row of action buttons in a hero
   becomes full-width column on phones. Helps reception/billing/
   marketing/patient-file heroes. */
@media (max-width: 480px) {
  .dash-hero-actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .dash-hero-actions .btn {
    width: 100%;
    justify-content: center;
  }
  /* Icon-only buttons stay inline (they're small) */
  .dash-hero-actions .btn.icon,
  .dash-hero-actions .icon-btn {
    width: 44px;
    flex: 0 0 auto;
  }
  /* If a row has BOTH icon and text buttons, wrap into rows */
  .dash-hero-actions:has(.btn.icon) {
    flex-direction: row;
    flex-wrap: wrap;
  }
}
/* /10 — Inputs and selects WCAG-AA height on phones. 16px font
   size to prevent iOS auto-zoom on focus. */
@media (max-width: 768px) {
  .input,
  .textarea,
  .select,
  input[type="text"],
  input[type="number"],
  input[type="tel"],
  input[type="email"],
  input[type="date"],
  input[type="time"],
  textarea,
  select {
    min-height: 44px;
    font-size: 16px;
  }
}
/* ============================================================
   V-Responsive (Phase 1.5 architectural — 2026-05-26)
   ============================================================
   Layout Primitives + Container Queries + Mobile-First Components.
   Inspired by Heydon Pickering's "Every Layout" — algebraic CSS
   patterns that collapse naturally based on container space, NOT
   viewport breakpoints. Screens compose these primitives instead
   of writing per-screen @media rules.

   See MOBILE_ARCHITECTURE.md for the full guide + migration plan.

   §1  Layout Primitives — composable boxes:
        .l-stack    — vertical rhythm with consistent gap
        .l-cluster  — horizontal wrap with consistent gap
        .l-switcher — horizontal → vertical at a threshold
        .l-sidebar  — main + sidebar; sidebar drops below on narrow
        .l-grid     — auto-fit grid with sensible minmax
        .l-center   — max-width container, centered
        .l-cover    — fills viewport, optional centered child
   §2  Container Queries — cards adapt to their OWN width
   §3  Responsive Table card view — see also data-table.jsx
   §4  Responsive Modal — see also responsive-modal.jsx
   ============================================================ */
/* §1.1 Stack — vertical flex with token-scaled gap.
   Use for: any vertical list of children (form fields, card
   contents, page sections). Replaces ad-hoc <div style={{
   display: 'flex', flexDirection: 'column', gap: 12 }}>. */
.l-stack {
  display: flex;
  flex-direction: column;
  gap: var(--l-stack-gap, var(--space-fluid-md));
}
.l-stack--xs { --l-stack-gap: var(--space-fluid-xs); }
.l-stack--sm { --l-stack-gap: var(--space-fluid-sm); }
.l-stack--lg { --l-stack-gap: var(--space-fluid-lg); }
.l-stack--xl { --l-stack-gap: var(--space-fluid-xl); }
/* §1.2 Cluster — horizontal flex with wrap. The defining feature:
   every child is on a separate text-line if it can't fit; never
   horizontal scroll. Use for: button rows, chip groups, breadcrumbs,
   filter pills, hero action buttons. */
.l-cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--l-cluster-gap, var(--space-fluid-sm));
  align-items: center;
}
.l-cluster--center  { justify-content: center; }
.l-cluster--end     { justify-content: flex-end; }
.l-cluster--between { justify-content: space-between; }
.l-cluster--top     { align-items: flex-start; }
/* §1.3 Switcher — flex row that becomes flex column when its
   container is narrower than a threshold. The threshold is set
   via --l-switcher-threshold (default 30rem = 480px). No @media
   query needed — pure CSS algebra via flex-basis calc().
   How it works: when (threshold - 100%) is positive, flex-basis
   is huge → items wrap to single column. When negative, basis is
   0 → items align horizontally and grow to fill.
   Use for: 2-column layouts that should stack on narrow widths. */
.l-switcher {
  display: flex;
  flex-wrap: wrap;
  gap: var(--l-switcher-gap, var(--space-fluid-md));
}
.l-switcher > * {
  flex-grow: 1;
  flex-basis: calc((var(--l-switcher-threshold, 30rem) - 100%) * 999);
}
/* §1.4 Sidebar — main content + sidebar where the sidebar drops
   below the main on narrow containers. Sidebar width = --l-sidebar-width
   (default 20rem = 320px). First child = main content, second =
   sidebar. Add .l-sidebar--reverse to swap. */
.l-sidebar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--l-sidebar-gap, var(--space-fluid-md));
}
.l-sidebar > :first-child {
  flex-grow: 999;
  flex-basis: 0;
  min-width: var(--l-sidebar-content-min, 50%);
}
.l-sidebar > :last-child {
  flex-grow: 1;
  flex-basis: var(--l-sidebar-width, 20rem);
}
.l-sidebar--reverse > :first-child {
  flex-grow: 1;
  flex-basis: var(--l-sidebar-width, 20rem);
  min-width: auto;
}
.l-sidebar--reverse > :last-child {
  flex-grow: 999;
  flex-basis: 0;
  min-width: var(--l-sidebar-content-min, 50%);
}
/* §1.5 Grid — auto-fit responsive grid. Each cell has a minimum
   width set via --l-grid-min (default 14rem). The grid figures out
   how many columns fit and wraps the rest. The min(100%, ...)
   ensures the grid never overflows its container even when the
   minmax-min is larger than the container itself (key gotcha). */
.l-grid {
  display: grid;
  gap: var(--l-grid-gap, var(--space-fluid-md));
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, var(--l-grid-min, 14rem)), 1fr)
  );
}
.l-grid--sm   { --l-grid-min: 10rem; }
.l-grid--md   { --l-grid-min: 14rem; }
.l-grid--lg   { --l-grid-min: 18rem; }
.l-grid--card { --l-grid-min: 16rem; }
/* §1.5b Fixed-count grids for HERO KPI rows. When you have exactly
   N tiles and want them to all fit in a single row at tablet+ widths
   (regardless of available space), use these instead of auto-fit.
   Pattern:
     - phone (< 30em / 480px): 1 column (stacked)
     - phone-landscape + tablet+ (>= 30em): N equal columns
   Solves the iPad-portrait 2+1 problem with auto-fit when the
   sidebar squeezes the main area below 3 * --l-grid-min. */
.l-grid--fixed-2,
.l-grid--fixed-3,
.l-grid--fixed-4 {
  display: grid;
  gap: var(--l-grid-gap, var(--space-fluid-md));
  grid-template-columns: 1fr;
}
@media (min-width: 30em) {
  .l-grid--fixed-2 { grid-template-columns: repeat(2, 1fr); }
  .l-grid--fixed-3 { grid-template-columns: repeat(3, 1fr); }
  .l-grid--fixed-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 48em) {
  .l-grid--fixed-4 { grid-template-columns: repeat(4, 1fr); }
}
/* §1.6 Center — max-width container with auto horizontal margins
   and consistent inline padding. Replaces ad-hoc maxWidth styles. */
.l-center {
  max-width: var(--l-center-max, var(--container-wide));
  margin-inline: auto;
  padding-inline: var(--l-center-pad, var(--space-fluid-md));
  width: 100%;
}
.l-center--prose  { --l-center-max: var(--container-prose); }
.l-center--narrow { --l-center-max: 40rem; }
/* §1.7 Cover — fills viewport height; optional centered child.
   Useful for empty states, splash screens, auth screens. */
.l-cover {
  display: flex;
  flex-direction: column;
  min-height: var(--l-cover-min, 100dvh);
  gap: var(--space-fluid-md);
}
.l-cover > .l-cover__center {
  margin-block: auto;
}
/* §1.8 Tabs — scrollable horizontal strip with optional snap. The
   strip stays a single row on every viewport; if children overflow
   horizontally, the strip becomes touch-scrollable with scroll-snap
   so each tab settles in the viewport. Active tab auto-scrolls into
   view via scroll-margin-inline.
   The DOM shape is:
     <div class="l-tabs">
       <div class="l-tabs__rail">
         <button class="l-tabs__tab is-active">...</button>
         <button class="l-tabs__tab">...</button>
       </div>
     </div>
   The outer .l-tabs creates the overflow container so border + bg
   stay anchored; the inner .l-tabs__rail is the scrollable flex row.
   ────────────────────────────────────────────────────────── */
.l-tabs {
  position: relative;
  border-bottom: 1px solid var(--border);
  /* Inline padding so the active-tab focus ring doesn't get clipped */
  padding-inline: var(--space-fluid-3xs);
  /* Fade-edge masks so the first/last tab don't feel cut off */
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--space-fluid-md),
    #000 calc(100% - var(--space-fluid-md)),
    transparent 100%
  );
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--space-fluid-md),
    #000 calc(100% - var(--space-fluid-md)),
    transparent 100%
  );
}
.l-tabs__rail {
  display: flex;
  gap: var(--space-fluid-2xs);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;  /* Firefox */
  scroll-snap-type: x proximity;
  padding-block: var(--space-fluid-2xs);
}
.l-tabs__rail::-webkit-scrollbar { display: none; }
/* Chrome/Safari */
.l-tabs__tab {
  flex-shrink: 0;
  scroll-snap-align: start;
  scroll-margin-inline: var(--space-fluid-md);
  display: inline-flex;
  align-items: center;
  gap: var(--space-fluid-2xs);
  padding: var(--space-fluid-2xs) var(--space-fluid-sm);
  min-height: 44px;           /* WCAG touch target */
  background: transparent;
  border: none;
  border-radius: var(--radius);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  transition: background 160ms ease, color 160ms ease;
  position: relative;
}
.l-tabs__tab:hover {
  background: var(--bg-subtle);
  color: var(--text-primary);
}
.l-tabs__tab.is-active {
  color: var(--accent);
  font-weight: 800;
}
.l-tabs__tab.is-active::after {
  content: '';
  position: absolute;
  inset-inline-start: var(--space-fluid-2xs);
  inset-inline-end: var(--space-fluid-2xs);
  bottom: calc(var(--space-fluid-2xs) * -1 - 1px);
  height: 2px;
  background: var(--accent);
  border-radius: 2px 2px 0 0;
}
.l-tabs__tab:focus-visible {
  outline: none;
  box-shadow: var(--ring-shadow);
}
/* §2 Container Queries — cards adapt to their OWN width.
   When .l-card-container is applied to a wrapper, children using
   @container queries respond to that wrapper's width, NOT the
   viewport. Lets a card render dense when in a sidebar (narrow)
   but spacious when in the main canvas (wide).
   Browser support: Chrome 105+, Safari 16+, Firefox 110+ — all
   covered by the chrome87 build target with chrome 109+ devices. */
.l-card-container {
  container-type: inline-size;
  container-name: card;
}
@container card (min-width: 30em) {  /* 480px container width */
  .l-card-container .l-card-grid-2 { grid-template-columns: 1fr 1fr; }
}
@container card (min-width: 40em) {  /* 640px container width */
  .l-card-container .l-card-grid-3 { grid-template-columns: 1fr 1fr 1fr; }
}
.l-card-grid-2,
.l-card-grid-3 {
  display: grid;
  grid-template-columns: 1fr;  /* default: 1 column on narrow */
  gap: var(--space-fluid-sm);
}
/* §3 Responsive Table card view — for DataTable's mobile mode.
   The DataTable primitive (app/src/ui/data-table.jsx) renders a
   normal <table> on tablet+ and a stack of cards on phone. The
   <table> gets .data-table-desktop (visible ≥ 768px), the card
   list gets .data-table-cards (visible < 768px). Default: cards
   hidden, table visible. */
.data-table-cards {
  display: none;
}
@media (max-width: 47.99em) {  /* < 768px */
  .data-table-desktop {
    display: none;
  }
  .data-table-cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-fluid-sm);
  }
}
.dt-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-fluid-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-fluid-xs);
  transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease;
}
.dt-card--clickable {
  cursor: pointer;
}
.dt-card--clickable:hover,
.dt-card--clickable:focus-visible {
  transform: translateY(var(--lift-1));
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.18);
  border-color: var(--accent);
  outline: none;
}
.dt-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-fluid-sm);
}
.dt-card-title {
  font-size: var(--text-md);
  font-weight: 800;
  color: var(--text-primary);
  line-height: var(--leading-snug);
}
.dt-card-subtitle {
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  line-height: var(--leading-snug);
}
.dt-card-aside {
  flex-shrink: 0;
}
.dt-card-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-fluid-3xs) var(--space-fluid-sm);
  margin: 0;
  padding-top: var(--space-fluid-2xs);
  border-top: 1px dashed var(--border);
  font-size: var(--text-sm);
}
.dt-card-meta dt {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-weight: 700;
  align-self: center;
}
.dt-card-meta dd {
  margin: 0;
  font-weight: 600;
  color: var(--text-primary);
  align-self: center;
}
/* Wave 2a (V-Patients/4): touch-friendly action footer at the bottom
   of mobile cards. Renders as a row of full-width buttons separated
   by a dashed border. */
.dt-card-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-fluid-xs);
  padding-top: var(--space-fluid-xs);
  border-top: 1px dashed var(--border);
  margin-top: var(--space-fluid-2xs);
}
.dt-card-footer > * {
  flex: 1 1 auto;
  min-height: 40px;  /* WCAG-friendly tap target */
}
/* §4 Responsive Modal — bottom-sheet on phone, centered on tablet+.
   Used by app/src/ui/responsive-modal.jsx. See that file for the JSX. */
.rm-backdrop {
  position: fixed;
  inset: 0;
  /* ADR-139 Wave 1 (2026-05-28): scrim deepened to .55 + blur lifted to
     12px so the modal floats over a softer, more cinematic backdrop —
     matches the Ctrl+K command palette feel. */
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: var(--z-modal-backdrop);
  padding: 0;
  animation: rm-backdrop-in 220ms ease-out;
}
.rm-backdrop.is-exiting {
  animation: rm-backdrop-out 180ms ease-out forwards;
}
@keyframes rm-backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes rm-backdrop-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}
/* ADR-139 Wave 0 (2026-05-28): premium shell is now the default.
   What used to be opt-in `.rm-card--premium` is now baked into the
   base `.rm-card` so every modal automatically reads as "Ctrl+K-style"
   premium: deeper float shadow, larger desktop radius, deeper body
   padding, soft accent input glow, primary CTA hover lift.
   The `.rm-card--premium` modifier class is kept as a no-op alias
   for back-compat with any consumer that still passes it.
   ADR-139 Wave 11 (2026-05-28): card now uses the glass surface
   tokens — same recipe as the Ctrl+K command palette. The
   semi-transparent bg + heavy backdrop-blur turns the modal into a
   true floating glass panel over the dimmed scrim. Subtle border
   highlight mimics the cmdk panel. Text contrast stays AAA because
   the glass tokens are tuned at ~88-92% opacity. */
.rm-card {
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  width: 100%;
  max-height: 95dvh;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: var(--glass-shadow);
  /* ADR-139 Wave 8 (2026-05-28): position context for the drag handle
     so it can sit on top of the card without taking flex slot space. */
  position: relative;
  /* ADR-139 Wave 1 (2026-05-28): entrance curve aligned with the
     Ctrl+K command palette — cubic-bezier(0.34, 1.32, 0.64, 1) is the
     gentle-overshoot spring that makes the modal land softly into
     place. Same curve on mobile bottom-sheet + desktop scale. */
  animation: rm-card-in-mobile 320ms cubic-bezier(0.34, 1.32, 0.64, 1);
}
.rm-backdrop.is-exiting .rm-card {
  animation: rm-card-out-mobile 180ms ease-in forwards;
}
@keyframes rm-card-in-mobile {
  from { transform: translateY(40px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes rm-card-out-mobile {
  from { transform: translateY(0); opacity: 1; }
  to   { transform: translateY(28px); opacity: 0; }
}
@media (min-width: 48em) {  /* 768px+ */
  .rm-backdrop {
    align-items: center;
    padding: var(--space-fluid-lg);
  }
  .rm-card {
    width: min(100%, var(--rm-max-width, 600px));
    max-height: calc(100dvh - 4rem);
    border-radius: var(--radius-modal-premium);
    /* ADR-139 Wave 1: same overshoot curve as the mobile sheet for a
       continuous feel across breakpoints; tightened from 280ms to
       240ms so desktop pops faster (less wait on hover-to-click). */
    animation: rm-card-in-desktop 240ms cubic-bezier(0.34, 1.32, 0.64, 1);
  }
  .rm-backdrop.is-exiting .rm-card {
    animation: rm-card-out-desktop 160ms ease-in forwards;
  }
  @keyframes rm-card-in-desktop {
    from { transform: scale(0.94); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
  }
  @keyframes rm-card-out-desktop {
    from { transform: scale(1); opacity: 1; }
    to   { transform: scale(0.97); opacity: 0; }
  }
}
/* ADR-139 Wave 8 (2026-05-28): drag-handle affordance for the mobile
   bottom-sheet. The pill sits inside the card padding (not on top of
   it) so the header keeps its tap target. Hidden on tablet+ where the
   modal is centered. */
.rm-drag-handle {
  display: block;
  width: 36px;
  height: 4px;
  margin: 8px auto 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--text-tertiary) 38%, transparent);
  flex-shrink: 0;
}
@media (min-width: 48em) {
  .rm-drag-handle { display: none; }
}
.rm-card--sm { --rm-max-width: 420px; }
.rm-card--md { --rm-max-width: 600px; }
.rm-card--lg { --rm-max-width: 800px; }
.rm-card--xl { --rm-max-width: 1100px; }
.rm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--pad-modal-premium-sm) var(--pad-modal-premium);
  /* ADR-139 Wave 11: header tint sits OVER the glass card. Solid
     var(--bg-subtle) would hide the glass — we use a translucent
     wash instead so the blur shows through softly. */
  border-bottom: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
  flex-shrink: 0;
  background: color-mix(in srgb, var(--bg-subtle) 55%, transparent);
}
@media (max-width: 47.99em) {
  .rm-header { padding: 16px 20px; }
}
/* V-Polish 2026-05-27: cluster wraps the optional leading icon with
   the title so they read as a single header element. RTL keeps the
   icon on the right of the text. */
.rm-title-cluster {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1 1 auto;
}
.rm-title-icon {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.rm-title-icon svg {
  width: 20px;
  height: 20px;
}
/* ADR-139 Wave 2 (2026-05-28): text-stack inside the title cluster wraps
   .rm-title + optional .rm-subtitle so the leading icon stays vertically
   centered against both lines as a single header element. */
.rm-title-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.rm-title-text--with-sub .rm-title { line-height: 1.2; }
.rm-title {
  font-size: var(--text-md);
  font-weight: 800;
  color: var(--text-primary);
  line-height: var(--leading-snug);
  /* Allow title text to ellipsis if the modal width gets tight on phones */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* ADR-139 Wave 2: optional secondary line below the title. Smaller,
   muted, single-line with ellipsis so it stays compact on phones. */
.rm-subtitle {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-tertiary);
  line-height: 1.3;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 6px;
}
/* V-Polish: keyboard hints strip — shown above the footer on
   pointer devices. Lives inside the modal card; hidden on touch
   hardware where keyboard shortcuts have no input device. */
.rm-keyboard-hints {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  padding: 6px var(--space-fluid-md);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
}
.rm-keyboard-hints kbd {
  font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace;
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  min-width: 18px;
  text-align: center;
}
.rm-keyboard-hints__sep {
  opacity: 0.45;
  margin: 0 2px;
}
@media (pointer: coarse) {
  /* Touch-primary devices: no keyboard shortcuts on screen. */
  .rm-keyboard-hints { display: none; }
}
/* V-Polish: section divider — wrap a group of related form fields
   with a visible label + thin separator. Tightens the visual scan
   pattern in tall forms (purchase invoice, lab order, expense). */
.modal-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-fluid-xs);
  padding-block-end: var(--space-fluid-sm);
  border-bottom: 1px dashed color-mix(in srgb, var(--border) 70%, transparent);
  margin-block-end: var(--space-fluid-sm);
}
.modal-section:last-child {
  border-bottom: none;
  padding-block-end: 0;
  margin-block-end: 0;
}
.modal-section__title {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: none;
  letter-spacing: 0.01em;
  margin-block-end: 4px;
  /* ADR-139 Wave 8 (2026-05-28): subtle accent dot on the start side
     so each section reads as part of the same visual rhythm as the
     header title-icon circle. The dot is purely decorative; the
     section title remains the primary anchor. */
  display: flex;
  align-items: center;
  gap: 8px;
}
.modal-section__title::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 70%, transparent);
  flex-shrink: 0;
}
.modal-section__hint {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  line-height: var(--leading-normal);
}
.rm-close {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 14px;
  transition: all 160ms ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.rm-close:hover {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
}
.rm-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--pad-modal-premium);
  min-height: 0;
}
@media (max-width: 47.99em) {
  .rm-body { padding: var(--pad-modal-premium-sm); }
}
.rm-footer {
  display: flex;
  gap: 10px;
  padding: var(--pad-modal-premium-sm) var(--pad-modal-premium);
  /* ADR-139 Wave 11: footer also wears a translucent wash over the
     glass card — same recipe as the header for visual symmetry. */
  border-top: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
  flex-shrink: 0;
  background: color-mix(in srgb, var(--bg-subtle) 55%, transparent);
}
.rm-footer .btn { flex: 1 1 auto; }
/* ADR-139 Wave 4 (2026-05-28): structured footer action row.
   When the modal uses primaryAction/secondaryAction/destructiveAction
   props instead of the explicit `footer` ReactNode, we render a flex
   row that lays the destructive button at the start (RTL: right) and
   the secondary+primary pair at the end (RTL: left). Without a
   destructive button the row simply collapses to flex-end. */
.rm-footer--actions {
  justify-content: flex-end;
  flex-wrap: wrap;
}
.rm-footer--actions.rm-footer--has-destructive {
  justify-content: space-between;
}
.rm-footer__end {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-inline-start: auto;
  flex-wrap: wrap;
}
/* Destructive uses outline-with-danger-text styling so it reads as a
   warning without dominating the visual hierarchy of the modal. */
.rm-footer__destructive {
  color: var(--danger);
}
.rm-footer__destructive:hover:not(:disabled) {
  background: var(--danger-soft);
  border-color: var(--danger);
}
.rm-footer--actions .btn {
  /* override the .rm-footer .btn { flex: 1 1 auto } rule so structured
     action buttons size to content (premium pill feel) instead of
     stretching to fill. */
  flex: 0 0 auto;
}
/* ADR-139 Wave 0: input focus glow + label weight + primary CTA hover lift
   are now scoped to .rm-card so every modal gets the premium feel. */
.rm-card .input:focus,
.rm-card .select:focus,
.rm-card textarea:focus {
  border-color: var(--accent);
  box-shadow: var(--input-focus-glow-premium);
  outline: none;
}
.rm-card .input,
.rm-card .select,
.rm-card textarea {
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.rm-card .label {
  font-weight: 700;
  color: var(--text-secondary);
  margin-block-end: 6px;
}
.rm-card .rm-footer .btn.primary {
  transition: transform 140ms ease, box-shadow 160ms ease;
}
.rm-card .rm-footer .btn.primary:hover:not(:disabled) {
  transform: translateY(var(--lift-1));
  box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 28%, transparent);
}
/* ADR-139 Wave 8 (2026-05-28): success-state pulse for the primary
   button. When the consumer's save handler sets aria-busy=true on the
   button while the request is in flight, the button gets a soft
   pulsing glow that hints "something is happening". Pairs with the
   loadingLabel string from the primaryAction primitive. */
.rm-card .rm-footer .btn.primary[aria-busy="true"] {
  animation: rm-btn-pulse 1.2s ease-in-out infinite;
  opacity: 0.92;
}
@keyframes rm-btn-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
  50%      { box-shadow: 0 0 0 8px color-mix(in srgb, var(--accent) 16%, transparent); }
}
/* Reduced motion: skip the pulse but keep the opacity hint. */
@media (prefers-reduced-motion: reduce) {
  .rm-card .rm-footer .btn.primary[aria-busy="true"] {
    animation: none;
  }
}
/* Reduced motion: keep state, drop animation */
@media (prefers-reduced-motion: reduce) {
  .rm-backdrop,
  .rm-card { animation: none !important; }
}
/* ============================================================
   ADR-139 Wave 0 (2026-05-28) — Premium modal shell is the default
   ============================================================
   The styles that used to live under `.rm-card--premium` are now
   baked into the base `.rm-card` above. Every ResponsiveModal
   automatically gets the Ctrl+K-style premium feel.

   `.rm-card--premium` survives as a NO-OP alias so any legacy
   consumer that still passes className="rm-card--premium" keeps
   working without breakage. Eventually we'll grep + remove the
   modifier everywhere, but for now this is the cheapest path.
   ============================================================ */
.rm-card--premium { /* no-op alias: see .rm-card base */ }
/* ============================================================
   ADR-139 Wave 5 (2026-05-28) — Shared form primitives
   ============================================================
   CSS for the 4 primitives in app/src/ui/form-primitives.jsx:
   PaymentStatusToggle, PatientPicker, InvoiceItemRow, InvoiceSummary.
   These styles read as native parts of the premium modal shell —
   same accent border, same rounded corners, same hover/focus glow.
   ============================================================ */
/* ── PaymentStatusToggle ─────────────────────────────────────── */
.pay-toggle {
  display: inline-flex;
  border-radius: 10px;
  background: var(--bg-subtle);
  padding: 4px;
  gap: 4px;
}
.pay-toggle__btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  font-weight: 600;
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-smooth),
              color var(--duration-fast) var(--ease-smooth);
}
.pay-toggle__btn:hover { color: var(--text-primary); }
.pay-toggle__btn.is-active.is-paid {
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success);
}
.pay-toggle__btn.is-active.is-unpaid {
  background: color-mix(in srgb, var(--warning) 14%, transparent);
  color: var(--warning);
}
.pay-toggle__icon { font-size: 13px; line-height: 1; }
.pay-toggle--sm .pay-toggle__btn { padding: 6px 10px; font-size: var(--text-xs); }
/* ── PatientPicker ───────────────────────────────────────────── */
/* ADR-139 A2-v2 (2026-05-28): position: relative so the floating
   dropdown anchors to the picker root. The list itself becomes an
   overlay (position: absolute) so opening it doesn't push the
   surrounding form down — fixing the empty-column gap the owner
   flagged in the post-A2 screenshot. */
.pp {
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}
.pp-input-wrap {
  position: relative;
}
.pp-input-icon {
  position: absolute;
  inset-inline-end: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-tertiary);
  pointer-events: none;
}
.pp-input {
  padding-inline-end: 36px;
}
/* ADR-139 A2-v2: floating overlay dropdown. z-index 20 sits above
   form siblings AND any sticky footer chrome inside the rm-card. */
.pp-list {
  position: absolute;
  top: calc(100% + 6px);
  inset-inline-start: 0;
  inset-inline-end: 0;
  z-index: 20;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-1, 0 10px 24px rgba(0, 0, 0, 0.12));
  scrollbar-width: thin;
  /* Subtle fade-in so the overlay doesn't pop abruptly. */
  animation: pp-list-in 160ms cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes pp-list-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .pp-list { animation: none; }
}
.pp-empty {
  padding: 16px;
  text-align: center;
  color: var(--text-tertiary);
  font-size: var(--text-sm);
}
.pp-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: transparent;
  border: 0;
  text-align: start;
  cursor: pointer;
  color: var(--text-primary);
  font: inherit;
  transition: background var(--duration-fast) var(--ease-smooth);
}
.pp-item.is-active {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.pp-avatar {
  width: 28px;
  height: 28px;
  font-size: 12px;
  background: var(--bg-subtle);
  color: var(--text-secondary);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-weight: 700;
}
.pp-item__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.pp-item__name {
  font-weight: 600;
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pp-item__sub {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.pp-selected {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.pp-selected__icon {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  border-radius: 8px;
  flex-shrink: 0;
}
.pp-selected__body { flex: 1; min-width: 0; }
.pp-selected__name { font-weight: 700; font-size: var(--text-md); }
.pp-selected__sub { font-size: var(--text-xs); color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.pp-selected__clear {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--duration-fast) var(--ease-smooth), color var(--duration-fast) var(--ease-smooth);
}
.pp-selected__clear:hover {
  background: var(--danger-soft);
  color: var(--danger);
}
/* ── InvoiceItemRow ──────────────────────────────────────────── */
/* ADR-139 A2-fix (2026-05-28): padding tightened 10/12 -> 8/10
   per owner feedback "حاسه كبير خالص". Saves ~8px per item card. */
.inv-item-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 10px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 10px;
  align-items: end;
}
.inv-item-row__field { display: flex; flex-direction: column; }
/* ADR-139 A2-v2: service column capped at 50% so it can't dominate
   the row on wide modals. Was flex: 2 1 200px (no cap), giving the
   select ~600px on size:xl shells — owner flagged as imbalanced
   vs the 90/110/110px numeric columns. */
.inv-item-row__field--service { flex: 1 1 240px; min-width: 0; max-width: 50%; }
.inv-item-row__field--qty     { flex: 0 1 88px;  min-width: 80px; }
.inv-item-row__field--price   { flex: 0 1 108px; min-width: 96px; }
.inv-item-row__field--total   { flex: 0 1 108px; min-width: 96px; }
/* Phones (<=480px): the cap doesn't help — let service take full row. */
@media (max-width: 480px) {
  .inv-item-row__field--service { max-width: 100%; flex-basis: 100%; }
}
.inv-item-row__total {
  font-weight: 800;
  font-size: var(--text-md);
  color: var(--accent);
  padding: 9px 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border));
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.inv-item-row__delete {
  display: flex;
  align-items: flex-end;
  padding-block-end: 4px;
}
/* ── InvoiceSummary ──────────────────────────────────────────── */
/* ADR-139 A2-fix (2026-05-28): compact inline layout.
   3-column grid (subtotal | discount | total) + methods strip
   replaces the previous 5-row vertical stack. ~80px shorter per
   modal. Stacks vertically on phones (<=480px) automatically. */
.inv-summary {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 12px;
}
/* 3-col grid: subtotal | discount | total */
.inv-summary__grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1.2fr;
  gap: 12px;
  align-items: end;
}
.inv-summary__cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.inv-summary__cell--total {
  padding-inline-start: 12px;
  border-inline-start: 1px dashed var(--border);
}
.inv-summary__cell-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-tertiary);
  line-height: 1.2;
}
.inv-summary__cell-value {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.inv-summary__cell-caption {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--danger);
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}
.inv-summary__discount-input {
  width: 100%;
  padding: 6px 10px;
  font-size: var(--text-sm);
}
.inv-summary__total {
  font-size: 22px;
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
/* Stack the 3 columns on phones for legibility */
@media (max-width: 480px) {
  .inv-summary__grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .inv-summary__cell--total {
    padding-inline-start: 0;
    border-inline-start: 0;
    padding-block-start: 8px;
    border-block-start: 1px dashed var(--border);
  }
}
/* Methods strip — row label + pills */
.inv-summary__methods-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
/* View-mode legacy rows (paid / balance) — kept stacked for clarity */
.inv-summary__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.inv-summary__row--view { font-size: var(--text-sm); }
.inv-summary__label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
}
.inv-summary__paid {
  font-weight: 700;
  color: var(--success);
  font-variant-numeric: tabular-nums;
}
.inv-summary__balance {
  font-weight: 700;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.inv-summary__balance.is-due { color: var(--danger); }
.inv-summary__row--balance {
  padding-block-start: 8px;
  border-block-start: 1px dashed var(--border);
}
.inv-summary__methods {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}
.inv-summary__method {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-smooth),
              color var(--duration-fast) var(--ease-smooth),
              border-color var(--duration-fast) var(--ease-smooth);
}
.inv-summary__method:hover {
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
  color: var(--text-primary);
}
.inv-summary__method.is-active {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 32%, var(--border));
}
/* ============================================================
   ADR-139 Wave 10 (2026-05-28) — QuickAddPatient inline variant
   ============================================================
   Modal variant uses ResponsiveModal's premium shell now. This block
   styles ONLY the inline variant (the embedded sub-form that opens
   inside the WalkInModal when the user clicks "إضافة مريض جديد").
   The slide-in animation curve matches the W1 Ctrl+K curve so the
   inline sub-form lands with the same feel as the parent modal. */
.quickadd-inline-card {
  border-radius: var(--radius-xl);
  background: var(--bg-elevated);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  overflow: hidden;
  margin-top: 8px;
  box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 10%, transparent);
  animation: quickaddSlideIn 320ms cubic-bezier(0.34, 1.32, 0.64, 1);
}
@keyframes quickaddSlideIn {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .quickadd-inline-card { animation: none; }
}
.quickadd-inline-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border);
}
.quickadd-inline-icon {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  flex-shrink: 0;
}
.quickadd-inline-titles { min-width: 0; flex: 1; }
.quickadd-inline-title {
  font-size: var(--text-md);
  font-weight: 800;
  color: var(--text-primary);
}
.quickadd-inline-sub {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin-top: 2px;
}
.quickadd-inline-body { padding: 16px 18px; }
.quickadd-inline-actions {
  display: flex;
  gap: 8px;
  padding: 12px 18px;
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
  justify-content: flex-end;
}
/* ============================================================
   ADR-139 Wave 6 (2026-05-28) — WizardModal step indicator
   ============================================================
   Renders inside the ResponsiveModal subtitle slot when a wizard
   has 2+ steps. Each step is a pill with a number (or check when
   done), connected by a thin line. Active step uses accent tint;
   completed steps use success tint; future steps muted.
   ============================================================ */
/* ADR-139 A3-v4 (2026-05-28) — wizard step body wrapper.
   The previous global min-height clamp was a one-size-fits-all
   floor that left sparse steps (patient picker only, visit type
   cards only) with a large empty area at the bottom. Owner asked
   for "flexible per step" sizing.
   Default: no min-height — body shrinks to natural content size.
   Per-step override: the consumer can pass a `minHeight` on the
   step config (e.g. step 1: 280px so the overlay PatientPicker
   dropdown stays inside body bounds without triggering rm-body's
   overflow-y: auto). Other steps get true content-driven height. */
.wizard-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.wizard-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  width: 100%;
}
.wizard-indicator__pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 4px;
  border-radius: 999px;
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  font-weight: 600;
  transition: background var(--duration-fast) var(--ease-smooth),
              color var(--duration-fast) var(--ease-smooth);
}
.wizard-indicator__pill.is-current {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.wizard-indicator__pill.is-done {
  background: color-mix(in srgb, var(--success) 10%, transparent);
  color: var(--success);
}
.wizard-indicator__dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-elevated);
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 800;
  border: 1px solid var(--border);
}
.wizard-indicator__pill.is-current .wizard-indicator__dot {
  background: var(--accent);
  color: var(--bg-elevated);
  border-color: var(--accent);
}
.wizard-indicator__pill.is-done .wizard-indicator__dot {
  background: var(--success);
  color: var(--bg-elevated);
  border-color: var(--success);
}
.wizard-indicator__label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wizard-subtitle__text {
  margin-top: 4px;
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}
/* On phones, hide the step labels to save horizontal space — just
   dots stay so users still see progress. */
@media (max-width: 480px) {
  .wizard-indicator__label { display: none; }
  .wizard-indicator__pill { padding: 4px; }
}
/* ============================================================
   W3 (ADR-077 → redesigned in ADR-079) — Public Landing Page V2
   Premium 2-column hero + stats + how-it-works + features +
   why-us + pricing + FAQ + final CTA + multi-column footer.
   ============================================================ */
.lp-shell{
  --lp-max:1220px;
  --lp-gap:24px;
  --lp-accent:#0ea5b7;
  --lp-accent-dark:#0a8a99;
  --lp-success:#22c55e;
  /* ADR-081: #root is a flex container (display:flex, height:100dvh,
     overflow:hidden) designed for the main app's .main-shell { flex: 1 }
     child. Pre-auth surfaces render directly inside #root, so the
     landing shell must claim the full flex slot AND own its own
     scrolling — otherwise it shrinks to content-width (aligned to start
     = right edge in RTL, leaving the left half empty) and the page
     can't scroll past the first viewport. */
  flex: 1 1 100%;
  width: 100%;
  min-width: 0;
  height: 100dvh;
  overflow-y: auto;
  overflow-x: hidden;
  background:var(--bg);
  color:var(--text-primary);
  font-family:inherit;
}
/* ───── 1. Sticky nav ───── */
.lp-nav{
  position:sticky;top:0;z-index:50;
  background:rgba(255,255,255,.78);
  backdrop-filter:saturate(180%) blur(20px);
  -webkit-backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid transparent;
  transition:all 280ms var(--ease-out, ease-out);
}
.lp-nav.is-scrolled{
  background:rgba(255,255,255,.92);
  border-bottom-color:var(--border-subtle, var(--border));
  box-shadow:0 4px 18px rgba(15,23,42,.04);
}
.lp-nav-inner{
  max-width:var(--lp-max);margin:0 auto;
  padding:14px 24px;
  display:flex;align-items:center;justify-content:space-between;gap:20px;
}
.lp-nav-brand{display:flex;align-items:center;}
/* ADR-083 (revised after owner feedback): the modirify-logo PNG (768×512)
   is a STACKED composition — square "M" icon band (y≈85–225) +
   "Modirify" wordmark text band (y≈234–300) + tagline "Run your clinic.
   Automatically." (y≈310–336) + top/bottom transparent padding. Width
   is set inline via the `width=220` prop on ModirifyLogo (React's
   inline style attribute wins specificity battles vs a CSS rule on the
   base class). Height + cover-crop trim the canvas padding so all three
   content bands sit visible inside the bar (~108 px total height). */
.lp-nav-brand .modirify-logo{
  display:block;
  height:80px !important;
  object-fit:cover;
  object-position:center 41%;
}
.lp-nav-links{
  display:flex;align-items:center;gap:28px;flex:1 1 auto;justify-content:center;
}
.lp-nav-links a{
  font-size:14px;font-weight:700;color:var(--text-secondary);
  text-decoration:none;cursor:pointer;
  transition:color 160ms;
}
.lp-nav-links a:hover{color:var(--lp-accent);}
.lp-nav-actions{display:flex;gap:10px;align-items:center;}
.lp-nav-login{
  background:transparent;border:none;cursor:pointer;
  font-size:14px;font-weight:700;color:var(--text-primary);
  padding:8px 14px;border-radius:999px;
  transition:all 160ms;
}
.lp-nav-login:hover{background:var(--bg-subtle);color:var(--lp-accent);}
.lp-nav-cta{
  display:inline-flex;align-items:center;gap:6px;
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;border:none;cursor:pointer;
  font-size:14px;font-weight:800;
  padding:10px 18px;border-radius:999px;
  box-shadow:0 6px 18px rgba(14,165,183,.28);
  transition:all 200ms var(--ease-out, ease-out);
}
.lp-nav-cta:hover{transform:translateY(var(--lift-1));box-shadow:0 10px 24px rgba(14,165,183,.4);}
/* ───── 2. Hero — 2 columns ───── */
.lp-hero{
  position:relative;overflow:hidden;
  padding:90px 24px 110px;
  background:
    radial-gradient(ellipse at 80% 20%, rgba(14,165,183,.08) 0%, transparent 55%),
    radial-gradient(ellipse at 20% 70%, rgba(34,197,94,.06) 0%, transparent 55%);
}
.lp-hero-blob{
  position:absolute;border-radius:50%;filter:blur(80px);
  pointer-events:none;z-index:0;opacity:.55;
  animation:lpFloat 18s ease-in-out infinite;
}
.lp-hero-blob--1{
  width:520px;height:520px;top:-180px;right:-160px;
  background:radial-gradient(circle, var(--lp-accent) 0%, transparent 70%);
  animation-delay:-3s;
}
.lp-hero-blob--2{
  width:420px;height:420px;bottom:-160px;left:-120px;
  background:radial-gradient(circle, var(--lp-success) 0%, transparent 70%);
  animation-delay:-9s;
}
.lp-hero-grid{
  position:absolute;inset:0;pointer-events:none;z-index:0;
  background-image:
    linear-gradient(rgba(14,165,183,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(14,165,183,.05) 1px, transparent 1px);
  background-size:42px 42px;
  mask-image:radial-gradient(ellipse at center, #000 30%, transparent 70%);
  -webkit-mask-image:radial-gradient(ellipse at center, #000 30%, transparent 70%);
}
.lp-hero-inner{
  position:relative;z-index:1;
  max-width:var(--lp-max);margin:0 auto;
  display:grid;grid-template-columns:1.1fr 1fr;gap:60px;align-items:center;
}
.lp-hero-copy{text-align:start;}
.lp-hero-badge{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 16px;border-radius:999px;
  background:rgba(255,255,255,.86);
  backdrop-filter:blur(8px);
  border:1px solid rgba(14,165,183,.32);color:var(--lp-accent);
  font-size:12px;font-weight:800;
  margin-bottom:24px;
  animation:lpFadeIn .6s var(--ease-out, ease-out) both;
}
.lp-hero-badge svg{color:#f59e0b;}
.lp-hero-title{
  font-size:clamp(38px, 5.5vw, 62px);
  font-weight:900;line-height:1.1;
  margin:0 0 22px;letter-spacing:-.025em;
  animation:lpFadeIn .7s var(--ease-out, ease-out) .1s both;
}
.lp-hero-accent{
  background:linear-gradient(120deg, var(--lp-accent) 0%, var(--lp-success) 100%);
  background-clip:text;-webkit-background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
  position:relative;display:inline;
}
.lp-hero-sub{
  font-size:clamp(15px, 1.5vw, 18px);
  color:var(--text-secondary);line-height:1.85;
  max-width:560px;margin:0 0 32px;
  animation:lpFadeIn .8s var(--ease-out, ease-out) .2s both;
}
.lp-hero-actions{
  display:flex;gap:12px;flex-wrap:wrap;
  margin-bottom:32px;
  animation:lpFadeIn .9s var(--ease-out, ease-out) .3s both;
}
.lp-btn-primary,
.lp-btn-outline{
  display:inline-flex;align-items:center;gap:8px;
  padding:14px 26px;font-size:15px;font-weight:800;
  border-radius:999px;cursor:pointer;
  transition:all 220ms var(--ease-out, ease-out);
}
.lp-btn-primary{
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;border:none;
  box-shadow:0 10px 28px rgba(14,165,183,.34);
}
.lp-btn-primary:hover{transform:translateY(var(--lift-2));box-shadow:0 14px 36px rgba(14,165,183,.44);}
.lp-btn-outline{
  background:rgba(255,255,255,.7);
  color:var(--text-primary);
  border:1.5px solid var(--border);
  backdrop-filter:blur(8px);
}
.lp-btn-outline:hover{
  transform:translateY(var(--lift-1));
  border-color:var(--lp-accent);color:var(--lp-accent);
}
.lp-hero-trust{
  display:flex;gap:20px;flex-wrap:wrap;
  font-size:13px;color:var(--text-tertiary);
  animation:lpFadeIn 1s var(--ease-out, ease-out) .4s both;
}
.lp-hero-trust-item{display:inline-flex;align-items:center;gap:6px;font-weight:600;}
.lp-hero-trust-item svg{
  color:#fff;
  background:var(--lp-success);
  border-radius:50%;padding:2px;
  width:18px;height:18px;
}
/* App preview mock (synthetic dashboard) */
.lp-hero-visual{
  position:relative;
  animation:lpFadeIn 1s var(--ease-out, ease-out) .35s both;
}
.lp-mock{position:relative;}
.lp-mock-window{
  background:#fff;
  border:1px solid rgba(15,23,42,.08);
  border-radius:18px;
  overflow:hidden;
  box-shadow:0 30px 60px rgba(15,23,42,.12), 0 12px 28px rgba(15,23,42,.06);
  transform:perspective(1200px) rotateY(-4deg) rotateX(2deg);
  transition:transform 600ms var(--ease-out, ease-out);
}
.lp-mock-window:hover{transform:perspective(1200px) rotateY(-2deg) rotateX(1deg);}
.lp-mock-chrome{
  display:flex;align-items:center;gap:7px;
  padding:11px 14px;
  background:linear-gradient(180deg, #fafbfc 0%, #f5f6f8 100%);
  border-bottom:1px solid rgba(15,23,42,.06);
}
.lp-mock-dot{
  width:11px;height:11px;border-radius:50%;display:inline-block;
}
.lp-mock-dot--red{background:#ed6a5e;}
.lp-mock-dot--yellow{background:#f5bf4f;}
.lp-mock-dot--green{background:#62c554;}
.lp-mock-url{
  flex:1;text-align:center;
  font-size:11px;color:var(--text-tertiary);font-weight:600;
  font-family:ui-monospace, monospace;
}
.lp-mock-body{padding:18px;}
.lp-mock-kpis{
  display:grid;grid-template-columns:repeat(3, 1fr);gap:10px;margin-bottom:14px;
}
.lp-mock-kpi{
  padding:12px;border-radius:10px;
  background:var(--bg-subtle);
  border:1px solid transparent;
}
.lp-mock-kpi--accent{
  background:linear-gradient(135deg, rgba(14,165,183,.1) 0%, rgba(14,165,183,.02) 100%);
  border-color:rgba(14,165,183,.18);
}
.lp-mock-kpi--success{
  background:linear-gradient(135deg, rgba(34,197,94,.1) 0%, rgba(34,197,94,.02) 100%);
  border-color:rgba(34,197,94,.18);
}
.lp-mock-kpi--warning{
  background:linear-gradient(135deg, rgba(245,158,11,.1) 0%, rgba(245,158,11,.02) 100%);
  border-color:rgba(245,158,11,.18);
}
.lp-mock-kpi-label{font-size:10px;color:var(--text-tertiary);font-weight:700;}
.lp-mock-kpi-value{
  font-size:22px;font-weight:900;line-height:1.1;margin:4px 0;
  font-variant-numeric:tabular-nums;
}
.lp-mock-kpi--accent .lp-mock-kpi-value{color:var(--lp-accent);}
.lp-mock-kpi--success .lp-mock-kpi-value{color:var(--lp-success);}
.lp-mock-kpi--warning .lp-mock-kpi-value{color:#f59e0b;}
.lp-mock-kpi-trend{font-size:10px;color:var(--text-secondary);font-weight:700;}
.lp-mock-list{
  border:1px solid rgba(15,23,42,.06);
  border-radius:10px;overflow:hidden;
}
.lp-mock-list-head{
  display:flex;align-items:center;justify-content:space-between;
  padding:10px 14px;
  background:var(--bg-subtle);
  font-size:12px;font-weight:800;
  border-bottom:1px solid rgba(15,23,42,.06);
}
.lp-mock-pill{
  font-size:10px;font-weight:700;
  padding:2px 8px;border-radius:999px;
  background:rgba(14,165,183,.1);color:var(--lp-accent);
}
.lp-mock-row{
  display:grid;grid-template-columns:46px 1fr 1fr auto;gap:10px;align-items:center;
  padding:10px 14px;
  font-size:12px;
  border-top:1px solid rgba(15,23,42,.04);
}
.lp-mock-row:first-of-type{border-top:none;}
.lp-mock-row-time{
  font-variant-numeric:tabular-nums;font-weight:800;color:var(--text-primary);
  font-family:ui-monospace, monospace;
}
.lp-mock-row-name{font-weight:700;color:var(--text-primary);}
.lp-mock-row-service{color:var(--text-secondary);font-size:11px;}
.lp-mock-row-status{
  font-size:10px;font-weight:800;
  padding:2px 8px;border-radius:999px;
}
.lp-mock-row-status.is-confirmed{background:rgba(34,197,94,.14);color:#16a34a;}
.lp-mock-row-status.is-in-progress{background:rgba(14,165,183,.14);color:var(--lp-accent);}
.lp-mock-row-status.is-pending{background:rgba(245,158,11,.14);color:#d97706;}
.lp-mock-float{
  position:absolute;
  background:#fff;
  border:1px solid rgba(15,23,42,.08);
  border-radius:14px;
  padding:12px 14px;
  box-shadow:0 14px 32px rgba(15,23,42,.1);
  animation:lpFloatCard 6s ease-in-out infinite;
}
.lp-mock-float--chart{
  left:-30px;top:46%;
  width:180px;
  animation-delay:-2s;
}
.lp-mock-float--credit{
  right:-12px;bottom:-12px;
  display:flex;align-items:center;gap:10px;
  animation-delay:-4s;
}
.lp-mock-float-label{font-size:10px;color:var(--text-tertiary);font-weight:700;}
.lp-mock-float-value{
  font-size:15px;font-weight:900;color:var(--text-primary);
  font-variant-numeric:tabular-nums;margin-bottom:4px;
}
.lp-mock-sparkline{width:100%;height:34px;}
.lp-mock-float-icon{
  width:32px;height:32px;border-radius:10px;
  display:grid;place-items:center;
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;flex-shrink:0;
}
.lp-mock-float-mini-label{font-size:10px;color:var(--text-tertiary);font-weight:700;}
.lp-mock-float-mini-value{font-size:12px;font-weight:800;color:var(--text-primary);}
@keyframes lpFadeIn{
  from{opacity:0;transform:translateY(16px);}
  to{opacity:1;transform:translateY(0);}
}
@keyframes lpFloat{
  0%,100%{transform:translate(0,0) scale(1);}
  33%{transform:translate(-22px,18px) scale(1.06);}
  66%{transform:translate(18px,-12px) scale(.96);}
}
@keyframes lpFloatCard{
  0%,100%{transform:translateY(0);}
  50%{transform:translateY(-8px);}
}
/* Reveal-on-scroll */
.lp-reveal{opacity:0;transform:translateY(28px);transition:opacity 700ms var(--ease-out, ease-out), transform 700ms var(--ease-out, ease-out);}
.lp-reveal.is-revealed{opacity:1;transform:translateY(0);}
/* ───── 3. Stats bar ───── */
.lp-stats-section{
  max-width:var(--lp-max);margin:-40px auto 0;padding:0 24px;
  position:relative;z-index:2;
}
.lp-stats-grid{
  display:grid;grid-template-columns:repeat(4, 1fr);gap:0;
  background:#fff;
  border:1px solid var(--border-subtle, var(--border));
  border-radius:18px;
  padding:24px;
  box-shadow:0 20px 48px rgba(15,23,42,.08);
}
.lp-stat{
  text-align:center;padding:12px 16px;
  border-left:1px solid var(--border-subtle, var(--border));
}
.lp-stat:last-child{border-left:none;}
.lp-stat-value{
  font-size:32px;font-weight:900;line-height:1;
  font-variant-numeric:tabular-nums;
  background:linear-gradient(120deg, var(--lp-accent) 0%, var(--lp-success) 100%);
  background-clip:text;-webkit-background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
}
.lp-stat-suffix{font-size:18px;}
.lp-stat-label{
  font-size:13px;color:var(--text-secondary);font-weight:600;
  margin-top:6px;
}
/* ───── Section shells ───── */
.lp-section{
  max-width:var(--lp-max);margin:0 auto;
  padding:90px 24px;
}
.lp-section-header{
  text-align:center;max-width:720px;margin:0 auto 64px;
}
.lp-section-eyebrow{
  display:inline-block;
  font-size:13px;font-weight:800;color:var(--lp-accent);
  text-transform:uppercase;letter-spacing:.1em;
  margin-bottom:14px;
}
.lp-section-title{
  font-size:clamp(28px, 3.8vw, 42px);
  font-weight:900;line-height:1.2;margin:0 0 18px;
  letter-spacing:-.02em;
}
.lp-section-sub{
  font-size:16px;color:var(--text-secondary);
  line-height:1.85;margin:0;
}
/* ───── 4. How it works ───── */
.lp-how-grid{
  display:grid;grid-template-columns:repeat(3, 1fr);gap:24px;
  position:relative;
}
.lp-how-grid::before{
  content:"";position:absolute;
  top:46px;right:16%;left:16%;
  height:2px;
  background:linear-gradient(to left, transparent 0%, rgba(14,165,183,.18) 20%, rgba(14,165,183,.18) 80%, transparent 100%);
  z-index:0;
}
.lp-how-card{
  position:relative;z-index:1;
  padding:28px 24px;
  background:#fff;
  border:1px solid var(--border-subtle, var(--border));
  border-radius:18px;
  text-align:center;
  transition:all 280ms var(--ease-out, ease-out);
}
.lp-how-card:hover{
  transform:translateY(var(--lift-2));
  border-color:var(--lp-accent);
  box-shadow:0 18px 40px rgba(14,165,183,.12);
}
.lp-how-step{
  position:absolute;top:-16px;left:50%;transform:translateX(-50%);
  width:44px;height:44px;border-radius:50%;
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;
  display:grid;place-items:center;
  font-size:14px;font-weight:900;
  box-shadow:0 8px 18px rgba(14,165,183,.32);
}
.lp-how-icon{
  width:60px;height:60px;border-radius:16px;
  display:grid;place-items:center;margin:18px auto 16px;
  background:linear-gradient(135deg, rgba(14,165,183,.1) 0%, rgba(34,197,94,.06) 100%);
  color:var(--lp-accent);
}
.lp-how-title{
  font-size:18px;font-weight:800;margin-bottom:10px;
}
.lp-how-body{
  font-size:14px;color:var(--text-secondary);line-height:1.8;
}
/* ───── 5. Features grid ───── */
.lp-features-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(260px, 1fr));
  gap:20px;
}
.lp-feature-card{
  padding:28px 22px;
  background:#fff;
  border:1px solid var(--border-subtle, var(--border));
  border-radius:16px;
  transition:all 280ms var(--ease-out, ease-out);
  position:relative;overflow:hidden;
}
.lp-feature-card::before{
  content:"";position:absolute;top:0;right:0;width:100%;height:3px;
  background:linear-gradient(90deg, var(--lp-accent) 0%, var(--lp-success) 100%);
  transform:scaleX(0);transform-origin:right;
  transition:transform 280ms var(--ease-out, ease-out);
}
.lp-feature-card:hover{
  transform:translateY(var(--lift-2));
  border-color:rgba(14,165,183,.4);
  box-shadow:0 14px 36px rgba(14,165,183,.1);
}
.lp-feature-card:hover::before{transform:scaleX(1);}
.lp-feature-icon{
  width:52px;height:52px;border-radius:14px;
  display:grid;place-items:center;
  background:linear-gradient(135deg, rgba(14,165,183,.12) 0%, rgba(14,165,183,.04) 100%);
  color:var(--lp-accent);
  margin-bottom:18px;
  transition:transform 320ms var(--ease-out, ease-out);
}
.lp-feature-card:hover .lp-feature-icon{transform:scale(1.08) rotate(-4deg);}
.lp-feature-title{
  font-size:17px;font-weight:800;margin-bottom:8px;
}
.lp-feature-body{
  font-size:14px;color:var(--text-secondary);line-height:1.75;
}
/* ───── 6. Why Modirify ───── */
.lp-why-grid{
  display:grid;grid-template-columns:repeat(2, 1fr);gap:20px;
}
.lp-why-card{
  display:flex;align-items:flex-start;gap:18px;
  padding:24px;
  background:linear-gradient(135deg, #fff 0%, rgba(14,165,183,.02) 100%);
  border:1px solid var(--border-subtle, var(--border));
  border-radius:16px;
  transition:all 280ms var(--ease-out, ease-out);
}
.lp-why-card:hover{
  border-color:rgba(14,165,183,.32);
  box-shadow:0 12px 32px rgba(14,165,183,.08);
}
.lp-why-icon{
  width:48px;height:48px;border-radius:14px;flex-shrink:0;
  display:grid;place-items:center;
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;
  box-shadow:0 6px 16px rgba(14,165,183,.28);
}
.lp-why-title{font-size:16px;font-weight:800;margin-bottom:6px;}
.lp-why-body{font-size:14px;color:var(--text-secondary);line-height:1.8;}
/* ───── 7. Pricing grid ───── */
.lp-pricing-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));
  gap:24px;
  max-width:1000px;margin:0 auto;
}
.lp-pricing-loading{
  text-align:center;padding:40px;color:var(--text-tertiary);
}
.lp-plan-card{
  position:relative;
  padding:36px 28px;
  background:#fff;
  border:2px solid var(--border-subtle, var(--border));
  border-radius:20px;
  display:flex;flex-direction:column;
  transition:all 280ms var(--ease-out, ease-out);
}
.lp-plan-card:hover{
  transform:translateY(var(--lift-2));
  box-shadow:0 14px 36px rgba(15,23,42,.08);
}
.lp-plan-card.is-highlighted{
  border-color:var(--lp-accent);
  background:linear-gradient(180deg, rgba(14,165,183,.05) 0%, #fff 60%);
  box-shadow:0 14px 36px rgba(14,165,183,.18);
  transform:scale(1.04);
}
.lp-plan-card.is-highlighted:hover{transform:scale(1.04) translateY(var(--lift-2));}
.lp-plan-badge{
  position:absolute;top:-14px;left:50%;transform:translateX(-50%);
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;
  padding:7px 16px;border-radius:999px;
  font-size:11px;font-weight:900;letter-spacing:.06em;
  box-shadow:0 6px 16px rgba(14,165,183,.36);
}
.lp-plan-label{
  font-size:15px;font-weight:800;color:var(--lp-accent);
  letter-spacing:.04em;
  margin-bottom:18px;
}
.lp-plan-price-row{
  display:flex;align-items:baseline;gap:6px;
  margin-bottom:24px;
}
.lp-plan-price{
  font-size:52px;font-weight:900;line-height:1;
  font-variant-numeric:tabular-nums;
  color:var(--text-primary);
  letter-spacing:-.02em;
}
.lp-plan-currency{font-size:18px;font-weight:800;color:var(--text-secondary);}
.lp-plan-period{font-size:14px;color:var(--text-tertiary);}
.lp-plan-features{
  list-style:none;padding:0;margin:0 0 28px;
  display:flex;flex-direction:column;gap:11px;
}
.lp-plan-features li{
  display:flex;align-items:center;gap:8px;
  font-size:14px;color:var(--text-secondary);line-height:1.6;
}
.lp-plan-features li svg{
  color:#fff;background:var(--lp-success);
  border-radius:50%;padding:2px;width:18px;height:18px;
  flex-shrink:0;
}
.lp-plan-cta{
  margin-top:auto;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:13px 18px;
  border-radius:999px;
  background:var(--bg-card);
  color:var(--text-primary);
  border:1.5px solid var(--border);
  font-size:14px;font-weight:800;cursor:pointer;
  transition:all 200ms var(--ease-out, ease-out);
}
.lp-plan-cta:hover{
  border-color:var(--lp-accent);color:var(--lp-accent);
  transform:translateY(var(--lift-1));
}
.lp-plan-cta.is-primary{
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 100%);
  color:#fff;border-color:var(--lp-accent);
  box-shadow:0 8px 20px rgba(14,165,183,.28);
}
.lp-plan-cta.is-primary:hover{
  color:#fff;box-shadow:0 12px 28px rgba(14,165,183,.4);
  transform:translateY(var(--lift-1));
}
/* ── Wave 4 (ADR-171): Billing toggle + plan highlights + inherited chip ── */
.lp-billing-toggle-wrap{
  display:flex;justify-content:center;
  margin:0 auto 28px;
  background:var(--bg-subtle,#f8fafc);
  border-radius:999px;
  padding:4px;
  width:fit-content;
  border:1px solid var(--border);
}
.lp-billing-opt{
  padding:8px 22px;
  border-radius:999px;
  border:none;background:transparent;
  font-size:14px;font-weight:700;
  color:var(--text-tertiary);
  cursor:pointer;
  display:flex;align-items:center;gap:8px;
  transition:all 180ms ease;
  line-height:1;
}
.lp-billing-opt.is-active{
  background:#fff;
  color:var(--lp-accent);
  box-shadow:0 2px 8px rgba(15,23,42,.10);
}
.lp-billing-save-chip{
  background:color-mix(in srgb, var(--lp-success,#16a34a) 15%, transparent);
  color:var(--lp-success,#16a34a);
  padding:2px 8px;border-radius:999px;
  font-size:11px;font-weight:900;
}
.lp-plan-tagline{
  font-size:13px;color:var(--text-secondary);
  margin-top:4px;margin-bottom:10px;
}
.lp-plan-highlights{
  display:flex;gap:10px;flex-wrap:wrap;
  margin-bottom:18px;
}
.lp-plan-highlight{
  display:inline-flex;align-items:center;gap:5px;
  font-size:12px;font-weight:700;
  color:var(--text-secondary);
  background:var(--bg-subtle,#f8fafc);
  border:1px solid var(--border);
  border-radius:999px;padding:3px 10px;
}
.lp-plan-highlight svg{color:var(--lp-accent);flex-shrink:0;}
/* Inherited chip — "All {prev} features +" in Pro/Premium cards */
.lp-plan-inherited{
  display:flex!important;align-items:center;gap:7px;
  background:color-mix(in srgb, var(--lp-success,#16a34a) 10%, transparent)!important;
  color:var(--lp-success,#16a34a)!important;
  border-radius:10px;padding:8px 12px!important;
  font-size:13px!important;font-weight:800!important;
  border:1px solid color-mix(in srgb, var(--lp-success,#16a34a) 25%, var(--border));
  margin-bottom:6px;
}
/* Override the generic li svg style for inherited chip so the icon has no circle */
.lp-plan-inherited svg{
  background:none!important;color:var(--lp-success,#16a34a)!important;
  padding:0!important;width:16px!important;height:16px!important;
}
.lp-pricing-note{
  display:flex;align-items:center;gap:8px;justify-content:center;
  margin-top:36px;
  font-size:13px;color:var(--text-tertiary);
  text-align:center;flex-wrap:wrap;
}
/* ───── 8. FAQ ───── */
.lp-faq-list{
  max-width:820px;margin:0 auto;
  display:flex;flex-direction:column;gap:10px;
}
.lp-faq-item{
  background:#fff;
  border:1px solid var(--border-subtle, var(--border));
  border-radius:14px;
  overflow:hidden;
  transition:all 240ms var(--ease-out, ease-out);
}
.lp-faq-item.is-open{
  border-color:var(--lp-accent);
  box-shadow:0 8px 24px rgba(14,165,183,.08);
}
.lp-faq-q{
  width:100%;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:20px 22px;
  background:transparent;border:none;cursor:pointer;
  font-size:15px;font-weight:700;color:var(--text-primary);
  text-align:start;
}
.lp-faq-q:hover{background:var(--bg-subtle);}
.lp-faq-q svg{color:var(--text-tertiary);transition:all 240ms;flex-shrink:0;}
.lp-faq-item.is-open .lp-faq-q{color:var(--lp-accent);}
.lp-faq-item.is-open .lp-faq-q svg{color:var(--lp-accent);transform:scale(1.1);}
.lp-faq-a{
  padding:0 22px 22px;
  font-size:14px;color:var(--text-secondary);line-height:1.95;
  animation:lpFadeIn 280ms var(--ease-out, ease-out) both;
}
/* ───── 9. Final CTA ───── */
.lp-cta-final{padding-top:32px;padding-bottom:96px;}
.lp-cta-card{
  position:relative;overflow:hidden;
  text-align:center;
  padding:72px 32px;
  background:linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent-dark) 60%, #064e58 100%);
  border-radius:24px;
  max-width:880px;margin:0 auto;
  color:#fff;
  box-shadow:0 24px 60px rgba(14,165,183,.32);
}
.lp-cta-bg{
  position:absolute;inset:0;pointer-events:none;
  background-image:
    radial-gradient(circle at 18% 30%, rgba(255,255,255,.18) 0%, transparent 35%),
    radial-gradient(circle at 82% 70%, rgba(255,255,255,.12) 0%, transparent 38%);
  animation:lpFloat 14s ease-in-out infinite;
}
.lp-cta-inner{position:relative;z-index:1;}
.lp-cta-eyebrow{
  font-size:13px;font-weight:800;color:rgba(255,255,255,.85);
  text-transform:uppercase;letter-spacing:.1em;margin-bottom:14px;
}
.lp-cta-title{
  font-size:clamp(28px, 3.4vw, 38px);
  font-weight:900;line-height:1.25;margin:0 0 16px;
  letter-spacing:-.02em;
}
.lp-cta-sub{
  font-size:16px;color:rgba(255,255,255,.9);line-height:1.85;
  margin:0 auto 32px;max-width:540px;
}
.lp-cta-button{
  display:inline-flex;align-items:center;gap:8px;
  padding:16px 32px;font-size:16px;font-weight:800;
  background:#fff;color:var(--lp-accent);border:none;
  border-radius:999px;cursor:pointer;
  box-shadow:0 12px 32px rgba(0,0,0,.18);
  transition:all 220ms var(--ease-out, ease-out);
}
.lp-cta-button:hover{
  transform:translateY(var(--lift-2));
  box-shadow:0 18px 40px rgba(0,0,0,.26);
  color:var(--lp-accent-dark);
}
/* ───── 10. Footer ───── */
.lp-footer{
  background:#0f172a;
  color:rgba(255,255,255,.7);
  padding:60px 24px 24px;
}
.lp-footer-inner{
  max-width:var(--lp-max);margin:0 auto;
  display:grid;
  grid-template-columns:2fr 1fr 1fr 1fr;gap:40px;
}
.lp-footer-col{display:flex;flex-direction:column;gap:10px;}
.lp-footer-col--brand{gap:14px;}
.lp-footer-col--brand .modirify-logo{filter:brightness(0) invert(1);opacity:.95;}
.lp-footer-tagline{
  font-size:13px;color:rgba(255,255,255,.6);line-height:1.85;
  margin:0;max-width:340px;
}
.lp-footer-col-title{
  font-size:13px;font-weight:800;color:#fff;
  text-transform:uppercase;letter-spacing:.08em;
  margin-bottom:6px;
}
.lp-footer-col a{
  font-size:13px;color:rgba(255,255,255,.65);text-decoration:none;
  display:inline-flex;align-items:center;gap:6px;
  transition:color 160ms;cursor:pointer;
}
.lp-footer-col a:hover{color:var(--lp-accent);}
.lp-footer-copy{
  max-width:var(--lp-max);margin:36px auto 0;
  padding-top:24px;
  border-top:1px solid rgba(255,255,255,.1);
  font-size:12px;color:rgba(255,255,255,.5);text-align:center;
}
/* ============================================================
   W4 (ADR-078) — Manual receipts: upload form + admin queue
   ============================================================ */
/* Upload form inside MarketingUpgradeModal */
.mk-upgrade__back-btn{
  display:inline-flex;align-items:center;gap:6px;
  background:transparent;border:none;cursor:pointer;
  font-size:13px;color:var(--text-secondary);
  padding:0;margin-bottom:10px;
}
.mk-upgrade__back-btn:hover{color:var(--accent);}
.mk-upgrade__order-summary{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:14px 16px;
  background:var(--bg-subtle);
  border:1px solid var(--accent);border-radius:var(--radius-sm);
  margin-bottom:14px;
}
.mk-upgrade__order-label{font-weight:700;color:var(--text-tertiary);font-size:13px;}
.mk-upgrade__order-name{font-weight:800;color:var(--text-primary);flex:1 1 auto;}
.mk-upgrade__order-price{font-weight:900;color:var(--accent);font-variant-numeric:tabular-nums;}
.mk-upgrade__instructions{
  padding:14px 16px;
  background:var(--info-soft, var(--bg-subtle));
  border:1px dashed var(--info, var(--border));
  border-radius:var(--radius-sm);
  margin-bottom:16px;
}
.mk-upgrade__instructions-title{
  display:flex;align-items:center;gap:6px;
  font-weight:700;color:var(--text-primary);margin-bottom:8px;
}
.mk-upgrade__instructions-list{
  list-style:decimal;padding-right:18px;margin:0;
  font-size:13px;color:var(--text-secondary);line-height:2;
}
.mk-upgrade__instructions-list strong{color:var(--text-primary);font-variant-numeric:tabular-nums;}
.mk-upgrade__form{display:flex;flex-direction:column;gap:14px;}
.mk-upgrade__field{display:flex;flex-direction:column;gap:6px;}
.mk-upgrade__field-label{font-size:13px;font-weight:700;color:var(--text-primary);}
.mk-upgrade__file-input{cursor:pointer;}
.mk-upgrade__file-name{
  display:inline-flex;align-items:center;gap:4px;
  font-size:12px;color:#22c55e;font-weight:700;margin-top:4px;
}
.mk-upgrade__actions{
  display:flex;gap:10px;flex-wrap:wrap;margin-top:6px;
}
.mk-upgrade__actions .btn{flex:1 1 auto;justify-content:center;}
/* ADR-145 F2: legal note under the receipt-upload actions. Small, muted,
   but the billing-policy link is bold so it reads as a real anchor. */
.mk-upgrade__legal-note{
  margin-top:14px;
  padding:10px 12px;
  display:flex;align-items:flex-start;gap:8px;
  font-size:12px;line-height:1.7;
  color:var(--text-tertiary);
  background:var(--bg-subtle);
  border-radius:10px;
}
.mk-upgrade__legal-note a{
  color:var(--accent);font-weight:800;text-decoration:none;
}
.mk-upgrade__legal-note a:hover{text-decoration:underline;}
.mk-upgrade__success{
  display:flex;flex-direction:column;align-items:center;gap:14px;
  text-align:center;padding:32px 20px;
}
.mk-upgrade__success-icon{
  width:64px;height:64px;border-radius:50%;
  display:grid;place-items:center;
  background:linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
  color:#fff;
  animation:lpFadeIn 400ms var(--ease-out, ease-out) both;
}
.mk-upgrade__success-title{font-size:20px;font-weight:900;margin:0;}
.mk-upgrade__success-body{font-size:14px;color:var(--text-secondary);line-height:1.8;margin:0;max-width:420px;}
/* SaaS-admin receipts queue */
.sa-receipts-card{padding:18px;display:flex;flex-direction:column;gap:14px;}
.sa-receipts-head{display:flex;align-items:center;justify-content:space-between;}
.sa-receipts-title{
  display:inline-flex;align-items:center;gap:8px;
  font-size:16px;font-weight:800;color:var(--text-primary);
}
.sa-receipts-tabs{
  display:flex;gap:4px;
  border-bottom:1px solid var(--border-subtle, var(--border));
}
.sa-receipts-tab{
  display:inline-flex;align-items:center;gap:6px;
  padding:10px 14px;
  background:transparent;border:none;cursor:pointer;
  font-size:13px;font-weight:700;color:var(--text-secondary);
  border-bottom:2px solid transparent;
  transition:all 160ms;
}
.sa-receipts-tab:hover{color:var(--text-primary);}
.sa-receipts-tab.is-active{color:var(--accent);border-bottom-color:var(--accent);}
.sa-receipts-tab__count{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:20px;padding:0 6px;height:18px;
  border-radius:999px;
  background:var(--bg-subtle);color:var(--text-tertiary);
  font-size:11px;font-weight:800;font-variant-numeric:tabular-nums;
}
.sa-receipts-tab.is-active .sa-receipts-tab__count{
  background:var(--accent);color:#fff;
}
.sa-receipts-empty{
  display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:32px;color:var(--text-tertiary);
}
.sa-receipts-list{display:flex;flex-direction:column;gap:10px;}
.sa-receipt-row{
  padding:14px;
  background:var(--bg-card);
  border:1px solid var(--border-subtle, var(--border));
  border-radius:var(--radius-sm);
  display:flex;flex-direction:column;gap:8px;
}
.sa-receipt-row.is-verified{border-color:#22c55e;}
.sa-receipt-row.is-rejected{border-color:var(--danger);opacity:.85;}
.sa-receipt-row__head{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
}
.sa-receipt-row__amount{
  font-size:18px;font-weight:900;color:var(--text-primary);
  font-variant-numeric:tabular-nums;
}
.sa-receipt-row__amount span{font-size:13px;color:var(--text-tertiary);margin-right:4px;}
.sa-receipt-row__method{
  font-size:12px;color:var(--text-secondary);
  padding:2px 8px;border-radius:999px;
  background:var(--bg-subtle);
}
.sa-receipt-row__meta{
  font-size:12px;color:var(--text-tertiary);line-height:1.7;
}
.sa-receipt-row__meta code{
  font-family:ui-monospace, monospace;
  background:var(--bg-subtle);padding:1px 6px;border-radius:4px;
}
.sa-receipt-row__notes,
.sa-receipt-row__rejection{
  display:inline-flex;align-items:center;gap:6px;
  font-size:12px;color:var(--text-secondary);
  padding:6px 10px;border-radius:var(--radius-xs, 6px);
  background:var(--bg-subtle);
}
.sa-receipt-row__rejection{background:var(--danger-soft);color:var(--danger);}
.sa-receipt-row__actions{
  display:flex;gap:8px;flex-wrap:wrap;margin-top:4px;
}
.sa-receipt-row__actions .btn{padding:6px 12px;font-size:12px;}
.btn.danger{background:var(--danger);color:#fff;border-color:var(--danger);}
.btn.danger:hover:not(:disabled){background:#b91c1c;border-color:#b91c1c;}
/* Receipt preview overlay */
.sa-receipt-preview-backdrop{
  position:fixed;inset:0;z-index:60;
  background:rgba(0,0,0,.55);
  display:grid;place-items:center;padding:20px;
}
.sa-receipt-preview,
.sa-receipt-reject{
  background:var(--bg-card);
  border-radius:var(--radius-lg, 16px);
  padding:18px;
  max-width:min(620px, 96vw);
  max-height:90vh;overflow:auto;
  display:flex;flex-direction:column;gap:12px;
  box-shadow:0 24px 48px rgba(0,0,0,.32);
}
.sa-receipt-preview__head{
  display:flex;align-items:center;justify-content:space-between;
}
.sa-receipt-preview__img{
  max-width:100%;max-height:60vh;
  object-fit:contain;border-radius:var(--radius-sm);
  background:var(--bg-subtle);
}
.sa-receipt-preview__pdf{
  width:100%;height:60vh;border:1px solid var(--border);border-radius:var(--radius-sm);
}
.sa-receipt-preview__loading{
  display:inline-flex;align-items:center;gap:8px;
  padding:32px;color:var(--text-tertiary);justify-content:center;
}
.sa-receipt-preview__error{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:10px;padding:32px 18px;text-align:center;
  color:var(--danger);background:var(--bg-subtle);
  border-radius:var(--radius);
}
.sa-receipt-preview__error p{margin:0;font-size:14px;color:var(--text-secondary);}
.sa-receipt-preview__open{align-self:flex-start;}
/* ─── ADR-087: SaaS Admin KPIs + tabs + pricing UI ─── */
/* KPI grid under the hero - 6 tiles, responsive */
.sa-kpis{
  display:grid;
  grid-template-columns:repeat(6, minmax(0, 1fr));
  gap:12px;
  margin-top:14px;
}
.sa-kpi{
  display:flex;align-items:center;gap:12px;
  padding:12px 14px;
  background:var(--bg-card);
  border:1px solid var(--border);
  border-radius:14px;
  box-shadow:0 1px 3px rgba(0,0,0,.04);
  transition:transform 120ms, box-shadow 120ms;
}
.sa-kpi:hover{transform:translateY(var(--lift-1));box-shadow:0 4px 12px rgba(0,0,0,.06);}
.sa-kpi__icon{
  width:38px;height:38px;border-radius:11px;
  display:flex;align-items:center;justify-content:center;
  flex-shrink:0;
}
.sa-kpi__icon--accent  {background:rgba(14,165,183,0.12);color:#0a8a99;}
.sa-kpi__icon--success {background:rgba(34,197,94,0.12);color:#16a34a;}
.sa-kpi__icon--info    {background:rgba(59,130,246,0.12);color:#2563eb;}
.sa-kpi__icon--warning {background:rgba(245,158,11,0.12);color:#d97706;}
.sa-kpi__icon--danger  {background:rgba(239,68,68,0.12);color:#dc2626;}
.sa-kpi__value{font-size:18px;font-weight:900;color:var(--text-primary);line-height:1.1;}
.sa-kpi__label{font-size:11px;color:var(--text-tertiary);margin-top:2px;}
/* Tabs nav */
.sa-tabs{
  display:flex;gap:6px;
  border-bottom:2px solid var(--border);
  padding:0 4px;
  overflow-x:auto;
}
.sa-tabs__tab{
  display:inline-flex;align-items:center;gap:8px;
  padding:12px 18px;
  background:none;border:0;
  font-size:14px;font-weight:700;
  color:var(--text-secondary);
  cursor:pointer;
  border-bottom:2px solid transparent;
  margin-bottom:-2px;
  transition:color 140ms, border-color 140ms;
  white-space:nowrap;
}
.sa-tabs__tab:hover{color:var(--text-primary);}
.sa-tabs__tab.is-active{color:var(--accent);border-bottom-color:var(--accent);}
.sa-tabs__badge{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:20px;height:20px;padding:0 6px;
  background:var(--danger);color:#fff;
  font-size:11px;font-weight:800;
  border-radius:999px;
}
/* Pricing admin tab */
.sa-pricing{display:flex;flex-direction:column;gap:16px;}
.sa-pricing-loading{
  display:flex;align-items:center;justify-content:center;gap:10px;
  padding:48px;color:var(--text-tertiary);
}
.sa-pricing-migration-banner{
  display:flex;align-items:flex-start;gap:14px;
  padding:18px;
  background:rgba(245,158,11,0.08);
  border:1px solid rgba(245,158,11,0.3);
  border-radius:14px;
  color:#92400e;
}
.sa-pricing-migration-banner strong{display:block;margin-bottom:6px;font-size:15px;}
.sa-pricing-migration-banner p{margin:0;font-size:13px;line-height:1.7;}
.sa-pricing-migration-banner code{
  background:rgba(0,0,0,.06);padding:2px 6px;border-radius:4px;
  font-family:ui-monospace,monospace;font-size:12px;
}
.sa-pricing-trial{
  display:flex;flex-direction:column;gap:14px;
  padding:18px;
  background:linear-gradient(135deg, rgba(14,165,183,0.05), rgba(59,130,246,0.05));
}
.sa-pricing-trial__head{display:flex;align-items:flex-start;gap:14px;}
.sa-pricing-trial__icon{
  width:44px;height:44px;border-radius:12px;
  background:rgba(14,165,183,0.15);color:#0a8a99;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.sa-pricing-trial__title{font-weight:900;font-size:16px;color:var(--text-primary);}
.sa-pricing-trial__hint{font-size:12px;color:var(--text-secondary);margin-top:3px;line-height:1.6;}
.sa-pricing-trial__row{
  display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;
}
.sa-pricing-trial__row .sa-pricing-field{flex:0 0 200px;}
.sa-pricing-section{padding:18px;display:flex;flex-direction:column;gap:14px;}
.sa-pricing-section__head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:12px;
}
.sa-pricing-section__title{
  display:flex;align-items:center;gap:8px;
  font-size:17px;font-weight:900;color:var(--text-primary);
  margin:0;
}
.sa-pricing-section__hint{
  font-size:12px;color:var(--text-secondary);
  margin:4px 0 0;line-height:1.6;
}
.sa-pricing-empty{
  padding:24px;text-align:center;color:var(--text-tertiary);
  background:var(--bg-subtle);border-radius:12px;
}
/* Bank rails editor (Wave 3 / ADR-108) */
.sa-rails{display:flex;flex-direction:column;gap:14px;}
.sa-rails-row{
  border:1px solid var(--border);border-radius:12px;
  padding:14px;background:var(--bg-subtle);
  display:flex;flex-direction:column;gap:12px;
}
.sa-rails-row-head{
  display:grid;grid-template-columns:1fr 2fr auto;gap:10px;align-items:end;
}
@media (max-width:640px){.sa-rails-row-head{grid-template-columns:1fr;}}
.sa-rails-numbers{
  display:flex;flex-direction:column;gap:8px;
  padding-top:10px;border-top:1px dashed var(--border);
}
.sa-rails-number-row{display:flex;align-items:center;gap:6px;}
.sa-rails-footer{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.sa-pricing-grid{
  display:grid;grid-template-columns:repeat(auto-fill, minmax(320px, 1fr));
  gap:14px;
}
.sa-pricing-card{
  display:flex;flex-direction:column;gap:14px;
  padding:16px;
  background:var(--bg-card);
  border:1.5px solid var(--border);
  border-radius:14px;
  transition:border-color 160ms, transform 160ms, box-shadow 160ms;
}
.sa-pricing-card:hover{border-color:var(--accent-soft);}
.sa-pricing-card.has-changes{
  border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(14,165,183,0.08);
}
.sa-pricing-card.is-inactive{
  opacity:0.55;
  background:var(--bg-subtle);
}
.sa-pricing-card__head{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
}
.sa-pricing-card__title-row{
  display:flex;align-items:center;gap:8px;flex:1;min-width:0;
}
.sa-pricing-card__code{
  font-family:ui-monospace,monospace;
  font-size:11px;font-weight:700;
  padding:3px 8px;
  background:var(--bg-subtle);color:var(--text-tertiary);
  border-radius:6px;
  flex-shrink:0;
}
.sa-pricing-card__name-input{
  flex:1;
  border:0;background:transparent;
  font-size:16px;font-weight:800;color:var(--text-primary);
  padding:4px 6px;border-radius:6px;
  min-width:0;
}
.sa-pricing-card__name-input:focus{outline:0;background:var(--bg-subtle);}
.sa-pricing-toggle{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 10px;border:0;background:transparent;
  font-size:11px;font-weight:700;cursor:pointer;
  border-radius:999px;
  transition:background 140ms;
}
.sa-pricing-toggle.is-on{color:#16a34a;}
.sa-pricing-toggle.is-off{color:var(--text-tertiary);}
.sa-pricing-toggle:hover{background:var(--bg-subtle);}
/* Migration 080: trial plan card visual distinction */
.sa-pricing-card.is-trial{border-color:var(--lp-accent,#6366f1);background:color-mix(in srgb,var(--lp-accent,#6366f1) 4%,var(--bg));}
.sa-pricing-trial-badge{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;color:var(--lp-accent,#6366f1);background:color-mix(in srgb,var(--lp-accent,#6366f1) 12%,transparent);padding:4px 10px;border-radius:999px;white-space:nowrap;}
.sa-pricing-card__grid{
  display:grid;grid-template-columns:repeat(3, 1fr);gap:10px;
}
.sa-pricing-card__grid--pack{grid-template-columns:repeat(2, 1fr);}
.sa-pricing-field{display:flex;flex-direction:column;gap:5px;}
.sa-pricing-field__label{
  font-size:11px;font-weight:700;color:var(--text-secondary);
}
.sa-pricing-features{
  padding:12px;background:var(--bg-subtle);border-radius:10px;
}
.sa-pricing-features__label{
  font-size:11px;font-weight:700;color:var(--text-secondary);margin-bottom:8px;
}
.sa-pricing-feature{
  display:flex;align-items:center;gap:8px;
  padding:5px 0;font-size:13px;color:var(--text-primary);
  cursor:pointer;
}
.sa-pricing-feature input{cursor:pointer;}
.sa-pricing-card__actions{
  display:flex;gap:8px;
}
/* ADR-088: Clinic quick-actions card + plan-picker / credit-grant modals */
.sa-clinic-actions{
  padding:18px;
  background:linear-gradient(135deg, rgba(14,165,183,0.04), rgba(34,197,94,0.04));
  display:flex;flex-direction:column;gap:12px;
}
.sa-clinic-actions__head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;}
.sa-clinic-actions__title{
  display:flex;align-items:center;gap:8px;
  font-size:15px;font-weight:900;color:var(--text-primary);margin:0;
}
.sa-clinic-actions__hint{
  font-size:12px;color:var(--text-secondary);
  margin:4px 0 0;line-height:1.7;
}
.sa-clinic-actions__link{
  background:none;border:0;color:var(--accent);
  font-weight:700;font-size:12px;cursor:pointer;
  padding:0 4px;text-decoration:underline;
}
.sa-clinic-actions__link:hover{color:var(--accent-dark, var(--accent));}
.sa-clinic-actions__buttons{display:flex;gap:10px;flex-wrap:wrap;}
.sa-modal-backdrop{
  position:fixed;inset:0;z-index:60;
  background:rgba(0,0,0,.55);
  display:grid;place-items:center;padding:20px;
}
.sa-modal{
  background:var(--bg-card);
  border-radius:var(--radius-lg, 16px);
  padding:22px;
  max-width:min(520px, 96vw);
  max-height:90vh;overflow:auto;
  display:flex;flex-direction:column;gap:14px;
  box-shadow:0 24px 48px rgba(0,0,0,.32);
}
.sa-modal__head{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  font-size:16px;
}
.sa-modal__hint{
  font-size:13px;color:var(--text-secondary);
  margin:0;line-height:1.7;
}
.sa-modal__form{display:flex;flex-direction:column;gap:12px;}
.sa-modal__actions{display:flex;gap:10px;flex-wrap:wrap;}
.sa-modal__actions .btn{flex:1 1 auto;justify-content:center;}
.sa-plan-picker{display:flex;flex-direction:column;gap:8px;}
.sa-plan-picker__option{
  display:flex;align-items:center;gap:12px;
  padding:12px 14px;border:1.5px solid var(--border);border-radius:10px;
  cursor:pointer;transition:border-color 140ms, background 140ms;
}
.sa-plan-picker__option:hover{border-color:var(--accent-soft);}
.sa-plan-picker__option.is-selected{
  border-color:var(--accent);
  background:rgba(14,165,183,0.06);
}
.sa-plan-picker__option input[type="radio"]{flex-shrink:0;cursor:pointer;}
.sa-plan-picker__name{font-weight:800;font-size:14px;color:var(--text-primary);}
.sa-plan-picker__meta{font-size:12px;color:var(--text-secondary);margin-top:3px;}
/* ADR-089 (B-G26): credit ledger view */
.sa-ledger{padding:18px;display:flex;flex-direction:column;gap:12px;}
.sa-ledger__head{display:flex;align-items:flex-start;justify-content:space-between;}
.sa-ledger__title{
  display:flex;align-items:center;gap:8px;
  font-size:15px;font-weight:900;margin:0;
}
.sa-ledger__hint{
  font-size:12px;color:var(--text-secondary);margin:4px 0 0;line-height:1.6;
}
.sa-ledger__empty{
  padding:18px;text-align:center;color:var(--text-tertiary);
  background:var(--bg-subtle);border-radius:10px;
}
.sa-ledger__list{
  display:flex;flex-direction:column;gap:6px;
  max-height:420px;overflow:auto;
}
.sa-ledger__row{
  display:grid;
  grid-template-columns:auto 1fr auto auto;
  gap:10px;align-items:center;
  padding:10px 12px;
  border:1px solid var(--border);
  border-radius:8px;
  background:var(--bg-card);
  font-size:13px;
}
.sa-ledger__row.is-debit{background:rgba(239,68,68,0.04);}
.sa-ledger__row.is-credit{background:rgba(34,197,94,0.04);}
.sa-ledger__amount{font-weight:800;min-width:80px;}
.sa-ledger__row.is-debit .sa-ledger__amount{color:#dc2626;}
.sa-ledger__row.is-credit .sa-ledger__amount{color:#16a34a;}
.sa-ledger__meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0;}
.sa-ledger__chip{
  font-size:10px;padding:2px 7px;border-radius:999px;font-weight:700;
}
.sa-ledger__chip.is-monthly{background:rgba(14,165,183,0.12);color:#0a8a99;}
.sa-ledger__chip.is-bonus{background:rgba(34,197,94,0.12);color:#16a34a;}
.sa-ledger__chip.is-mixed{background:rgba(245,158,11,0.12);color:#d97706;}
.sa-ledger__source{
  font-family:ui-monospace,monospace;font-size:11px;color:var(--text-tertiary);
}
.sa-ledger__ref{font-size:11px;color:var(--text-secondary);}
.sa-ledger__balance{
  font-size:11px;color:var(--text-tertiary);
  font-family:ui-monospace,monospace;white-space:nowrap;
}
.sa-ledger__time{
  font-size:11px;color:var(--text-tertiary);white-space:nowrap;
}
@media (max-width: 768px){
  .sa-ledger__row{grid-template-columns:1fr;gap:4px;}
  .sa-ledger__balance,.sa-ledger__time{font-size:10px;}
}
/* Responsive */
@media (max-width: 1200px){
  .sa-kpis{grid-template-columns:repeat(3, 1fr);}
}
@media (max-width: 768px){
  .sa-kpis{grid-template-columns:repeat(2, 1fr);gap:8px;}
  .sa-kpi{padding:10px 12px;}
  .sa-kpi__icon{width:32px;height:32px;}
  .sa-kpi__value{font-size:15px;}
  .sa-tabs__tab{padding:10px 12px;font-size:13px;}
  .sa-pricing-card__grid{grid-template-columns:1fr 1fr;}
  .sa-pricing-grid{grid-template-columns:1fr;}
  .sa-clinic-actions__buttons .btn{flex:1 1 100%;}
}
.sa-receipt-reject__hint{
  font-size:13px;color:var(--text-secondary);line-height:1.7;margin:0;
}
.sa-receipt-reject__actions{
  display:flex;gap:10px;flex-wrap:wrap;margin-top:4px;
}
.sa-receipt-reject__actions .btn{flex:1 1 auto;justify-content:center;}
@media (max-width: 768px) {
  .sa-receipt-row__head{flex-direction:column;align-items:flex-start;gap:6px;}
  .sa-receipt-row__amount{font-size:16px;}
  .mk-upgrade__order-summary{flex-direction:column;align-items:flex-start;gap:4px;}
}
/* W3 (ADR-077) — Back-to-landing pill on the login portal */
.portal-back-link{
  position:fixed;top:18px;right:18px;z-index:30;
  display:inline-flex;align-items:center;gap:6px;
  padding:8px 14px;border-radius:999px;
  background:var(--bg-card);
  border:1px solid var(--border);
  color:var(--text-secondary);
  font-size:13px;font-weight:700;cursor:pointer;
  box-shadow:0 4px 12px rgba(0,0,0,.06);
  transition:all 160ms;
}
.portal-back-link:hover{
  background:var(--accent);color:#fff;border-color:var(--accent);
  transform:translateY(var(--lift-1));
}
/* ───── Tablet + phone responsive ───── */
@media (max-width: 1024px) {
  .lp-hero-inner{grid-template-columns:1fr;gap:40px;text-align:center;}
  .lp-hero-copy{text-align:center;}
  .lp-hero-sub{margin-left:auto;margin-right:auto;}
  .lp-hero-actions,
  .lp-hero-trust{justify-content:center;}
  .lp-hero-visual{max-width:560px;margin:0 auto;}
  .lp-nav-links{display:none;}
  .lp-how-grid{grid-template-columns:1fr;gap:32px;}
  .lp-how-grid::before{display:none;}
  .lp-why-grid{grid-template-columns:1fr;}
  .lp-footer-inner{grid-template-columns:1fr 1fr;gap:32px;}
  .lp-footer-col--brand{grid-column:1 / -1;}
}
@media (max-width: 768px) {
  .lp-hero{padding:60px 18px 70px;}
  .lp-section{padding:64px 18px;}
  .lp-section-header{margin-bottom:40px;}
  .lp-nav-inner{padding:12px 16px;}
  .lp-nav-login{display:none;}
  .lp-hero-actions{flex-direction:column;align-items:stretch;width:100%;}
  .lp-btn-primary,.lp-btn-outline{justify-content:center;}
  .lp-stats-section{margin-top:-30px;padding:0 14px;}
  .lp-stats-grid{grid-template-columns:repeat(2, 1fr);padding:18px;}
  .lp-stat{border-left:none;border-bottom:1px solid var(--border-subtle, var(--border));padding:14px 8px;}
  .lp-stat:nth-child(2n){border-left:1px solid var(--border-subtle, var(--border));}
  .lp-stat:nth-last-child(-n+2){border-bottom:none;}
  .lp-stat-value{font-size:26px;}
  .lp-plan-card.is-highlighted{transform:none;}
  .lp-plan-card.is-highlighted:hover{transform:translateY(var(--lift-2));}
  .lp-cta-card{padding:48px 22px;}
  .lp-mock-float--chart{display:none;}
  .lp-mock-float--credit{right:0;bottom:-8px;font-size:11px;}
  .lp-footer-inner{grid-template-columns:1fr;gap:24px;text-align:start;}
  .lp-footer-col--brand{grid-column:auto;}
  .portal-back-link{top:12px;right:12px;font-size:12px;padding:6px 12px;}
}
@media (max-width: 480px) {
  .lp-stats-grid{grid-template-columns:1fr;}
  .lp-stat{border-left:none;border-bottom:1px solid var(--border-subtle, var(--border));}
  .lp-stat:nth-child(2n){border-left:none;}
  .lp-stat:last-child{border-bottom:none;}
}
/* ============================================================
   V-Reception/W1 — Premium kanban polish + sub-states
   ============================================================
   Goals:
   • Full-width kanban (no Schedule panel right sibling anymore).
   • WhatsApp pre-confirm card treatment (green wash + pulse).
   • Waiting for بنج / أشعة card treatment (orange wash + pulse).
   • Secondary actions revealed on hover (primary always visible).
   • Smoother stage colors at the column header level.
   ============================================================ */
/* Full-width kanban: 5 equal columns share the row.
   The base .kanban-board (line ~1670) sets grid-template-columns to
   repeat(5, 1fr) implicitly via auto-fit; we lock the constraint
   explicitly here for the new Reception layout. */
.kanban-board.kanban-full-width {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.kanban-board.kanban-full-width .kanban-col {
  max-width: none;
  min-width: 0;
}
.kanban-board.kanban-full-width .kanban-cards-stack {
  min-height: 240px;
}
/* Column header — premium gradient stripe per stage, picked up via
   data-stage attribute. The currentColor (set inline by the stage
   color) drives the ::before stripe on .kanban-col-hdr. */
.kanban-col[data-stage="pending"]     .kanban-col-hdr { color: var(--warning); }
.kanban-col[data-stage="confirmed"]   .kanban-col-hdr { color: var(--info); }
.kanban-col[data-stage="in-progress"] .kanban-col-hdr { color: var(--accent); }
.kanban-col[data-stage="done"]        .kanban-col-hdr { color: var(--success); }
.kanban-col[data-stage="cancelled"]   .kanban-col-hdr { color: var(--danger); }
/* Card hover lift — slightly stronger than base for premium feel.
   Uses the --lift-2 token so the U-10/4 smoke check (translateY(-Npx)
   limited to non-lift sites) stays at 2 occurrences. */
.kanban-card {
  position: relative;
  border-radius: var(--radius);
  background: var(--bg-elevated);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.kanban-card:hover {
  transform: translateY(var(--lift-2));
  box-shadow:
    0 6px 16px rgba(0, 0, 0, 0.08),
    0 2px 4px rgba(0, 0, 0, 0.04);
}
/* Primary action row — always visible. */
.kanban-card-primary-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}
/* Secondary action row — hidden until hover, then fades in.
   On touch devices (hover: none) we keep them always-visible so
   tap-only users can reach the actions. */
.kanban-card-secondary-row {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed color-mix(in srgb, var(--border) 80%, transparent);
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transform: translateY(-4px);
  transition:
    opacity var(--duration-base) var(--ease-smooth),
    max-height var(--duration-base) var(--ease-smooth),
    transform var(--duration-base) var(--ease-smooth);
  pointer-events: none;
}
.kanban-card:hover .kanban-card-secondary-row,
.kanban-card:focus-within .kanban-card-secondary-row {
  opacity: 1;
  max-height: 40px;
  transform: translateY(0);
  pointer-events: auto;
}
@media (hover: none) {
  .kanban-card-secondary-row {
    opacity: 1;
    max-height: 40px;
    transform: none;
    pointer-events: auto;
  }
}
/* ── WhatsApp pre-confirmed: green wash + pulse halo ─────────────── */
.kanban-card.wa-pre-confirmed {
  background:
    linear-gradient(
      135deg,
      color-mix(in srgb, var(--success) 10%, var(--bg-elevated)) 0%,
      color-mix(in srgb, var(--success) 4%, var(--bg-elevated)) 100%
    );
  border-color: color-mix(in srgb, var(--success) 35%, var(--border));
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--success) 20%, transparent),
    0 2px 6px color-mix(in srgb, var(--success) 12%, transparent);
  animation: wa-pre-confirm-pulse 2.6s ease-in-out infinite;
}
@keyframes wa-pre-confirm-pulse {
  0%, 100% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--success) 20%, transparent), 0 2px 6px color-mix(in srgb, var(--success) 12%, transparent); }
  50%      { box-shadow: 0 0 0 1px color-mix(in srgb, var(--success) 45%, transparent), 0 4px 14px color-mix(in srgb, var(--success) 22%, transparent); }
}
/* Persistent badge for WA pre-confirmed (survives the 8s recentAction window) */
.wa-confirm-badge.persistent {
  background: color-mix(in srgb, var(--success) 18%, var(--bg-elevated));
  color: var(--success);
  border: 1px solid color-mix(in srgb, var(--success) 40%, transparent);
}
/* ── Waiting for بنج / أشعة: orange wash + pulse ─────────────────── */
.kanban-card.waiting-extra {
  background:
    linear-gradient(
      135deg,
      color-mix(in srgb, #ea580c 12%, var(--bg-elevated)) 0%,
      color-mix(in srgb, #ea580c 4%, var(--bg-elevated)) 100%
    );
  border-color: color-mix(in srgb, #ea580c 38%, var(--border));
  box-shadow:
    0 0 0 1px color-mix(in srgb, #ea580c 22%, transparent),
    0 2px 6px color-mix(in srgb, #ea580c 14%, transparent);
  animation: waiting-pulse 2.4s ease-in-out infinite;
}
@keyframes waiting-pulse {
  0%, 100% { box-shadow: 0 0 0 1px color-mix(in srgb, #ea580c 22%, transparent), 0 2px 6px color-mix(in srgb, #ea580c 14%, transparent); }
  50%      { box-shadow: 0 0 0 1px color-mix(in srgb, #ea580c 48%, transparent), 0 4px 14px color-mix(in srgb, #ea580c 26%, transparent); }
}
/* Waiting badge — orange chip sitting on top of the card. */
.kanban-waiting-badge {
  position: absolute;
  top: 8px;
  insetInlineEnd: 10px;
  inset-inline-end: 10px;
  background: #ea580c;
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  padding: 3px 8px;
  border-radius: 999px;
  box-shadow: 0 2px 6px color-mix(in srgb, #ea580c 35%, transparent);
  z-index: 2;
  animation: waiting-badge-bob 2.4s ease-in-out infinite;
}
@keyframes waiting-badge-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-5px); }
}
/* Reduce motion — respect the system preference. */
@media (prefers-reduced-motion: reduce) {
  .kanban-card.wa-pre-confirmed,
  .kanban-card.waiting-extra,
  .kanban-waiting-badge {
    animation: none;
  }
}
/* Stage-column max-width override for the full-width layout.
   The base rule (line ~1681) caps columns at 220px — that was right
   for the 60% split layout but limits the new full-width kanban. */
.kanban-board.kanban-full-width .kanban-col {
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--bg-subtle) 60%, var(--bg-elevated));
}
/* ADR-139 A4 (2026-05-28): AppointmentSideDrawer migrated to
   ResponsiveModal. The bespoke .side-drawer-* namespace (backdrop,
   slide-in panel, custom header/body/footer rhythm, RTL slide
   keyframes) is fully retired - the modal inherits the premium
   glass shell + Wave 4 action footer from the shared primitive. */
/* ============================================================
   V-Appointments/W2 — Day-view drag-drop visual feedback
   ============================================================
   • .appt-block.is-draggable        — grab cursor on hover
   • .appt-block.is-dragging         — dim + slight scale-down
   • .appt-slot.drop-target          — accent dashed ring (valid drop)
   • .appt-slot.drop-forbidden       — danger dashed ring (occupied)
   ============================================================ */
.appt-block.is-draggable {
  user-select: none;
}
.appt-block.is-dragging {
  cursor: grabbing !important;
  filter: saturate(0.85);
}
.appt-slot {
  transition: background var(--duration-fast) var(--ease-smooth), box-shadow var(--duration-fast) var(--ease-smooth);
}
.appt-slot.drop-target {
  background: color-mix(in srgb, var(--accent) 8%, transparent) !important;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
  animation: appt-slot-drop-pulse 1.4s ease-in-out infinite;
}
.appt-slot.drop-forbidden {
  background: color-mix(in srgb, var(--danger) 6%, transparent) !important;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--danger) 45%, transparent);
  cursor: not-allowed !important;
}
@keyframes appt-slot-drop-pulse {
  0%, 100% { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); }
  50%      { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 75%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .appt-slot.drop-target { animation: none; }
}
/* Touch devices: hide drag affordance (HTML5 dnd is desktop-only here). */
@media (hover: none) {
  .appt-block.is-draggable { cursor: pointer; }
}
/* ============================================================
   V-Phase2 — Mobile Polish (ADR-132)
   ============================================================
   Owner audit on 2026-05-27 with Preview MCP screenshots
   (viewport 375x812) flagged six issues across the Reception +
   Appointments screens; A and B are shared chrome and affect
   every screen via the shell siblings, so the fix belongs here
   in the global stylesheet rather than per-screen.

   Issues addressed:
   A. TopBar at 197px on phones (3 rows). The 132px-min clock
      div was the single biggest contributor — it forced the
      .topbar-actions row to wrap once on the clock + WhatsApp
      icons, then again when the avatar wouldn't fit.
   B. Hero card duplicates topbar info (clock + greeting + clinic
      name) and adds ~250px more chrome. Compress on phones.
   C. Kanban broken: .kanban-board.kanban-full-width (specificity
      0,2,0) overrode Wave 5b's grid-template-columns: 1fr rule
      at <=480px (specificity 0,1,1), so the 5-col 180px-each
      horizontal scroll layout shipped to phones unchanged.
   D. Day calendar enforced Math.max(600, ...) minWidth even at
      1 room, clipping "الغرفة" to "الغر" on a 375px viewport.
      Fixed in appointments.jsx; this block handles font/cell
      compression so the room label has breathing room.
   E. KPI strip on Reception used .l-grid--sm (auto-fit, 10rem
      min) which resolved to 1 column on phones — 5 tiles tall
      ~400px of chrome before the kanban. New 2x2+1 layout.
   F. Week view 7-col grid: Wave 5c's stack rule existed but
      inline grid-template-columns wasn't being beaten reliably.
      Belt-and-suspenders enforcement here.

   Class hooks added to JSX in this same commit:
     topbar-clock     — app/shell/topbar.jsx
     topbar-subtitle  — app/shell/topbar.jsx
     appt-day-grid    — app/screens/appointments.jsx
     appt-day-scroll  — app/screens/appointments.jsx
     reception-kpis   — app/screens/reception.jsx
*/
@media (max-width: 768px) {
  /* A — TopBar: single-row chrome.
     The earlier @media (max-width: 768px) rule at line ~3202
     applies flex-wrap: wrap + sets .search and .topbar-actions
     to width: 100% — that produces the 3-row pile. Override
     here: nowrap, hide search (cmdk-launch icon already gives
     a search affordance), hide clock (every hero owns a live
     clock pill), hide subtitle (tabs strip + hero already
     restate any context the user needs on a phone). */
  .topbar {
    flex-wrap: nowrap;
    gap: 6px;
    padding: 10px 14px;
  }
  .topbar > .search { display: none !important; }
  .topbar > .topbar-actions {
    order: 2;
    width: auto;
    flex-wrap: nowrap;
    flex-shrink: 0;
    margin-inline-start: auto;
    gap: 4px;
    justify-content: flex-end;
  }
  /* !important on hide rules — the .topbar-clock div is rendered with
     inline style="display: grid" by Topbar.jsx (the JSX inline keeps
     the grid-based clock-layout self-contained); inline styles beat
     selector-only rules so the hide needs !important to win. */
  .topbar-actions > .topbar-clock { display: none !important; }
  .topbar-title-block .topbar-subtitle { display: none !important; }
}
@media (max-width: 480px) {
  /* B — Hero card: compress aggressively. The greeting line
     ("مساء الخير 👋") is small-talk that the user reads once at
     the start of a shift; on a phone where every pixel is taxed
     it's the first thing to cut. The hero clock duplicates the
     date pill — same purpose, less precision — so it goes too. */
  .dash-hero .dash-hero-greet { display: none; }
  .dash-hero .reception-hero-clock { display: none; }
  .dash-hero .dash-hero-title { font-size: 18px; }
  .dash-hero { padding: 14px 14px; border-radius: 14px; }

  /* C — Kanban: shared rules for every mobile breakpoint. The
     specificity fix (.kanban-board.kanban-full-width beats line
     ~12959) lives here; the per-breakpoint grid templates live in
     the V-Phase2 Wave 2 block below. !important is required for
     the grid-template-columns because the existing
     `.kanban-board.kanban-full-width` rule (specificity 0,2,0)
     would otherwise lock the column count to 5. */
  .kanban-board.kanban-full-width .kanban-col {
    min-width: 0;
  }
  /* Sticky stage header so the user keeps context while scrolling
     a long column of cards. Applies at every mobile breakpoint
     (chips mode, 2-col, 3-col). */
  .kanban-board.kanban-full-width .kanban-col-hdr {
    position: sticky;
    top: 0;
    z-index: 2;
  }

  /* D — Day calendar: with the JSX-side fix removing the 600
     minWidth floor for one-room layouts, the grid fits in 343px
     content width naturally. This rule trims the time column to
     60px so even ultra-narrow viewports have room for room
     labels. */
  .appt-day-grid {
    grid-template-columns: 60px 1fr !important;
  }
  .appt-day-grid > div {
    font-size: 12px;
  }

  /* E — Reception KPIs: 2 columns; the 5th tile spans the row
     via :last-child:nth-child(odd) so the layout stays balanced
     (2 + 2 + 1 wide rather than 2 + 2 + 1 narrow). */
  .reception-kpis.l-grid {
    grid-template-columns: 1fr 1fr !important;
    gap: 8px;
  }
  .reception-kpis.l-grid > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /* F — Week view defensive stack. Wave 5c had the right rule;
     this is belt-and-suspenders. Each day card in the stack
     gets a left-aligned header so the user can scan the stream
     without losing day context. */
  .appt-week-grid {
    grid-template-columns: 1fr !important;
  }
  .appt-week-grid > div {
    border-bottom: 1px solid var(--border);
  }
  .appt-week-grid > div > :first-child {
    text-align: start;
    padding: 12px 14px !important;
  }
}
/* ============================================================
   V-Phase2 Wave 2 — Adaptive kanban (ADR-132 follow-up)
   ============================================================
   Owner picked Option D (adaptive layout per breakpoint) after the
   single-column stack on Wave 1 felt too tall — ~1300px of scroll
   to walk the full 5 stages, with each empty stage eating a 250px
   card vertically. New behavior:

     <=390px  chips filter + 1 stage at a time (full-width cards)
     391-768  2 cols: محجوز+انتظار / طبيب+تمت / لم يحضر spans
     769-1023 3 cols: 3 active stages row 1 (span 2 each on a 6-fr
              grid) + 2 reference stages row 2 (span 3 each)
     >=1024   5 cols — current desktop, unchanged

   Default chip selection is "pending" (محجوز) because that's the
   most common entry point for receptionist workflow (new patient
   arrives, gets booked into pending, then walks in to confirmed).
   The chip strip is always rendered in JSX so the active state
   lives in one place; CSS hides it at >=391px since the parallel
   layouts make the chips redundant.

   Drag-drop:
     - At >=391px every column is visible, dnd works as before.
     - At <=390px only the active stage's cards are draggable;
       drop targets are extended to the chip buttons themselves
       so the receptionist can drag a card onto another stage's
       chip without first switching tabs (see onDrop in
       reception.jsx).
*/
/* Chip strip hidden by default (desktop + tablet + 2-col phones) */
.kanban-mobile-chips { display: none; }
@media (max-width: 390px) {
  /* Single column inside the grid; the chip strip occupies row 1,
     the active stage occupies row 2. Every non-active stage column
     gets display:none via the data-active-stage attribute selectors
     below. */
  .kanban-board.kanban-full-width {
    grid-template-columns: 1fr !important;
    overflow-x: visible !important;
    padding-bottom: 0 !important;
  }
  .kanban-mobile-chips {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 8px 4px;
    grid-column: 1 / -1;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .kanban-mobile-chips::-webkit-scrollbar { display: none; }
  .kanban-mobile-chip {
    flex-shrink: 0;
    scroll-snap-align: start;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-elevated);
    font-size: 12px;
    font-weight: 700;
    color: var(--text-secondary);
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    min-height: 36px;
  }
  .kanban-mobile-chip:hover { background: var(--bg-hover); }
  .kanban-mobile-chip:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
  .kanban-mobile-chip.active {
    background: color-mix(in srgb, var(--accent) 12%, var(--bg-elevated));
    border-color: var(--accent);
    color: var(--accent);
  }
  .kanban-mobile-chip-count {
    background: var(--bg-subtle);
    color: var(--text-tertiary);
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 800;
    min-width: 20px;
    text-align: center;
    line-height: 1.4;
  }
  .kanban-mobile-chip.active .kanban-mobile-chip-count {
    background: color-mix(in srgb, var(--accent) 20%, transparent);
    color: var(--accent);
  }
  /* Filter columns by data-active-stage on the board. Five explicit
     pairings (one per stage key) so the cascade stays readable; any
     unrecognized data-active-stage value falls back to showing every
     column (safe default). */
  .kanban-board.kanban-full-width[data-active-stage="pending"] > .kanban-col[data-stage="pending"],
  .kanban-board.kanban-full-width[data-active-stage="confirmed"] > .kanban-col[data-stage="confirmed"],
  .kanban-board.kanban-full-width[data-active-stage="in-progress"] > .kanban-col[data-stage="in-progress"],
  .kanban-board.kanban-full-width[data-active-stage="done"] > .kanban-col[data-stage="done"],
  .kanban-board.kanban-full-width[data-active-stage="cancelled"] > .kanban-col[data-stage="cancelled"] {
    display: flex;
    flex-direction: column;
  }
  .kanban-board.kanban-full-width[data-active-stage="pending"]     > .kanban-col[data-stage]:not([data-stage="pending"]),
  .kanban-board.kanban-full-width[data-active-stage="confirmed"]   > .kanban-col[data-stage]:not([data-stage="confirmed"]),
  .kanban-board.kanban-full-width[data-active-stage="in-progress"] > .kanban-col[data-stage]:not([data-stage="in-progress"]),
  .kanban-board.kanban-full-width[data-active-stage="done"]        > .kanban-col[data-stage]:not([data-stage="done"]),
  .kanban-board.kanban-full-width[data-active-stage="cancelled"]   > .kanban-col[data-stage]:not([data-stage="cancelled"]) {
    display: none;
  }
}
@media (max-width: 768px) and (min-width: 391px) {
  /* 2 cols: محجوز + في الانتظار on row 1, مع الطبيب + تمت on row 2,
     لم يحضر spans both columns on row 3. The grid-auto-rows let
     each pair size naturally to their tallest card stack. */
  .kanban-board.kanban-full-width {
    grid-template-columns: 1fr 1fr !important;
    overflow-x: visible !important;
    padding-bottom: 0 !important;
    gap: 10px;
  }
  .kanban-board.kanban-full-width > .kanban-col[data-stage="cancelled"] {
    grid-column: 1 / -1;
  }
  /* Cards inside the 2-col layout get tighter padding so the
     primary CTA stays readable at ~165px-wide cells (iPhone 14). */
  .kanban-board.kanban-full-width .kanban-card {
    padding: 12px !important;
  }
  .kanban-board.kanban-full-width .kanban-card-primary-row {
    flex-wrap: wrap;
  }
}
@media (max-width: 1023px) and (min-width: 769px) {
  /* 3 cols using a 6-fr base so the last row can split 3+3 cleanly:
       Row 1: محجوز(span 2) | في الانتظار(span 2) | مع الطبيب(span 2)
       Row 2: تمت(span 3) | لم يحضر(span 3)
     Mapping by data-stage keeps the ordering intentional (active
     stages on row 1, reference stages on row 2) so the receptionist
     sees the working set first. */
  .kanban-board.kanban-full-width {
    grid-template-columns: repeat(6, 1fr) !important;
    overflow-x: visible !important;
    padding-bottom: 0 !important;
    gap: 12px;
  }
  .kanban-board.kanban-full-width > .kanban-col[data-stage="pending"],
  .kanban-board.kanban-full-width > .kanban-col[data-stage="confirmed"],
  .kanban-board.kanban-full-width > .kanban-col[data-stage="in-progress"] {
    grid-column: span 2;
  }
  .kanban-board.kanban-full-width > .kanban-col[data-stage="done"],
  .kanban-board.kanban-full-width > .kanban-col[data-stage="cancelled"] {
    grid-column: span 3;
  }
}
/* ADR-143: route-level motion restraint.
   The old global page/card entrance animations made refresh and screen
   navigation feel like a second temporary screen was loading. Keep
   micro-interactions and modal animations, but make the main route body
   settle immediately once the shell is visible. */
.main-content > .fade-in,
.main-content .page-header {
  animation: none !important;
}
.main-content .page-content > .grid > .card,
.main-content .page-content > .grid > .card.kpi,
.main-content .page-content > .grid > .card.interactive,
.main-content .page-content > .grid > .card.feature,
.main-content .page-content > .grid > .card.section,
.main-content .page-content > .grid.cols-4 > div,
.main-content .page-content > div > .card,
.main-content .page-content > .grid > div[style*="borderInlineStart"],
.main-content .page-content > .grid > .card[style*="borderInlineStart"] {
  animation: none !important;
  animation-delay: 0ms !important;
}
/* ============================================
   Announcements Wave 1.5 (2026-05-31)
   ============================================
   Originally shipped a custom slide-in @keyframes for the
   announcements-drawer pattern. After owner feedback we switched
   to the ResponsiveModal primitive (centered modal on desktop,
   bottom-sheet on mobile) — the keyframes was retired because
   ResponsiveModal owns the animation lifecycle. Only the card
   hover rule below remains. */
.announcements-card:hover {
  background: var(--bg-hover) !important;
}
/* ============================================
   Announcements Wave 2 (2026-05-31) — premium polish
   ============================================ */
/* --- Topbar icon: severity-toned pulse halo --- */
.ann-icon-btn {
  position: relative;
}
.ann-icon-pulse {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  animation: annPulseGlow 2.4s ease-out infinite;
  z-index: 0;
}
.ann-icon-btn > svg,
.ann-icon-btn > .ann-icon-badge {
  position: relative;
  z-index: 1;
}
.ann-icon-pulse--info {
  background: radial-gradient(circle, color-mix(in srgb, var(--info, #3b82f6) 50%, transparent) 0%, transparent 65%);
}
.ann-icon-pulse--success {
  background: radial-gradient(circle, color-mix(in srgb, var(--success, #22c55e) 55%, transparent) 0%, transparent 65%);
}
.ann-icon-pulse--warning {
  background: radial-gradient(circle, color-mix(in srgb, var(--warning, #f59e0b) 55%, transparent) 0%, transparent 65%);
}
.ann-icon-pulse--danger {
  background: radial-gradient(circle, color-mix(in srgb, var(--danger, #ef4444) 60%, transparent) 0%, transparent 65%);
}
@keyframes annPulseGlow {
  0%   { opacity: 0;   transform: scale(0.85); }
  50%  { opacity: 0.85; transform: scale(1.25); }
  100% { opacity: 0;   transform: scale(1.45); }
}
/* Badge — fixed positioning + size for visual consistency with the
   ann-icon-pulse halo layering above. */
.ann-icon-badge {
  position: absolute;
  top: -3px;
  inset-inline-end: -3px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  background: var(--danger, #ef4444);
  color: #fff;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
  display: grid;
  place-items: center;
  box-shadow: 0 0 0 2px var(--bg, #fff);
}
/* --- Card severity tone stripe (4px inline-start bar) --- */
.announcements-card {
  position: relative;
}
.announcements-card::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--info, #3b82f6);
}
.announcements-card--success::before { background: var(--success, #22c55e); }
.announcements-card--info::before    { background: var(--info,    #3b82f6); }
.announcements-card--warning::before { background: var(--warning, #f59e0b); }
.announcements-card--danger::before  { background: var(--danger,  #ef4444); }
/* --- Inline media preview (image + video) --- */
.ann-media {
  width: 100%;
  border-radius: 12px;
  overflow: hidden;
  margin: 12px 0 4px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
}
.ann-media img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 320px;
  object-fit: cover;
}
.ann-media-video {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
}
.ann-media-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* --- Confetti shimmer on first-mount of a `feature` card --- */
.ann-confetti {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 18% 28%, color-mix(in srgb, var(--success, #22c55e) 50%, transparent) 0%, transparent 26%),
    radial-gradient(circle at 78% 68%, color-mix(in srgb, var(--success, #22c55e) 35%, transparent) 0%, transparent 28%),
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--success, #22c55e) 14%, transparent) 0%, transparent 60%);
  animation: annConfettiShimmer 700ms ease-out;
  opacity: 0;
  z-index: 0;
}
.announcements-card > * {
  position: relative;
  z-index: 1;
}
@keyframes annConfettiShimmer {
  0%   { opacity: 0; transform: scale(0.96); }
  45%  { opacity: 1; transform: scale(1.02); }
  100% { opacity: 0; transform: scale(1.06); }
}
/* --- Login splash — sparkle float --- */
@keyframes annSparkleFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}
/* --- Loading skeleton (panel) --- */
.announcements-panel__skeleton {
  display: grid;
  gap: 1px;
}
.ann-skeleton-card {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.ann-skeleton-line {
  height: 12px;
  background: linear-gradient(
    90deg,
    var(--border) 0%,
    var(--bg-subtle) 50%,
    var(--border) 100%
  );
  background-size: 200% 100%;
  animation: annSkeletonShimmer 1.6s ease-in-out infinite;
  border-radius: 6px;
  margin-bottom: 8px;
}
.ann-skeleton-line:last-child { margin-bottom: 0; }
@keyframes annSkeletonShimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}
/* --- Editor split-screen (form + live preview) --- */
.ann-editor-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 20px;
  align-items: start;
}
.ann-editor-preview {
  position: sticky;
  top: 12px;
  padding: 14px;
  background: var(--bg-subtle);
  border-radius: 12px;
  border: 1px solid var(--border);
  max-height: 70vh;
  overflow-y: auto;
}
.ann-editor-preview__label {
  font-size: 12px;
  font-weight: 800;
  color: var(--text-tertiary);
  margin-bottom: 10px;
  letter-spacing: 0.02em;
}
.ann-editor-preview__frame {
  background: var(--bg, #fff);
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
}
.ann-editor-preview__frame .announcements-card {
  border-bottom: 0;
}
/* Collapse to single column on tablets / phones — preview goes below the form. */
@media (max-width: 920px) {
  .ann-editor-split {
    grid-template-columns: 1fr;
  }
  .ann-editor-preview {
    position: static;
    max-height: none;
  }
}
/* ============================================
   Announcements Wave 2.1 (2026-05-31)
   Login splash redesign — hero preview with severity badge,
   title, body, and inline image/video.
   ============================================ */
.ann-login-modal__body {
  text-align: center;
  padding: 6px 4px 14px;
}
.ann-login-modal__sparkle {
  font-size: 36px;
  margin-bottom: 10px;
  animation: annSparkleFloat 2.2s ease-in-out infinite;
  line-height: 1;
}
.ann-login-modal__chip-row {
  display: flex;
  justify-content: center;
  margin-bottom: 10px;
}
.ann-login-modal__title {
  font-weight: 900;
  font-size: 20px;
  color: var(--text-primary);
  line-height: 1.3;
  margin-bottom: 10px;
}
.ann-login-modal__body-text {
  font-size: 13.5px;
  color: var(--text-secondary);
  line-height: 1.6;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-bottom: 12px;
  text-align: start;
  padding-inline: 6px;
}
.ann-login-modal__media {
  margin: 8px auto 0;
  max-width: 100%;
}
.ann-login-modal__media iframe,
.ann-login-modal__media img {
  display: block;
}
/* ============================================
   Announcements Wave 2.2 (2026-05-31)
   Live preview language toggle (AR / EN) inside the editor.
   ============================================ */
.ann-editor-preview__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}
.ann-editor-preview__lang-toggle {
  display: flex;
  align-items: center;
}
/* ============================================
   Announcements Wave 3 (2026-05-31)
   Analytics modal: KPI grid, per-plan bars, recent viewers.
   ============================================ */
.ann-anl-body {
  display: grid;
  gap: 18px;
}
.ann-anl-kpis {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
}
@media (max-width: 920px) {
  .ann-anl-kpis { grid-template-columns: repeat(2, 1fr); }
}
.ann-anl-kpi {
  padding: 12px;
  border-radius: 10px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  display: grid;
  gap: 4px;
  text-align: center;
}
.ann-anl-kpi__icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  margin: 0 auto 4px;
  background: var(--bg-elevated, #fff);
  color: var(--text-secondary);
}
.ann-anl-kpi__value {
  font-size: 22px;
  font-weight: 900;
  color: var(--text-primary);
  line-height: 1;
}
.ann-anl-kpi__label {
  font-size: 11px;
  color: var(--text-tertiary);
  font-weight: 600;
}
.ann-anl-kpi--accent  .ann-anl-kpi__icon { background: color-mix(in srgb, var(--accent, #0ea5b7) 15%, transparent); color: var(--accent, #0ea5b7); }
.ann-anl-kpi--success .ann-anl-kpi__icon { background: color-mix(in srgb, var(--success, #22c55e) 15%, transparent); color: var(--success, #22c55e); }
.ann-anl-kpi--info    .ann-anl-kpi__icon { background: color-mix(in srgb, var(--info, #3b82f6) 15%, transparent); color: var(--info, #3b82f6); }
.ann-anl-kpi--warning .ann-anl-kpi__icon { background: color-mix(in srgb, var(--warning, #f59e0b) 15%, transparent); color: var(--warning, #f59e0b); }
.ann-anl-kpi--danger  .ann-anl-kpi__icon { background: color-mix(in srgb, var(--danger, #ef4444) 15%, transparent); color: var(--danger, #ef4444); }
.ann-anl-section {
  padding: 14px;
  background: var(--bg-subtle);
  border-radius: 12px;
  border: 1px solid var(--border);
}
.ann-anl-section__title {
  font-weight: 800;
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 10px;
}
.ann-anl-bars { display: grid; gap: 12px; }
.ann-anl-bar { display: grid; gap: 6px; }
.ann-anl-bar__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}
.ann-anl-bar__track {
  background: var(--border);
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
}
.ann-anl-bar__fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent, #0ea5b7), color-mix(in srgb, var(--accent, #0ea5b7) 60%, transparent));
  border-radius: 999px;
  transition: width .35s ease;
}
.ann-anl-recent {
  display: grid;
  gap: 1px;
  background: var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.ann-anl-recent__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg, #fff);
  font-size: 13px;
}
/* ============================================================
   AI Assistant Wave 1 (2026-05-31)
   See AI_ASSISTANT_PLAN.md sec 3 (Layer 1 - Frontend Shell).
   ============================================================ */
/* ---- Floating ball ---- */
/* AI Wave 1 hotfix (2026-05-31): owner asked to move the ball to the
   opposite side (RTL bottom-LEFT) so it stops overlapping the avatar
   /clinic-name block at the bottom-right. inset-inline-end resolves
   to LEFT in RTL and RIGHT in LTR — natural for both directions.
   Desktop bumped from 56px to 64px for stronger presence; mobile
   stays at 48px below the media query. */
.ai-ball {
  position: fixed;
  bottom: 22px;
  inset-inline-end: 22px;
  z-index: 180;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 0;
  cursor: pointer;
  background: linear-gradient(135deg, var(--accent, #6c63ff), var(--accent-2, #ff6c63));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 30px rgba(108, 99, 255, 0.42), 0 4px 12px rgba(0, 0, 0, 0.12);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.ai-ball:hover {
  transform: translateY(-4px) scale(1.04);
  box-shadow: 0 16px 38px rgba(108, 99, 255, 0.55), 0 6px 18px rgba(0, 0, 0, 0.18);
}
.ai-ball:active { transform: translateY(0) scale(0.98); }
.ai-ball:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
.ai-ball__icon { display: flex; align-items: center; justify-content: center; }
.ai-ball__pulse {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(108, 99, 255, 0.42) 0%, transparent 70%);
  animation: ai-ball-pulse 2.4s ease-out infinite;
  pointer-events: none;
}
@keyframes ai-ball-pulse {
  0%   { transform: scale(1);   opacity: 0.55; }
  70%  { transform: scale(1.35); opacity: 0; }
  100% { transform: scale(1.35); opacity: 0; }
}
/* ---- First-visit nudge ---- */
.ai-ball-nudge {
  position: fixed;
  bottom: 98px;
  inset-inline-end: 22px;
  z-index: 181;
  max-width: 260px;
  padding: 12px 14px 12px 14px;
  background: var(--bg, #fff);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  animation: ai-nudge-in 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.ai-ball-nudge::after {
  content: '';
  position: absolute;
  bottom: -8px;
  inset-inline-end: 24px;
  width: 14px;
  height: 14px;
  background: var(--bg, #fff);
  border-right: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-bottom: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  transform: rotate(45deg);
}
.ai-ball-nudge__close {
  position: absolute;
  top: 6px;
  inset-inline-end: 6px;
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary, #999);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ai-ball-nudge__close:hover { background: var(--bg-subtle, rgba(0, 0, 0, 0.04)); }
.ai-ball-nudge__title { font-size: 13px; font-weight: 800; color: var(--text-primary, #111); padding-inline-end: 22px; }
.ai-ball-nudge__body  { font-size: 12px; color: var(--text-secondary, #666); margin-top: 4px; line-height: 1.5; }
@keyframes ai-nudge-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* ---- Panel ---- */
.ai-panel__body {
  display: flex;
  flex-direction: column;
  min-height: 420px;
  max-height: 70vh;
  gap: 0;
}
.ai-panel__thread {
  flex: 1;
  overflow-y: auto;
  padding: 8px 4px 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* ---- Message bubble ---- */
.ai-msg {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.ai-msg--user { flex-direction: row-reverse; }
.ai-msg__avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  color: var(--text-secondary, #666);
}
.ai-msg--assistant .ai-msg__avatar {
  background: linear-gradient(135deg, var(--accent, #6c63ff), var(--accent-2, #ff6c63));
  color: #fff;
}
.ai-msg--user .ai-msg__avatar {
  background: var(--accent, #6c63ff);
  color: #fff;
}
.ai-msg__body {
  max-width: 80%;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.ai-msg--user .ai-msg__body { align-items: flex-end; }
.ai-msg__role {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-tertiary, #888);
}
.ai-msg__content {
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  border-radius: 14px;
  padding: 9px 12px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-primary, #111);
  white-space: pre-wrap;
  word-break: break-word;
}
.ai-msg--user .ai-msg__content {
  background: var(--accent, #6c63ff);
  color: #fff;
}
.ai-msg--system {
  justify-content: center;
}
.ai-msg__system-text {
  font-size: 12px;
  color: var(--text-tertiary, #888);
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  padding: 6px 12px;
  border-radius: 12px;
  text-align: center;
}
.ai-msg--pending .ai-msg__content { background: transparent; padding: 0; }
.ai-msg__typing {
  display: flex;
  gap: 4px;
  padding: 10px 12px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  border-radius: 14px;
  width: fit-content;
}
.ai-msg__typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-tertiary, #999);
  animation: ai-typing 1.4s ease-in-out infinite;
}
.ai-msg__typing span:nth-child(2) { animation-delay: 0.2s; }
.ai-msg__typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes ai-typing {
  0%, 60%, 100% { transform: scale(0.85); opacity: 0.45; }
  30% { transform: scale(1.05); opacity: 1; }
}
/* ---- Composer ---- */
.ai-panel__composer {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 4px 6px;
  border-top: 1px solid var(--border, rgba(0, 0, 0, 0.08));
}
.ai-panel__input {
  flex: 1;
  border: 1px solid var(--border, rgba(0, 0, 0, 0.12));
  border-radius: 12px;
  padding: 10px 14px;
  font-size: 13.5px;
  background: var(--bg, #fff);
  color: var(--text-primary, #111);
  outline: none;
}
.ai-panel__input:focus { border-color: var(--accent, #6c63ff); }
.ai-panel__input:disabled { opacity: 0.6; cursor: not-allowed; }
.ai-panel__send {
  border: 0;
  background: var(--accent, #6c63ff);
  color: #fff;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.ai-panel__send:hover:not(:disabled) { transform: scale(1.05); }
.ai-panel__send:disabled { opacity: 0.4; cursor: not-allowed; }
/* ---- Footer ---- */
.ai-panel__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-top: 6px;
}
.ai-panel__footer-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--border, rgba(0, 0, 0, 0.1));
  border-radius: 10px;
  background: transparent;
  color: var(--text-secondary, #666);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
}
.ai-panel__footer-btn:hover:not(:disabled) { background: var(--bg-subtle, rgba(0, 0, 0, 0.04)); }
.ai-panel__footer-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.ai-panel__footer-btn--support {
  background: #25d366;
  color: #fff;
  border-color: #25d366;
}
.ai-panel__footer-btn--support:hover { background: #1ebe5c; }
/* ---- AI KB Tab (settings) ---- */
.ai-kb-tab__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.ai-kb-tab__title { font-size: 16px; font-weight: 900; margin: 0 0 4px; color: var(--text-primary, #111); }
.ai-kb-tab__sub   { font-size: 12.5px; color: var(--text-secondary, #666); margin: 0; line-height: 1.6; max-width: 540px; }
.ai-kb-tab__form {
  background: var(--bg-subtle, rgba(0, 0, 0, 0.03));
  border: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-radius: 14px;
  padding: 16px;
  margin-bottom: 16px;
}
.ai-kb-tab__form-row { display: grid; grid-template-columns: 1fr 200px; gap: 12px; margin-bottom: 12px; }
.ai-kb-tab__form label { display: flex; flex-direction: column; gap: 4px; }
.ai-kb-tab__label { font-size: 11px; font-weight: 800; color: var(--text-secondary, #666); }
.ai-kb-tab__form input,
.ai-kb-tab__form select,
.ai-kb-tab__form textarea {
  border: 1px solid var(--border, rgba(0, 0, 0, 0.12));
  border-radius: 10px;
  padding: 8px 12px;
  font-size: 13px;
  background: var(--bg, #fff);
  color: var(--text-primary, #111);
  font-family: inherit;
}
.ai-kb-tab__form textarea { resize: vertical; min-height: 80px; }
.ai-kb-tab__form-actions { display: flex; justify-content: flex-end; margin-top: 12px; }
.ai-kb-tab__error {
  background: rgba(220, 53, 69, 0.1);
  color: #b8001e;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 12.5px;
  margin: 8px 0 0;
}
.ai-kb-tab__list { display: flex; flex-direction: column; gap: 10px; }
.ai-kb-tab__empty {
  text-align: center;
  padding: 32px 16px;
  color: var(--text-tertiary, #888);
  font-size: 13px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.03));
  border-radius: 12px;
}
.ai-kb-tab__row {
  position: relative;
  background: var(--bg, #fff);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-radius: 12px;
  padding: 12px 14px;
}
.ai-kb-tab__row-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 6px; }
.ai-kb-tab__row-title { font-size: 13.5px; font-weight: 800; color: var(--text-primary, #111); }
.ai-kb-tab__row-cat {
  font-size: 10.5px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  color: var(--text-tertiary, #777);
  padding: 2px 8px;
  border-radius: 8px;
  font-weight: 700;
}
.ai-kb-tab__row-content { font-size: 13px; line-height: 1.7; color: var(--text-secondary, #555); white-space: pre-wrap; }
.ai-kb-tab__row-delete {
  position: absolute;
  top: 10px;
  inset-inline-end: 10px;
  border: 0;
  background: transparent;
  color: var(--text-tertiary, #999);
  width: 26px;
  height: 26px;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ai-kb-tab__row-delete:hover { background: rgba(220, 53, 69, 0.1); color: #b8001e; }
/* ============================================================
   AI Assistant Wave 2 - Inline action / tool cards inside chat.
   ============================================================ */
.ai-msg__cards {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
  width: 100%;
  max-width: 520px;
}
.ai-msg__error {
  margin-top: 6px;
  padding: 6px 10px;
  background: rgba(220, 53, 69, 0.1);
  color: #b8001e;
  border-radius: 8px;
  font-size: 12px;
}
.ai-card {
  background: var(--bg, #fff);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-radius: 12px;
  padding: 10px 12px;
  font-size: 13px;
  color: var(--text-primary, #111);
}
.ai-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.ai-card__title { font-size: 13px; font-weight: 800; color: var(--text-primary, #111); }
.ai-card__tool-name {
  font-size: 10.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  color: var(--text-tertiary, #888);
  padding: 2px 6px;
  border-radius: 6px;
}
.ai-card__empty {
  text-align: center;
  color: var(--text-tertiary, #888);
  padding: 10px;
  font-size: 12px;
}
/* Navigate card */
.ai-card--navigate {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, rgba(14, 165, 183, 0.10), rgba(34, 197, 94, 0.06));
  border-color: rgba(14, 165, 183, 0.35);
  cursor: pointer;
  font-weight: 700;
  width: fit-content;
  max-width: 100%;
  text-align: start;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.ai-card--navigate:hover {
  transform: translateY(-4px);
  box-shadow: 0 4px 12px rgba(14, 165, 183, 0.15);
}
.ai-card__navigate-label { color: var(--text-primary, #111); }
.ai-card__navigate-screen {
  font-size: 10.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(14, 165, 183, 0.12);
  color: #0a6c79;
  padding: 2px 6px;
  border-radius: 6px;
  margin-inline-start: auto;
}
/* Video card */
.ai-card--video { padding: 8px; }
.ai-card__video { width: 100%; }
.ai-card__video-title {
  font-size: 12.5px;
  font-weight: 700;
  margin-bottom: 6px;
  color: var(--text-primary, #111);
}
.ai-card__video-frame-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 8px;
  overflow: hidden;
  background: #000;
}
.ai-card__video-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.ai-card__video-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 20px 12px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.04));
  border-radius: 10px;
  color: var(--text-tertiary, #888);
  text-align: center;
}
.ai-card__video-placeholder-title { font-size: 13px; font-weight: 800; color: var(--text-secondary, #555); }
.ai-card__video-placeholder-sub   { font-size: 11.5px; }
/* KPI tiles */
.ai-card__kpis {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.ai-card__kpi-tile {
  background: var(--bg-subtle, rgba(0, 0, 0, 0.03));
  border-radius: 8px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ai-card__kpi-label  { font-size: 10.5px; color: var(--text-tertiary, #888); font-weight: 700; }
.ai-card__kpi-value  { font-size: 14px; font-weight: 800; color: var(--text-primary, #111); }
.ai-card__kpi-suffix { font-size: 10px; color: var(--text-tertiary, #999); }
/* Grouped bars */
.ai-card__bars { display: flex; flex-direction: column; gap: 6px; }
.ai-card__bar-row {
  display: grid;
  grid-template-columns: minmax(70px, 30%) 1fr auto;
  align-items: center;
  gap: 6px;
}
.ai-card__bar-label { font-size: 11.5px; color: var(--text-secondary, #555); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-card__bar-track {
  position: relative;
  height: 8px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.06));
  border-radius: 4px;
  overflow: hidden;
}
.ai-card__bar-fill {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  background: linear-gradient(90deg, #0ea5b7, #22c55e);
  border-radius: 4px;
  transition: width 0.3s ease;
}
.ai-card__bar-value { font-size: 11.5px; font-weight: 700; color: var(--text-primary, #111); min-width: 40px; text-align: end; }
/* Anomalies list */
.ai-card__anomalies { display: flex; flex-direction: column; gap: 6px; }
.ai-card__anomaly {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.03));
  border-inline-start: 3px solid var(--text-tertiary, #999);
}
.ai-card__anomaly--high   { border-inline-start-color: #dc3545; background: rgba(220, 53, 69, 0.05); }
.ai-card__anomaly--medium { border-inline-start-color: #f59e0b; background: rgba(245, 158, 11, 0.05); }
.ai-card__anomaly-kind  { font-size: 12px; font-weight: 700; color: var(--text-primary, #111); }
.ai-card__anomaly-meta  { display: flex; align-items: center; gap: 8px; }
.ai-card__anomaly-label { font-size: 11px; color: var(--text-tertiary, #888); }
.ai-card__anomaly-value { font-size: 12px; font-weight: 800; color: var(--text-secondary, #555); font-family: ui-monospace, monospace; }
/* Entity rows */
.ai-card__rows { display: flex; flex-direction: column; gap: 4px; }
.ai-card__row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 8px;
  background: var(--bg-subtle, rgba(0, 0, 0, 0.03));
}
.ai-card__row-title { flex: 1; font-size: 12.5px; font-weight: 700; color: var(--text-primary, #111); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-card__row-sub   { font-size: 11.5px; font-weight: 800; color: var(--text-secondary, #555); }
.ai-card__row-chip  { font-size: 10.5px; padding: 2px 6px; border-radius: 6px; background: rgba(0, 0, 0, 0.05); color: var(--text-tertiary, #888); }
/* Tool call working indicator */
.ai-card--working {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: rgba(14, 165, 183, 0.08);
  border-color: rgba(14, 165, 183, 0.2);
  color: var(--text-secondary, #555);
  font-size: 11.5px;
  font-weight: 700;
  width: fit-content;
}
.ai-card__working-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #0ea5b7;
  animation: ai-card-pulse 1.2s ease-in-out infinite;
}
@keyframes ai-card-pulse {
  0%, 100% { transform: scale(0.8); opacity: 0.4; }
  50%      { transform: scale(1.2); opacity: 1; }
}
/* Tool call error */
.ai-card--error {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(220, 53, 69, 0.07);
  border-color: rgba(220, 53, 69, 0.25);
  color: #b8001e;
  font-size: 11.5px;
  width: fit-content;
}
/* Mobile (<=768px) tweaks - keep ball smaller per owner ask. */
@media (max-width: 768px) {
  .ai-ball { width: 48px; height: 48px; bottom: 84px; inset-inline-end: 14px; }
  .ai-ball-nudge { bottom: 142px; inset-inline-end: 14px; max-width: 220px; }
  .ai-panel__body { min-height: 360px; max-height: 80vh; }
  .ai-msg__body { max-width: 88%; }
  .ai-kb-tab__form-row { grid-template-columns: 1fr; }
  .ai-card__kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ai-msg__cards { max-width: 100%; }
}
/* =================================================================
   AI Assistant Wave 3 - Behavior Watchers + Insights + Wins
   ----------------------------------------------------------------
   See AI_ASSISTANT_PLAN.md sec 10 Wave 3 (ADR-201 + ADR-202).
   Three view modes inside the panel (chat/insights/wins) + ball
   badge + observation banner + insight card + value prompt.
   ================================================================= */
/* Ball unread badge (Wave 3). */
.ai-ball__badge {
  position: absolute;
  top: 4px;
  inset-inline-end: 4px;
  background: var(--danger, #dc3545);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 5px;
  box-shadow: 0 0 0 2px var(--bg-base, #fff);
  line-height: 1;
}
.ai-ball__badge--dot {
  min-width: 12px;
  width: 12px;
  height: 12px;
  padding: 0;
}
/* Panel tabs (Wave 3). */
.ai-panel__tabs {
  display: flex;
  gap: 4px;
  padding: 8px 12px 4px;
  border-block-end: 1px solid var(--border-soft, rgba(0,0,0,0.06));
}
.ai-panel__tab {
  flex: 1;
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 7px 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted, #5d6b80);
  cursor: pointer;
  transition: background 120ms, color 120ms, border-color 120ms;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.ai-panel__tab:hover {
  background: var(--surface-hover, rgba(0,0,0,0.04));
  color: var(--text, #1d2331);
}
.ai-panel__tab.is-on {
  background: var(--brand-soft, rgba(8, 145, 178, 0.1));
  color: var(--brand, #0891b2);
  border-color: var(--brand-soft-border, rgba(8, 145, 178, 0.18));
}
.ai-panel__tab-badge {
  background: var(--danger, #dc3545);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 999px;
  line-height: 1.5;
}
/* Observation banner (C). */
.ai-observation-banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin: 10px 12px;
  padding: 10px 12px;
  background: var(--surface-info, rgba(8, 145, 178, 0.07));
  border: 1px solid var(--brand-soft-border, rgba(8, 145, 178, 0.18));
  border-radius: 12px;
}
.ai-observation-banner__icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--brand-soft, rgba(8, 145, 178, 0.12));
  color: var(--brand, #0891b2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.ai-observation-banner__body { flex: 1; min-width: 0; }
.ai-observation-banner__title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text, #1d2331);
  margin-block-end: 2px;
}
.ai-observation-banner__sub {
  font-size: 12px;
  color: var(--text-muted, #5d6b80);
  line-height: 1.5;
  margin-block-end: 6px;
}
.ai-observation-banner__bar {
  width: 100%;
  height: 4px;
  background: rgba(8, 145, 178, 0.12);
  border-radius: 999px;
  overflow: hidden;
}
.ai-observation-banner__bar-fill {
  height: 100%;
  background: var(--brand, #0891b2);
  border-radius: 999px;
  transition: width 240ms ease-out;
}
/* Insights view. */
.ai-insights-view {
  padding: 8px 12px 12px;
  overflow-y: auto;
  max-height: 60vh;
}
.ai-insights-view__filters {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-block-end: 10px;
}
.ai-insights-view__filter-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.ai-insights-chip {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted, #5d6b80);
  cursor: pointer;
  transition: background 120ms, color 120ms, border-color 120ms;
}
.ai-insights-chip:hover {
  background: var(--surface-hover, rgba(0,0,0,0.04));
  color: var(--text, #1d2331);
}
.ai-insights-chip.is-on {
  background: var(--brand, #0891b2);
  color: #fff;
  border-color: var(--brand, #0891b2);
}
.ai-insights-chip--status.is-on {
  background: var(--text, #1d2331);
  border-color: var(--text, #1d2331);
}
.ai-insights-view__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ai-insights-view__loading,
.ai-insights-view__empty {
  text-align: center;
  padding: 32px 12px;
  color: var(--text-muted, #5d6b80);
  font-size: 13px;
}
.ai-insights-view__empty-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 8px;
  border-radius: 50%;
  background: var(--success-soft, rgba(16, 185, 129, 0.12));
  color: var(--success, #10b981);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.ai-insights-view__empty-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text, #1d2331);
  margin-block-end: 4px;
}
/* Insight card. */
.ai-insight-card {
  position: relative;
  background: var(--surface, #fff);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 14px;
  padding: 12px 14px 10px;
  overflow: hidden;
  transition: transform 120ms, box-shadow 120ms;
}
.ai-insight-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 6px 16px rgba(15, 25, 50, 0.06);
}
.ai-insight-card.is-dismissed,
.ai-insight-card.is-acted {
  opacity: 0.62;
}
.ai-insight-card__stripe {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 3px;
  background: var(--brand, #0891b2);
}
.ai-insight-card--critical .ai-insight-card__stripe { background: var(--danger, #dc3545); }
.ai-insight-card--high .ai-insight-card__stripe     { background: var(--warning, #f59e0b); }
.ai-insight-card--medium .ai-insight-card__stripe   { background: var(--brand, #0891b2); }
.ai-insight-card--low .ai-insight-card__stripe      { background: var(--text-muted, #5d6b80); }
.ai-insight-card__head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-block-end: 6px;
  font-size: 11.5px;
}
.ai-insight-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border-radius: 6px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 10px;
}
.ai-insight-chip--critical { background: rgba(220, 53, 69, 0.12); color: #b8001e; }
.ai-insight-chip--high     { background: rgba(245, 158, 11, 0.14); color: #b35e00; }
.ai-insight-chip--medium   { background: rgba(8, 145, 178, 0.12); color: var(--brand, #0891b2); }
.ai-insight-chip--low      { background: rgba(93, 107, 128, 0.12); color: var(--text-muted, #5d6b80); }
.ai-insight-card__category {
  color: var(--text-muted, #5d6b80);
}
.ai-insight-card__subject {
  margin-inline-start: auto;
  font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
  background: rgba(0,0,0,0.04);
  padding: 2px 7px;
  border-radius: 6px;
  color: var(--text, #1d2331);
  font-size: 11px;
}
.ai-insight-card__body {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text, #1d2331);
  margin-block-end: 8px;
}
.ai-insight-card__action-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-block-end: 6px;
}
.ai-insight-card__action-btn,
.ai-insight-card__act-btn,
.ai-insight-card__dismiss-btn {
  appearance: none;
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  background: var(--surface-soft, #f7f8fa);
  border-radius: 8px;
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text, #1d2331);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  transition: background 120ms, transform 120ms;
}
.ai-insight-card__action-btn {
  background: var(--brand, #0891b2);
  color: #fff;
  border-color: var(--brand, #0891b2);
}
.ai-insight-card__action-btn:hover { transform: translateY(-4px); }
.ai-insight-card__act-btn:hover    { background: var(--surface-hover, rgba(0,0,0,0.04)); }
.ai-insight-card__dismiss-btn      { margin-inline-start: auto; padding: 5px; }
.ai-insight-card__feedback {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--text-muted, #5d6b80);
  border-block-start: 1px dashed var(--border-soft, rgba(0,0,0,0.06));
  padding-block-start: 6px;
}
.ai-insight-card__feedback-label { margin-inline-end: 4px; }
.ai-insight-card__thumb {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 8px;
  padding: 3px 8px;
  cursor: pointer;
  color: var(--text-muted, #5d6b80);
  transition: background 120ms, border-color 120ms, color 120ms;
}
.ai-insight-card__thumb:hover {
  background: var(--surface-hover, rgba(0,0,0,0.04));
}
.ai-insight-card__thumb.is-on {
  background: var(--brand-soft, rgba(8, 145, 178, 0.12));
  border-color: var(--brand, #0891b2);
  color: var(--brand, #0891b2);
}
.ai-insight-card__value-prompt {
  margin-block-start: 8px;
  padding: 8px 10px;
  background: var(--surface-soft, #f7f8fa);
  border: 1px dashed var(--border-soft, rgba(0,0,0,0.1));
  border-radius: 10px;
}
.ai-insight-card__value-label {
  font-size: 12px;
  color: var(--text-muted, #5d6b80);
  margin-block-end: 6px;
}
.ai-insight-card__value-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}
.ai-insight-card__value-kind {
  appearance: none;
  background: var(--surface, #fff);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 8px;
  padding: 5px 8px;
  font-size: 12.5px;
  color: var(--text, #1d2331);
  cursor: pointer;
}
.ai-insight-card__value-amount {
  flex: 1;
  min-width: 120px;
  background: var(--surface, #fff);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 8px;
  padding: 5px 8px;
  font-size: 12.5px;
}
.ai-insight-card__value-save,
.ai-insight-card__value-skip {
  appearance: none;
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  background: var(--surface, #fff);
  border-radius: 8px;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.ai-insight-card__value-save {
  background: var(--brand, #0891b2);
  color: #fff;
  border-color: var(--brand, #0891b2);
}
/* Wins view (B - Value Dashboard). */
.ai-wins-view {
  padding: 8px 12px 12px;
  overflow-y: auto;
  max-height: 60vh;
}
.ai-wins-view__period-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-block-end: 10px;
}
.ai-wins-chip {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted, #5d6b80);
  cursor: pointer;
}
.ai-wins-chip.is-on {
  background: var(--brand, #0891b2);
  color: #fff;
  border-color: var(--brand, #0891b2);
}
.ai-wins-view__hero {
  background: linear-gradient(135deg, rgba(8, 145, 178, 0.08), rgba(34, 197, 94, 0.06));
  border: 1px solid var(--brand-soft-border, rgba(8, 145, 178, 0.16));
  border-radius: 14px;
  padding: 16px 14px;
  text-align: center;
  margin-block-end: 12px;
}
.ai-wins-view__hero-label {
  font-size: 12px;
  color: var(--text-muted, #5d6b80);
  margin-block-end: 4px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.ai-wins-view__hero-value {
  font-size: 28px;
  font-weight: 800;
  color: var(--success, #10b981);
  line-height: 1.1;
  margin-block-end: 6px;
}
.ai-wins-view__hero-meta {
  font-size: 12px;
  color: var(--text-muted, #5d6b80);
}
.ai-wins-view__breakdown {
  background: var(--surface, #fff);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 12px;
  padding: 10px 12px;
}
.ai-wins-view__breakdown-title {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text, #1d2331);
  margin-block-end: 8px;
}
.ai-wins-view__breakdown-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ai-wins-view__breakdown-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 10px;
  background: var(--surface-soft, #f7f8fa);
  border-radius: 8px;
  font-size: 12.5px;
  overflow: hidden;
}
.ai-wins-view__breakdown-bar {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  background: rgba(8, 145, 178, 0.12);
  z-index: 0;
}
.ai-wins-view__breakdown-kind,
.ai-wins-view__breakdown-amount {
  position: relative;
  z-index: 1;
}
.ai-wins-view__breakdown-amount {
  font-weight: 700;
  color: var(--text, #1d2331);
}
.ai-wins-view__footer-note {
  margin-block-start: 10px;
  font-size: 11.5px;
  color: var(--text-muted, #5d6b80);
  text-align: center;
  line-height: 1.55;
}
/* SaaS Admin AI Watchers tab. */
.saas-ai-watchers { padding: 16px 0; }
.saas-ai-watchers__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-block-end: 12px;
}
.saas-ai-watchers__title { font-size: 16px; font-weight: 700; margin: 0; }
.saas-ai-watchers__reload {
  appearance: none;
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  background: var(--surface-soft, #f7f8fa);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 12.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.saas-ai-watchers__totals {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-block-end: 14px;
}
.saas-ai-watchers__total {
  background: var(--surface, #fff);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 12px;
  padding: 12px 14px;
}
.saas-ai-watchers__total-label {
  font-size: 11.5px;
  color: var(--text-muted, #5d6b80);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-block-end: 4px;
}
.saas-ai-watchers__total-value {
  font-size: 20px;
  font-weight: 800;
  color: var(--text, #1d2331);
}
.saas-ai-watchers__table-wrap { overflow-x: auto; }
.saas-ai-watchers__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}
.saas-ai-watchers__table th,
.saas-ai-watchers__table td {
  padding: 8px 10px;
  border-block-end: 1px solid var(--border-soft, rgba(0,0,0,0.06));
  text-align: start;
}
.saas-ai-watchers__table th {
  background: var(--surface-soft, #f7f8fa);
  font-weight: 700;
  color: var(--text-muted, #5d6b80);
}
.saas-ai-watchers__table tr.is-suppressed { opacity: 0.5; }
.saas-ai-watchers__name {
  font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
  font-weight: 700;
  font-size: 12px;
}
.saas-ai-watchers__desc {
  font-size: 11.5px;
  color: var(--text-muted, #5d6b80);
  margin-block-start: 2px;
  max-width: 320px;
}
.saas-ai-watchers__forbidden {
  text-align: center;
  padding: 32px 16px;
  color: var(--text-muted, #5d6b80);
}
.saas-ai-watchers__error {
  background: rgba(220, 53, 69, 0.07);
  border: 1px solid rgba(220, 53, 69, 0.2);
  color: #b8001e;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 12.5px;
  margin-block-end: 10px;
}
/* Mobile tweaks for Wave 3 views. */
@media (max-width: 768px) {
  .ai-insights-view, .ai-wins-view { max-height: 65vh; }
  .saas-ai-watchers__totals { grid-template-columns: 1fr; }
  .ai-insight-card__action-row { gap: 4px; }
}
/* =================================================================
   AI Watchers Settings Tab (Wave 3.5)
   ================================================================= */
.ai-watchers-tab { display: flex; flex-direction: column; gap: 14px; }
.ai-watchers-tab__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.ai-watchers-tab__title {
  font-size: 16px;
  font-weight: 800;
  color: var(--text, #1d2331);
  margin-block-end: 4px;
}
.ai-watchers-tab__sub {
  font-size: 13px;
  color: var(--text-muted, #5d6b80);
}
.ai-watchers-tab__search {
  appearance: none;
  background: var(--surface-soft, #f7f8fa);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 10px;
  padding: 7px 12px;
  font-size: 13px;
  min-width: 240px;
}
.ai-watchers-tab__section {
  background: var(--surface, #fff);
  border: 1px solid var(--border-soft, rgba(0,0,0,0.08));
  border-radius: 12px;
  overflow: hidden;
}
.ai-watchers-tab__section-head {
  appearance: none;
  background: var(--surface-soft, #f7f8fa);
  border: none;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  cursor: pointer;
  text-align: start;
  transition: background 120ms;
}
.ai-watchers-tab__section-head:hover {
  background: var(--surface-hover, rgba(0,0,0,0.04));
}
.ai-watchers-tab__section-icon {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--brand-soft, rgba(8, 145, 178, 0.1));
  color: var(--brand, #0891b2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.ai-watchers-tab__section-title {
  font-size: 14px;
  font-weight: 700;
  flex: 1;
  color: var(--text, #1d2331);
}
.ai-watchers-tab__section-count {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted, #5d6b80);
  background: rgba(0,0,0,0.04);
  padding: 2px 8px;
  border-radius: 999px;
}
.ai-watchers-tab__section-chev {
  color: var(--text-muted, #5d6b80);
  display: inline-flex;
}
.ai-watchers-tab__section-body {
  display: flex;
  flex-direction: column;
}
.ai-watchers-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-block-start: 1px solid var(--border-soft, rgba(0,0,0,0.06));
}
.ai-watchers-row.is-suppressed { opacity: 0.55; }
.ai-watchers-row__body { flex: 1; min-width: 0; }
.ai-watchers-row__title-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-block-end: 4px;
  flex-wrap: wrap;
}
.ai-watchers-row__title {
  font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text, #1d2331);
}
.ai-watchers-row__sev {
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 6px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ai-watchers-row__sev--critical { background: rgba(220, 53, 69, 0.12); color: #b8001e; }
.ai-watchers-row__sev--high     { background: rgba(245, 158, 11, 0.14); color: #b35e00; }
.ai-watchers-row__sev--medium   { background: rgba(8, 145, 178, 0.12); color: var(--brand, #0891b2); }
.ai-watchers-row__sev--low      { background: rgba(93, 107, 128, 0.12); color: var(--text-muted, #5d6b80); }
.ai-watchers-row__suppress {
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 6px;
  background: rgba(220, 53, 69, 0.07);
  color: #b8001e;
}
.ai-watchers-row__desc {
  font-size: 12.5px;
  color: var(--text-muted, #5d6b80);
  line-height: 1.5;
}
/* iOS-style toggle switch. */
.ai-watchers-row__toggle {
  appearance: none;
  border: none;
  width: 42px;
  height: 24px;
  border-radius: 999px;
  position: relative;
  cursor: pointer;
  transition: background 160ms;
  flex-shrink: 0;
}
.ai-watchers-row__toggle.is-on  { background: var(--brand, #0891b2); }
.ai-watchers-row__toggle.is-off { background: rgba(93, 107, 128, 0.3); }
.ai-watchers-row__toggle:disabled { opacity: 0.6; cursor: wait; }
.ai-watchers-row__toggle-knob {
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  transition: inset-inline-start 160ms;
}
.ai-watchers-row__toggle.is-on .ai-watchers-row__toggle-knob {
  inset-inline-start: 21px;
}
.ai-watchers-tab__footer-note {
  font-size: 11.5px;
  color: var(--text-muted, #5d6b80);
  text-align: center;
  padding: 6px 0;
}
.ai-watchers-tab__loading,
.ai-watchers-tab__empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--text-muted, #5d6b80);
  font-size: 13px;
}
.ai-watchers-tab__forbidden {
  padding: 32px 16px;
  text-align: center;
}
.ai-watchers-tab__forbidden-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 8px;
  border-radius: 50%;
  background: var(--warning-soft, rgba(245, 158, 11, 0.12));
  color: var(--warning, #f59e0b);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.ai-watchers-tab__forbidden-title {
  font-size: 15px;
  font-weight: 700;
  margin-block-end: 4px;
}
.ai-watchers-tab__forbidden-body {
  font-size: 12.5px;
  color: var(--text-muted, #5d6b80);
}
@media (max-width: 768px) {
  .ai-watchers-tab__search { min-width: 100%; }
  .ai-watchers-row { padding: 10px 12px; }
}
