/* ============================================================================
   om-tokens.css — the static token ladder.

   HALF ONE of the two permitted token sources (spec §3.3). Precedence: this
   file -> resources/views/partials/theme.blade.php (the themeable subset,
   from the settings table, emitted last in <head> so it wins) -> data-theme /
   data-density / data-radius / data-shadow on <html>. A :root block in any
   OTHER file under public/css/ is a defect.

   Everything from here to the "ADDITIONS LAYER" banner is the nine
   docs/design-system/kit/tokens/*.css files concatenated as: colors ·
   typography · fonts · spacing · radius · elevation · motion · layout ·
   semantic. (base.css is not a token file — it becomes om-base.css.)
   Exactly three mechanical edits are applied to that region: the Google-Fonts
   at-rule imports are dropped (_head.blade.php already loads the Arabic
   faces), the kit `@kind` authoring annotations are stripped (metadata only,
   and 1.6 KB of the size gate), and --bottomnav-h-safe is re-declared in the
   additions layer per D14. Regenerate via the Phase 1 plan, Task 5 Step 3;
   hand-edit only the additions layer.

   NO BUILD STEP: served verbatim. No at-rule imports, no preprocessor.
   ============================================================================ */

/* ============================================================
   COLOUR — token names are the live app's, values are Omni's.
   One blue: #337cec, hue 216deg. Never introduce a second blue.
   ============================================================ */
:root{
  /* ---- Brand. --primary is the name every Blade view already uses. ---- */
  --primary:#337cec;
  --primary-rgb:51,124,236;
  --primary-light:#5b97f1;
  --primary-dark:#2164ca;
  --primary-darker:#1e519e;
  --primary-glow:rgba(51,124,236,.25);
  --primary-soft:rgba(51,124,236,.10);
  --primary-ink:#1f4a8e;

  /* Full ramp, single hue 216deg — for chart series, tints and rails. */
  --blue-50:#ecf3fd;--blue-100:#d5e4fc;--blue-200:#b4cff9;--blue-300:#85b1f5;--blue-400:#5b97f1;
  --blue-500:#337cec;--blue-600:#2164ca;--blue-700:#1e519e;--blue-800:#1b4079;--blue-900:#16315a;

  /* Blue alphas — glows, rings, scrims. */
  --blue-a04:rgba(51,124,236,.04);--blue-a08:rgba(51,124,236,.08);--blue-a12:rgba(51,124,236,.12);
  --blue-a18:rgba(51,124,236,.18);--blue-a24:rgba(51,124,236,.24);--blue-a32:rgba(51,124,236,.32);
  --blue-a45:rgba(51,124,236,.45);--blue-a60:rgba(51,124,236,.60);

  /* ---- Secondary / accent. Kept because Blade views reference them. ----
     Re-pointed into the blue family so the product stays single-hue: the
     shipped defaults (#06d6a0 teal, #f59e0b amber) would have introduced two
     more hues on the sidebar-active gradient and the accent chips. */
  --secondary:#1e519e;
  --secondary-rgb:30,81,158;
  --secondary-soft:rgba(30,81,158,.12);
  --accent:#5b97f1;
  --accent-rgb:91,151,241;
  --accent-soft:rgba(91,151,241,.12);
  --accent-ink:#375a91;
  --accent-dark:#2164ca;

  /* ---- Gradients. Three, all single-hue. ---- */
  --gradient-main:linear-gradient(135deg,#4a8bef,#2164ca);
  --gradient-primary:linear-gradient(135deg,#337cec,#2164ca);
  /* --gradient-sidebar was a SECOND copy of --sidebar-bg's two literals, read by
     exactly one rule (.om-auth__brand) and never redeclared by partials/theme —
     so the login panel that documented itself as per-clinic branded was the one
     surface guaranteed NOT to be. T29 deleted it; --sidebar-bg is the sidebar. */
  --sidebar-bg:linear-gradient(180deg,#16315a 0%,#1e519e 100%);
  --sidebar-active:linear-gradient(135deg,#337cec,#5b97f1);
  --gradient-ink:linear-gradient(150deg,#1b2129 0%,#10151b 100%);
  --gradient-sheen:linear-gradient(110deg,transparent 0%,rgba(255,255,255,.10) 45%,rgba(255,255,255,.16) 50%,rgba(255,255,255,.10) 55%,transparent 100%);

  /* ---- Status. The app's own muted palette, unchanged. ---- */
  --success:#2e9e6b;--success-rgb:46,158,107;--success-soft:rgba(46,158,107,.12);--success-ink:#1c5f40;
  --warning:#cf962f;--warning-rgb:207,150,47;--warning-soft:rgba(207,150,47,.12);--warning-ink:#7c5a1c;
  --danger:#cf5563;--danger-rgb:207,85,99;--danger-soft:rgba(207,85,99,.12);--danger-ink:#7c333b;
  --info:#3b8fc0;--info-rgb:59,143,192;--info-soft:rgba(59,143,192,.12);--info-ink:#235673;

  /* ---- Appointment-status hues, verbatim from the doctor dashboard. ----
     These seven are the only colours outside the ramps above, because the
     product already teaches them to its users. */
  --st-scheduled:var(--primary);
  --st-confirmed:#0ea5e9;
  --st-arrived:#f59e0b;
  --st-in-progress:#8b5cf6;
  --st-completed:#16a34a;
  --st-cancelled:#ef4444;
  --st-no-show:#94a3b8;
  /* Each hue at ~60% lightness. This is what the SOLID chip tier fills with:
     white text fails AA on raw amber (#f59e0b) and raw slate (#94a3b8), and the
     darkened hue keeps the state instantly recognisable while passing. */
  --st-scheduled-deep:#1f4a8e;
  --st-confirmed-deep:#086399;
  --st-arrived-deep:#936007;
  --st-in-progress-deep:#533894;
  --st-completed-deep:#0d622c;
  --st-cancelled-deep:#8f2929;
  --st-no-show-deep:#59626e;
  /* Visit types */
  --vt-new:var(--primary);
  --vt-follow-up:#0891b2;
  --vt-emergency:#ef4444;
  --vt-walk-in:#f59e0b;
  --vt-new-deep:#1f4a8e;
  --vt-follow-up-deep:#05576a;
  --vt-emergency-deep:#8f2929;
  --vt-walk-in-deep:#936007;
  /* Payment states reuse the semantic four, with matching deep variants. */
  --pay-paid:var(--success);
  --pay-due:var(--danger);
  --pay-partial:var(--warning);
  --pay-insured:var(--info);
  --pay-paid-deep:#1c5f40;
  --pay-due-deep:#7c333b;
  --pay-partial-deep:#7c5a1c;
  --pay-insured-deep:#235673;

  /* ---- Gender chips, verbatim from theme.blade.php ---- */
  --gender-male:#1d4ed8;--gender-female:#be185d;
  --gender-male-soft:#dbeafe;--gender-female-soft:#fce7f3;
  --gender-other:#64748b;
  --gender-other-soft:#f1f5f9;

  /* ---- Timing badges (التوقيت column), verbatim from public/css/style.css.
          "done" is GREEN, not muted: a finished visit is a success state. ---- */
  --timing-wait-bg:#fef3c7;
  --timing-wait-fg:#92400e;
  --timing-active-bg:#ede9fe;
  --timing-active-fg:#5b21b6;
  --timing-done-bg:#d1fae5;
  --timing-done-fg:#065f46;
  --timing-late-bg:#fee2e2;
  --timing-late-fg:#991b1b;

  /* ---- Surfaces. The app's light defaults, tuned to the Omni cream. ---- */
  --bg-base:#f9fcfd;      /* the client's creamy white — replaces #f4f7fb */
  --bg-elevated:#ffffff;
  --bg-muted:#f4f7fa;
  --surface:#ffffff;
  --surface-soft:#f4f7fa;
  --card-bg:#ffffff;
  --border:#e2e8f0;
  --border-strong:#cbd5e1;
  --border-light:#f1f5f9;
  --ink:#1b2129;          /* charcoal black — replaces #0f172a */
  --ink-muted:#4f5c6b;
  --ink-faint:#94a3b8;
  --ink-rgb:27,33,41;
  --surface-rgb:255,255,255;

  /* Neutral ramp — for anything the semantic names above don't cover. */
  --n-0:#ffffff;--n-25:#f9fcfd;--n-50:#f4f7fa;--n-100:#e9eef4;--n-200:#dae2ec;--n-300:#c2cddb;
  --n-400:#9aa8ba;--n-500:#6f7d8e;--n-600:#4f5c6b;--n-700:#384350;--n-800:#242c36;--n-900:#1b2129;--n-950:#10151b;

  /* Neutral alphas — scrims, glass, dividers over photography. */
  --ink-a04:rgba(27,33,41,.04);--ink-a08:rgba(27,33,41,.08);--ink-a12:rgba(27,33,41,.12);
  --ink-a24:rgba(27,33,41,.24);--ink-a48:rgba(27,33,41,.48);--ink-a72:rgba(27,33,41,.72);
  --white-a08:rgba(255,255,255,.08);--white-a12:rgba(255,255,255,.12);--white-a16:rgba(255,255,255,.16);
  --white-a64:rgba(255,255,255,.64);--white-a88:rgba(255,255,255,.88);

  /* ---- Chart series. Blue first, then the app's status hues. ---- */
  --chart-1:#337cec;--chart-2:#85b1f5;--chart-3:#2e9e6b;--chart-4:#cf962f;
  --chart-5:#1e519e;--chart-6:#9aa8ba;
  --chart-grid:#e9eef4;--chart-axis:#9aa8ba;

  /* ---- Bootstrap interop — the app is Bootstrap 5. ---- */
  --bs-primary:#337cec;
  --bs-primary-rgb:51,124,236;
  --bs-link-color:#337cec;

  /* ---- Legacy aliases referenced by public/css/style.css ---- */
  --text:#1b2129;
  --text-dark:#1b2129;
  --text-muted:#4f5c6b;
  --text-faint:#94a3b8;
}

/* ============================================================
   DARK — data-theme="dark", matching the app's attribute exactly.
   Clinics run 24 hours; this is a first-class theme.
   ============================================================ */
[data-theme="dark"]{
  --bg-base:#0b1220;
  --bg-elevated:#111827;
  --bg-muted:#0f172a;
  --surface:#111827;
  --surface-soft:#1f2937;
  --card-bg:#111827;
  --border:#1f2937;
  --border-strong:#334155;
  --border-light:#1a2333;
  --ink:#f1f5f9;
  --ink-muted:#cbd5e1;
  --ink-faint:#64748b;
  --ink-rgb:241,245,249;
  --surface-rgb:17,24,39;
  --text:#f1f5f9;
  --text-dark:#f1f5f9;
  --text-muted:#cbd5e1;
  --primary-soft:rgba(51,124,236,.18);
  --primary-glow:rgba(51,124,236,.35);
  --primary-ink:#85b1f5;
  --secondary-soft:rgba(30,81,158,.18);
  --accent-soft:rgba(91,151,241,.18);--accent-ink:#a5c6f7;
  --success-soft:rgba(46,158,107,.18);--success-ink:#5fd6a5;
  --warning-soft:rgba(207,150,47,.18);--warning-ink:#e8b563;
  --danger-soft:rgba(207,85,99,.18);--danger-ink:#f0908f;
  --info-soft:rgba(59,143,192,.18);--info-ink:#7fc0e4;
  --gender-male-soft:rgba(29,78,216,.22);
  --gender-female-soft:rgba(190,24,93,.22);
  --shadow-sm:0 1px 3px rgba(0,0,0,.30);
  --shadow-md:0 4px 14px rgba(0,0,0,.40);
  --shadow-lg:0 14px 32px rgba(0,0,0,.50);
  --shadow-xl:0 24px 56px rgba(0,0,0,.58);
  --chart-grid:rgba(255,255,255,.08);--chart-axis:#64748b;
  --glass-bg:rgba(17,24,39,.72);
}
/* ============================================================
   TYPE — Cairo, the app's default Arabic face. The size ladder,
   line heights and weights are the app's own rem values; only the
   tracking rules are new (Arabic wants looser tracking than the
   Latin kit this redesign started from — see readme).
   ============================================================ */
:root{
  --fs-2xs:0.65rem;   /* 10.4px — micro labels, table meta */
  --fs-xs:0.75rem;    /* 12px  — captions, chips */
  --fs-sm:0.85rem;    /* 13.6px — DEFAULT table cell + secondary body */
  --fs-base:1rem;     /* 16px  — body; remapped by data-density */
  --fs-lg:1.125rem;   /* 18px  — card titles */
  --fs-xl:1.35rem;    /* 21.6px — section titles */
  --fs-2xl:1.65rem;   /* 26.4px — page titles, stat values */
  --fs-3xl:2rem;      /* 32px  — hero numbers */
  --fs-4xl:2.6rem;    /* 41.6px — queue-board digits */

  --lh-tight:1.25;
  --lh-base:1.6;
  --lh-loose:1.85;

  /* Arabic sets tighter than Latin at the same tracking, and Cairo's
     diacritics need room, so tracking stays at or near zero. Never apply
     the -0.5px global tracking the Latin base kit used. */
  --ls-tight:-0.01em;
  --ls-base:0;
  --ls-caps:0.06em;
  --ls-caps-wide:0.08em;

  --fw-regular:400;
  --fw-medium:500;
  --fw-semibold:600;
  --fw-bold:700;
  --fw-black:800;

  /* Composed roles. Use these, not raw sizes. */
  --type-page-title:var(--fw-black) var(--fs-2xl)/var(--lh-tight) var(--font-sans);
  --type-section:var(--fw-black) var(--fs-xl)/var(--lh-tight) var(--font-sans);
  --type-card-title:var(--fw-bold) var(--fs-lg)/var(--lh-tight) var(--font-sans);
  --type-stat:var(--fw-black) var(--fs-2xl)/1.1 var(--font-sans);
  --type-body:var(--fw-regular) var(--fs-base)/var(--lh-base) var(--font-sans);
  --type-body-sm:var(--fw-regular) var(--fs-sm)/var(--lh-base) var(--font-sans);
  --type-body-strong:var(--fw-bold) var(--fs-sm)/var(--lh-base) var(--font-sans);
  --type-label:var(--fw-bold) var(--fs-sm)/var(--lh-tight) var(--font-sans);
  --type-caption:var(--fw-regular) var(--fs-xs)/var(--lh-base) var(--font-sans);
  --type-overline:var(--fw-bold) var(--fs-2xs)/var(--lh-tight) var(--font-sans);
  --type-button:var(--fw-bold) var(--fs-sm)/1 var(--font-sans);

  /* Latin numerals inside Arabic text. Times, money, MRNs, vitals. */
  --numeric-tabular:"tnum" 1,"lnum" 1;
}

/* Density remaps, verbatim from theme.blade.php. */
[data-density="compact"]{--fs-base:0.92rem}
[data-density="spacious"]{--fs-base:1.05rem}
/* Touch step. --fs-2xs sat on 12.00px, under the 12.5px legible floor; compact is
   a desktop density that put body copy on 14.72px in the hand. (0,2,0) because
   theme.blade.php emits that selector inline and later, at (0,1,0). */
@media (max-width:1024px){
  :root{--fs-2xs:0.8125rem;--fs-xs:0.875rem;--fs-sm:0.9375rem}
  :root[data-density="compact"]{--fs-base:1rem}
}
/* The live app loads its Arabic face from the Google Fonts CDN and lets the
   clinic choose between Cairo (default), Almarai, Tajawal, IBM Plex Sans Arabic
   and Readex Pro via the theming tab. Cairo is the default and the one this
   design system is drawn against; IBM Plex Sans Arabic ships as the alternate
   because it is the most structurally different of the five (useful for
   testing that a layout survives a font swap). No font binaries exist in the
   source, so none are vendored — see readme.md > CAVEATS.

   Icons are Font Awesome 6 Free, loaded from CDN by tokens/base.css, matching
   the `fa-solid` / `fa-regular` classes used throughout the Blade views. */
:root{
  --font-sans:'Cairo','Almarai',system-ui,-apple-system,sans-serif;
  --font-sans-alt:'IBM Plex Sans Arabic','Cairo',system-ui,sans-serif;
  --font-mono:'JetBrains Mono','Courier New',monospace;
  /* Latin-facing surfaces (invoice numbers, MRNs, clock) inherit --font-sans;
     Cairo carries a complete Latin set, so no second family is needed. */
}
/* ============================================================
   SPACE — the app's rem scale, remapped by data-density.
   ============================================================ */
:root{
  /* Half-steps, not a renumber: 86 of 107 raw spacing values sat at/below 6px.
     FIXED (never density-remapped) — a micro-gap that shrinks stops separating. */
  --space-05:0.125rem;  /* 2px hairline: 44 literals at 1-3px, no rung */
  --space-1:0.25rem;
  --space-15:0.375rem;  /* 6px icon->label: 25 literals at 5-6px */
  --space-2:0.5rem;--space-3:0.75rem;--space-4:1rem;
  --space-5:1.5rem;--space-6:2rem;--space-7:3rem;

  /* Component insets measured off the live views. */
  --pad-card:var(--space-4);
  --pad-card-lg:var(--space-5);
  --pad-card-sm:var(--space-3);
  --pad-cell-y:0.7rem;
  --pad-cell-x:0.85rem;
  --pad-screen:var(--space-4);
  --pad-screen-lg:var(--space-5);
  --pad-nav-item:0.65rem 0.9rem;
  --gap-grid:var(--space-4);
  /* --gap-inline/--gap-stack deleted: 0 consumers; --space-15 replaces the first. */
}
/* compact --space-3 was 0.55rem — 0.8px from --space-2, not a step.
   MIRRORED in partials/theme.blade.php, which is emitted later and wins. */
[data-density="compact"]{--space-3:0.625rem;--space-4:0.75rem;--space-5:1.1rem;--space-6:1.5rem}
[data-density="spacious"]{--space-3:0.95rem;--space-4:1.25rem;--space-5:1.85rem;--space-6:2.5rem}
/* ============================================================
   RADIUS — the app's three themeable scales, selected by the
   data-radius attribute on <html>. "rounded" is the default.
   ============================================================ */
:root{
  --radius-2xs:0.1875rem; /* 3px rail cap: 10 of 15 raw radii were 2-3px, under --radius-sm. Unthemed — must equal --rail-h. */
  --radius-sm:0.4rem;   /* 6.4px */
  --radius-md:0.65rem;  /* 10.4px — buttons, inputs, nav items */
  --radius-lg:1rem;     /* 16px — cards */
  --radius-xl:1.25rem;  /* 20px — modals, floating panels */
  --radius-pill:999px;
  /* --radius-2xl deleted: 0 consumers, and it claimed the sheets that
     --radius-sheet actually paints at 20px. */
  --radius-sheet:var(--radius-xl) var(--radius-xl) 0 0; /* was frozen at 1.25rem — the one corner ignoring radius_scale */
}
[data-radius="sharp"]{--radius-sm:0.25rem;--radius-md:0.4rem;--radius-lg:0.6rem;--radius-xl:0.8rem}
[data-radius="soft"]{--radius-sm:0.5rem;--radius-md:0.85rem;--radius-lg:1.4rem;--radius-xl:1.75rem}
/* ============================================================
   ELEVATION — two families.
   SHADOW: the app's ink-based scale (rgba(15,23,42,x)), three
   themeable steps plus two extra for modals and sheets.
   GLOW: blue light. The app already ships --primary-glow and a
   .btn-glow class; this formalises the ladder around them.
   ============================================================ */
:root{
  --shadow-sm:0 1px 3px rgba(15,23,42,.06);
  --shadow-md:0 4px 12px rgba(15,23,42,.08);
  --shadow-lg:0 12px 28px rgba(15,23,42,.10);
  --shadow-xl:0 20px 46px rgba(15,23,42,.14);
  --shadow-2xl:0 30px 70px rgba(15,23,42,.20);
  --shadow-inset:inset 0 1px 0 rgba(255,255,255,.7);
  --shadow-nav-bottom:0 -8px 28px -8px rgba(15,23,42,.12);
  --shadow-nav-side:14px 0 44px -22px rgba(15,23,42,.28);

  /* The app's focus ring: 4px, WCAG AAA. Do not shrink it. */
  --shadow-ring:0 0 0 4px rgba(51,124,236,.18);

  --ring-hairline:0 0 0 1px var(--border);
  --ring-hairline-soft:0 0 0 1px var(--border-light);

  /* GLOW ladder — same hue, increasing spread. */
  --glow-xs:0 0 0 3px var(--blue-a12);
  --glow-sm:0 2px 10px -2px var(--blue-a32);
  --glow-md:0 6px 22px -4px var(--blue-a45);
  --glow-lg:0 10px 34px -8px var(--blue-a60);
  --glow-inset:inset 0 0 12px -4px var(--blue-a32);

  /* Semantic glows — status chips and destructive confirms only. */
  --glow-success:0 4px 16px -4px rgba(46,158,107,.45);
  --glow-warning:0 4px 16px -4px rgba(207,150,47,.45);
  --glow-danger:0 4px 16px -4px rgba(207,85,99,.45);

  /* The primary button at rest and on hover — the app's own values. */
  --elev-cta:0 4px 14px -3px var(--blue-a45);
  --elev-cta-hover:0 6px 22px rgba(51,124,236,.42),inset 0 0 0 1px rgba(51,124,236,.5);

  /* Sidebar active pill — verbatim from design-tokens.css. */
  --elev-nav-active:0 8px 22px rgba(51,124,236,.40),inset 0 0 0 1px rgba(255,255,255,.18),0 0 0 4px rgba(51,124,236,.12);

  /* Glass — top bar and mobile tab bar only. */
  --glass-bg:rgba(255,255,255,.78);
  --glass-blur:blur(18px) saturate(160%);
  --glass-border:1px solid rgba(255,255,255,.6);
}
[data-shadow="subtle"]{--shadow-sm:0 1px 2px rgba(15,23,42,.04);--shadow-md:0 2px 6px rgba(15,23,42,.05);--shadow-lg:0 6px 16px rgba(15,23,42,.06)}
[data-shadow="lifted"]{--shadow-sm:0 2px 6px rgba(15,23,42,.08);--shadow-md:0 8px 22px rgba(15,23,42,.12);--shadow-lg:0 18px 44px rgba(15,23,42,.16)}
/* ============================================================
   MOTION — the app's three durations and two curves, unchanged.
   Its own rule, kept: hover transitions animate colour and shadow,
   never width or height (no layout shift).
   ============================================================ */
:root{
  --motion-fast:150ms;
  --motion-base:220ms;
  --motion-slow:320ms;
  --motion-ambient:2400ms;

  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-in-out:cubic-bezier(.4,0,.2,1);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
  --ease-linear:linear;

  --transition:all var(--motion-base) var(--ease-out);
  --t-color:color var(--motion-fast) var(--ease-out),background-color var(--motion-fast) var(--ease-out),border-color var(--motion-fast) var(--ease-out);
  --t-elevate:transform var(--motion-base) var(--ease-out),box-shadow var(--motion-base) var(--ease-out);
  --t-glow:box-shadow var(--motion-slow) var(--ease-out);
  --t-all:all var(--motion-base) var(--ease-out);

  --lift-1:-1px;
  --lift-2:-2px;
  --lift-3:-3px;
  --press-scale:.97;
  --press-scale-subtle:.985;
  --hover-scale:1.015;
  --icon-hover:scale(1.15) rotate(-3deg);
}
@media (prefers-reduced-motion:reduce){
  :root{
    --motion-fast:0.001ms;
    --motion-base:0.001ms;
    --motion-slow:0.001ms;
  }
}
/* ============================================================
   LAYOUT — four form factors, because the app ships four layouts:
   app.blade.php (desktop) · app-tablet · app-mobile · tv (queue board).
   Breakpoints are the app's own: 576 / 768 / 992 / 1280.
   ============================================================ */
:root{
  --bp-sm:576px;--bp-md:768px;--bp-lg:992px;--bp-xl:1280px;--bp-2xl:1600px;

  --sidebar-w:280px;      /* desktop rail; the settings rail is also 280px */
  --sidebar-w-rail:80px;  /* tablet icon rail */
  --sidebar-w-drawer:284px;
  /* Room the tablet icon rail's nav scroller claims OVER the content column so
     that the label tooltip which replaces the hidden label (D7 / SHELL
     §Sidebar) is not clipped — a scroll container clips at its own padding box,
     and nothing positioned can escape it. .shell-rail-tip derives its max-width
     from this same token, so the two can never drift apart. */
  --rail-tip-room:260px;
  --topbar-h:64px;
  --topbar-h-mobile:56px;
  --bottomnav-h:64px;
  /* --bottomnav-h-safe is defined in the additions layer below (D14). */
  --content-max:1560px;
  --prose-max:70ch;
  --row-h:56px;--row-h-compact:46px;
  --control-h:44px;--control-h-sm:36px;--control-h-lg:52px;
  --chip-h:28px;--chip-h-sm:22px;
  --tap-min:44px;
  --avatar-xs:24px;--avatar-sm:32px;--avatar-md:40px;--avatar-lg:56px;--avatar-xl:84px;
  --queue-num:36px;
  --step-h:28px;
  /* Settings rail (T13). Geometry, not rhythm; named because each recurs
     across the rail's desktop and mobile forms — T2.5's test for a name. */
  --railnav-w:280px;
  --railnav-icon:36px;--railnav-icon-sm:26px;
  --railnav-dot-w:4px;--railnav-dot-h:22px;

  --z-base:0;
  --z-raised:10;
  --z-sticky:30;
  --z-topbar:40;
  --z-sidebar:50;
  --z-bottomnav:55;
  --z-overlay:60;
  --z-modal:70;
  --z-toast:80;
  --z-tooltip:90;
}
/* ============================================================
   SEMANTIC ALIASES + the clinical state vocabulary.
   The state names below are the app's own enum values — do not
   invent new ones, and do not paraphrase the Arabic labels.
   ============================================================ */
:root{
  /* Surfaces (aliases onto the app's names, for readability) */
  --canvas:var(--bg-base);
  --surface-sunken:var(--surface-soft);
  --surface-hover:var(--surface-soft);
  --surface-active:var(--n-100);
  --surface-selected:var(--primary-soft);
  --surface-inverse:var(--n-900);
  --surface-disabled:var(--n-100);

  --text-primary:var(--ink);
  --text-secondary:var(--ink-muted);
  --text-placeholder:var(--ink-faint);
  --text-disabled:var(--n-300);
  --text-inverse:#fff;
  --text-on-brand:#fff;
  --text-brand:var(--primary);
  --text-link:var(--primary);
  --text-link-hover:var(--primary-dark);

  --divider:var(--border-light);
  --focus-ring:var(--shadow-ring);

  --card-border:1px solid var(--border);
  --card-radius:var(--radius-lg);
  --card-shadow:var(--shadow-sm);
  --card-shadow-hover:var(--shadow-lg);

  /* ---- APPOINTMENT STATUS — the seven values in the codebase ----
     scheduled مجدول · confirmed مؤكد · arrived في الانتظار
     in_progress قيد الكشف · completed مكتمل · cancelled ملغي
     no_show لم يحضر                                              */
  --st-scheduled-fg:#1e4f8a;--st-scheduled-bg:var(--primary-soft);
  --st-confirmed-fg:#075985;--st-confirmed-bg:rgba(14,165,233,.12);
  --st-arrived-fg:#8a5a08;--st-arrived-bg:rgba(245,158,11,.14);
  --st-in-progress-fg:#5b21b6;--st-in-progress-bg:rgba(139,92,246,.14);
  --st-completed-fg:#14683a;--st-completed-bg:rgba(22,163,74,.12);
  --st-cancelled-fg:#9b1c1c;--st-cancelled-bg:rgba(239,68,68,.12);
  --st-no-show-fg:#4f5c6b;--st-no-show-bg:rgba(148,163,184,.16);

  /* ---- VISIT TYPE ----
     new كشف جديد · follow_up مراجعة · emergency طوارئ · walk_in حضور مباشر */
  --vt-new-fg:var(--primary-ink);--vt-new-bg:var(--primary-soft);
  --vt-follow-up-fg:#0e6b80;--vt-follow-up-bg:rgba(8,145,178,.12);
  --vt-emergency-fg:#9b1c1c;--vt-emergency-bg:rgba(239,68,68,.12);
  --vt-walk-in-fg:#8a5a08;--vt-walk-in-bg:rgba(245,158,11,.14);

  /* ---- PAYMENT (الدفع column) ---- */
  --pay-paid-fg:var(--success-ink);--pay-paid-bg:var(--success-soft);
  --pay-due-fg:var(--danger-ink);--pay-due-bg:var(--danger-soft);
  --pay-partial-fg:var(--warning-ink);--pay-partial-bg:var(--warning-soft);
  --pay-insured-fg:var(--info-ink);--pay-insured-bg:var(--info-soft);

  /* ---- ROW STATES on the appointments board ---- */
  --row-next-up:var(--primary-soft);
  --row-next-up-rail:var(--primary);
  --row-waiting:rgba(245,158,11,.05);
  --row-waiting-rail:var(--st-arrived);
  --row-active:rgba(139,92,246,.06);
  --row-active-rail:var(--st-in-progress);
  --row-cancelled-rail:var(--st-cancelled);
}

[data-theme="dark"]{
  --st-scheduled-fg:#9cc2f7;--st-scheduled-bg:rgba(51,124,236,.18);
  --st-confirmed-fg:#7dd3fc;--st-confirmed-bg:rgba(14,165,233,.18);
  --st-arrived-fg:#fcd34d;--st-arrived-bg:rgba(245,158,11,.18);
  --st-in-progress-fg:#c4b5fd;--st-in-progress-bg:rgba(139,92,246,.20);
  --st-completed-fg:#6ee7a8;--st-completed-bg:rgba(22,163,74,.18);
  --st-cancelled-fg:#fca5a5;--st-cancelled-bg:rgba(239,68,68,.18);
  --st-no-show-fg:#cbd5e1;--st-no-show-bg:rgba(148,163,184,.14);
  --vt-new-fg:#9cc2f7;--vt-follow-up-fg:#67e8f9;--vt-emergency-fg:#fca5a5;--vt-walk-in-fg:#fcd34d;
  --row-next-up:rgba(51,124,236,.14);
  --row-waiting:rgba(245,158,11,.07);
  --row-active:rgba(139,92,246,.10);
}

/* ============================================================================
   ADDITIONS LAYER — everything above is the kit verbatim; everything below is
   derived from the rebuild spec. Hand-edit here, never above.
   ============================================================================ */
:root{
  --glow-ring:var(--shadow-ring);
  --glow-focus:var(--shadow-ring);
  /* ---- opacity — spec §3.2, from DESIGN-LANGUAGE + COMPONENTS prose ---- */
  --opacity-disabled:.55;      /* "opacity .55, no pointer" */
  --opacity-row-action:.45;    /* "row actions sit at 45% opacity" */
  --opacity-nav-heading:.42;   /* "group headings ... @42% opacity" */

  /* ---- blur — spec §3.2, DESIGN-LANGUAGE "modal scrim ... 6px" ---- */
  --blur-scrim:6px;            /* --glass-blur (elevation) already exists */

  /* ---- icon sizing — spec §3.2, DESIGN-LANGUAGE §Icons + SHELL §Sidebar.
         The 18-vs-22 conflict resolves as an 18px glyph in a 22px fa-fw track. */
  --icon-btn:1rem;
  --icon-tab:1.15rem;
  --icon-tile:1.25rem;
  --icon-hero:1.35rem;
  --icon-nav:18px;
  --icon-nav-track:22px;
  /* Nothing renamed (those four names are also utility classes). 13 raw glyph
     sizes had no rung: the ladder stopped at 16px below and 21.6px above. Icons
     stay OFF --fs-* — a glyph scaling with density overflows its fixed tile. */
  --icon-micro:0.9rem;   /* 14.4px — micro label/badge glyph */
  --icon-glyph:1.5rem;   /* 24px — modal / stat medallion */
  --icon-empty:1.875rem; /* 30px — empty-state glyph */

  /* ---- NOT rhythm. Named so they are not mistaken for rungs. ---- */
  --hairline:1px;        /* device unit: cancels a border, clips a11y boxes. Never a gap. */
  --rail-h:0.1875rem;    /* 3px rail thickness; equals --radius-2xs so cap and bar cannot drift */
  /* Switch geometry — the thumb's travel is 40-16-2, previously a bare 22px. */
  --switch-w:40px;
  --switch-h:20px;
  --switch-thumb:16px;

  /* ---- D14 (LOCKED). The DYNAMIC bottom inset ANIMATES on scroll on BOTH
     engine families — Chrome 135+ as the Android chin retracts, iOS Safari as
     its toolbar collapses — so in a height or a padding it relayouts every
     frame (commit e989d83). It may appear only in `bottom:`, or in padding on
     something provably not a fixed-height bar.

     TWO tokens, because safe-area-max-inset-* is Chromium-only (131+): on
     WebKit/Gecko a token is EITHER static-but-approximate OR exact-but-
     animating, and which trade is right depends on whether the consumer cancels
     it, so one cannot serve both — the defect this split replaces. Overrides
     the kit layout.css value neutralised above.

     (1) STATIC ON EVERY ENGINE. Only for geometry a negative `bottom:` cancels:
     .mobile-bottom-nav (om-clinic.css §BOTTOM NAV GEOMETRY) and the
     --bottomnav-h-safe clearance from it. The bar reserves this much chin in
     height/padding, then offsets down by the same minus the CURRENT inset: the
     visible row is --bottomnav-h tall and sits on the chin on any engine,
     whatever the constant, and the rest hangs offscreen. Over-reserving is free;
     under-reserving leaves a transparent strip over the chin. So the fallback
     errs high. 36px IS a magic constant: the literal mobile-shell.css:339 has
     shipped under this pattern since e989d83 (its header requires both to
     mirror), and it clears every inset WebKit reports — 34px iPhone portrait, 21
     landscape, 20 iPad, 0 elsewhere. Sole cost: up to 36px of over-reserved
     scroll slack in .om-page on chinless non-Chromium. Rejected: this arm
     staying dynamic (the bug — WebKit relayouts the bar every frame); an
     @supports engine sniff (unrelated vendor property, breaks when WebKit ships
     the keyword, still needs a constant); JS writing a px value (gated on script
     timing, wrong if the toolbar starts retracted); a 0px fallback (page shows
     through the strip under a translucent bar).

     (2) Max inset where the engine has it, exact current inset where it does
     not. ONLY for sheet/composer padding that nothing cancels — .om-modal__foot
     and the AI composer, where the reasoning sits. ---- */
  --safe-max-inset-bottom:env(safe-area-max-inset-bottom,36px);
  --bottomnav-h-safe:calc(var(--bottomnav-h) + var(--safe-max-inset-bottom));
  --safe-inset-bottom-sheet:env(safe-area-max-inset-bottom,env(safe-area-inset-bottom,0px));
  --safe-inset-top:env(safe-area-inset-top,0px);

  /* ---- The four tokens that previously bypassed the theme entirely.
         Each was consumed only as var(--x, #hardcoded-fallback), so under
         [data-theme="dark"] the fallback rendered a light-theme colour
         (03-css.md §2.4). --text-primary is supplied by the semantic layer. */
  --ink-soft:var(--ink-muted);       /* ai-copilot.css:657 */
  --lh-relaxed:var(--lh-loose);      /* ai-copilot.css:658 */
  --border-subtle:var(--border-light); /* admin/doctors/index.blade.php:8,60 */

  /* ---- Legacy interop. These names existed ONLY inside style.css's deleted
         :root (03-css.md §2.5). Routed through the canonical scale so the 33
         var(--radius) and 13 var(--radius-xs) call sites finally respond to
         the per-clinic radius_scale setting, and so the surface aliases follow
         dark mode instead of staying pinned to a light hex. These declarations
         are deliberately LAST so they win over colors.css's literal values in
         both themes. ---- */
  --radius:var(--radius-xl);
  --radius-xs:var(--radius-sm);
  --bg:var(--bg-base);
  --text:var(--ink);
  --text-dark:var(--ink);
  --text-muted:var(--ink-muted);
  --text-faint:var(--ink-faint);
  --card-bg:var(--surface);
  --primary-darker:var(--blue-700);
  --accent-dark:var(--blue-600);
  --shadow-glow:var(--glow-md);
  --gradient-main-hover:linear-gradient(135deg,#2164ca,#1e519e);

  /* ---- LOCAL stacking, for ordering boxes WITHIN one component (a sheen under
         its label, a spinner over both). NOT rungs of the --z-* ladder above:
         anything that must escape its own component belongs on --z-sticky and
         up. Declared here because only this layer is hand-editable. ---- */
  --z-local-1:1;
  --z-local-2:2;
  --z-local-3:3;

  /* ---- Missing rungs of the white-alpha ladder. The kit layer paints three
         overlays on a gradient at alphas the generated ladder does not carry
         (.18, .22, .60), and a fill or a shadow COLOUR cannot carry its alpha
         as opacity the way a leaf ink can. Without these three the values snap
         to a04-a08 neighbours, which is a silent visual change. Pre-composed
         like every other rung above, NOT hand-mixed from --white-rgb: those
         channels exist for Bootstrap interop, and the colour gate matches the
         notation itself, so composing one here would be a fresh violation. ---- */
  --white-a18:rgba(255,255,255,.18);--white-a22:rgba(255,255,255,.22);--white-a60:rgba(255,255,255,.60);
  /* The dark-chrome rungs: om-clinic.css paints the sidebar, the slim hero and
     the TV board entirely in white-on-dark, and its eleven alphas missed every
     rung above. Snapping them to a neighbour would have silently re-graded the
     nav's three-level ink hierarchy (.82 item / .70 icon / .45 section head),
     so the ladder gains the rungs instead. --black-a18 is the one dark rung
     the same chrome needs, for the nav hover's cast shadow. ---- */
  --white-a07:rgba(255,255,255,.07);--white-a10:rgba(255,255,255,.10);--white-a14:rgba(255,255,255,.14);
  --white-a45:rgba(255,255,255,.45);--white-a50:rgba(255,255,255,.50);--white-a55:rgba(255,255,255,.55);
  --white-a62:rgba(255,255,255,.62);--white-a70:rgba(255,255,255,.70);--white-a72:rgba(255,255,255,.72);
  --white-a82:rgba(255,255,255,.82);--white-a92:rgba(255,255,255,.92);
  --black-a18:rgba(0,0,0,.18);

  /* ---- Chip tints. Each of om-clinic.css's three chip tiers paints a
         TRANSLUCENT DERIVATIVE of a chip hue: the SOLID tier's coloured drop
         shadow, the OUTLINE tier's hairline, the SOFT tier's fill and hairline.
         A translucent derivative is a colour, not an opacity — putting it on
         the leaf as `opacity` would fade the label with it — and composing it
         at the call site would put a colour notation in a consumer sheet. So
         it is composed here, in the palette, exactly like the alpha ladders
         above. The percentages are the ported kit's, unchanged. ---- */
  --st-scheduled-glow:color-mix(in srgb,var(--st-scheduled) 40%,transparent);
  --st-confirmed-glow:color-mix(in srgb,var(--st-confirmed) 40%,transparent);
  --st-arrived-glow:color-mix(in srgb,var(--st-arrived) 40%,transparent);
  --st-in-progress-glow:color-mix(in srgb,var(--st-in-progress) 40%,transparent);
  --st-completed-glow:color-mix(in srgb,var(--st-completed) 40%,transparent);
  --st-cancelled-glow:color-mix(in srgb,var(--st-cancelled) 40%,transparent);
  --st-no-show-glow:color-mix(in srgb,var(--st-no-show) 40%,transparent);
  --vt-new-line:color-mix(in srgb,var(--vt-new) 42%,transparent);
  --vt-follow-up-line:color-mix(in srgb,var(--vt-follow-up) 42%,transparent);
  --vt-walk-in-line:color-mix(in srgb,var(--vt-walk-in) 42%,transparent);
  /* طوارئ is the one visit type allowed to break the quiet tier: it alone gets
     a fill, and a heavier hairline than the other three. */
  --vt-emergency-tint:color-mix(in srgb,var(--vt-emergency) 14%,transparent);
  --vt-emergency-line:color-mix(in srgb,var(--vt-emergency) 45%,transparent);
  --pay-paid-tint:color-mix(in srgb,var(--pay-paid) 12%,transparent);
  --pay-partial-tint:color-mix(in srgb,var(--pay-partial) 12%,transparent);
  --pay-insured-tint:color-mix(in srgb,var(--pay-insured) 12%,transparent);
  --pay-due-tint:color-mix(in srgb,var(--pay-due) 12%,transparent);
  --pay-paid-line:color-mix(in srgb,var(--pay-paid) 24%,transparent);
  --pay-partial-line:color-mix(in srgb,var(--pay-partial) 24%,transparent);
  --pay-insured-line:color-mix(in srgb,var(--pay-insured) 24%,transparent);
  /* An unpaid balance blocks the patient at the desk — visible edge, not 24%. */
  --pay-due-line:color-mix(in srgb,var(--pay-due) 55%,transparent);
  /* The rule dividing an amount off from its label INSIDE a chip. currentColor
     is deliberately not resolved here: a custom property is substituted at the
     element that uses it, so this one rule tracks whichever chip ink it lands
     on — which is why it can be one token instead of fifteen. */
  --chip-amount-rule:color-mix(in srgb,currentColor 28%,transparent);

  /* ---- Chrome + scrim channels, moved out of mobile-shell.css's :root ---- */
  --white-rgb:255,255,255;
  --scrim-rgb:0,0,0;
}

/* ---- Dark theme lifts the two chip tiers that use a -deep hue AS TEXT: on a
       dark surface a 60%-lightness ink is unreadable. Declared only here
       because the token only exists in dark — in light those tiers read their
       -deep value directly. Same rule as the tints above: a mix is a colour,
       so it is composed in the palette and never at the call site. ---- */
[data-theme="dark"]{
  --vt-new-lift:color-mix(in srgb,var(--vt-new) 72%,var(--text-inverse));
  --vt-follow-up-lift:color-mix(in srgb,var(--vt-follow-up) 72%,var(--text-inverse));
  --vt-walk-in-lift:color-mix(in srgb,var(--vt-walk-in) 72%,var(--text-inverse));
  --vt-emergency-lift:color-mix(in srgb,var(--vt-emergency) 72%,var(--text-inverse));
  --pay-paid-lift:color-mix(in srgb,var(--pay-paid) 72%,var(--text-inverse));
  --pay-due-lift:color-mix(in srgb,var(--pay-due) 72%,var(--text-inverse));
  --pay-partial-lift:color-mix(in srgb,var(--pay-partial) 72%,var(--text-inverse));
  --pay-insured-lift:color-mix(in srgb,var(--pay-insured) 72%,var(--text-inverse));
}

/* ---- Ophthalmology module palette, moved out of ophthalmology.css's :root.
       D13: the module is re-tokenised, not rebuilt, so its namespace stays —
       but the declaration belongs in the one token file. ---- */
:root{
  --ophtho-accent:#4f46e5;  /* indigo — module accent + OD (right eye) */
  --ophtho-os:#ec4899;      /* pink   — OS (left eye) */
  --ophtho-teal:#0d9488;    /* teal   — anterior segment / IOL */
  --ophtho-purple:#7c3aed;  /* pupil, motility & fields */
  --ophtho-rose:#e11d48;    /* posterior segment */
  --ophtho-emerald:#059669; /* investigations */
  --ophtho-orange:#ea580c;  /* ICD-10 diagnosis */
  --ophtho-amber:#d97706;   /* IOP */
  --ophtho-sky:#0369a1;     /* ocular history */
}
[data-theme="dark"]{
  --ophtho-accent:#818cf8;
  --ophtho-os:#f472b6;
  --ophtho-teal:#2dd4bf;
  --ophtho-purple:#a78bfa;
  --ophtho-rose:#fb7185;
  --ophtho-emerald:#34d399;
  --ophtho-orange:#fb923c;
  --ophtho-amber:#fbbf24;
  --ophtho-sky:#38bdf8;
}

/* ============================================================================
   PRINT — the five tokens named in TOKENS.md §RTL,dark,print and shipped in no
   kit file (spec §3.2). Consumed by om-print.css — stubbed in Task 8 of this
   phase, rewritten into its three layers by Phase 7 Task 1.
   ============================================================================ */
@media print{
  :root{
    --print-ink:#111;
    --print-rule:#999;
    --print-page-margin:12mm;
    --print-fs-base:11pt;
    --print-fs-sm:9.5pt;
  }
}
