/* المنتج HR — الويب.
   نفس لوحة تطبيق أندرويد وخطّه، فالموظف الذي يفتح الاثنين لا يشعر بانتقال.
   مبنيّ للهاتف أولاً — أكثر من يفتحه مستخدمو iPhone. */

@font-face {
  font-family: 'Tajawal';
  src: url('../fonts/tajawal_regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Tajawal';
  src: url('../fonts/tajawal_medium.ttf') format('truetype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Tajawal';
  src: url('../fonts/tajawal_bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

:root {
  --teal: #255c82;
  --orange: #163a55;
  --yellow: #e0a800;
  --coral: #e85d5d;
  --pink: #d97c8e;
  --violet: #7c6bb0;
  --blue: #3e8fb8;
  --green: #3e9e62;
  --ink: #163a55;
  /* خافتٌ لكنْ مقروء: كان #8a7f6e ≈٣٫٢:١ على الرملي (دون AA)، صار ≈٤٫٩:١ */
  --muted: #6b6150;
  /* خلفيّةُ الشاشة — بيضاء (قرار المالك ٢٠٢٦-١٠-٠٣، «خلفية الشاشات بيضاء»)؛
     لا تُطابق خلفيّةَ الورقة المطبوعة (`paper.js` SAND تبقى #faf2e5) عمداً. */
  --sand: #ffffff;
  --card: #ffffff;
  --line: #e6ded2;
  /* ── حرفيّاتٌ كانت مبعثرةً داخل القواعد، صارت رموزاً (٣ أيلول ٢٠٢٦) ──
   *
   * القيمُ **لم تتغيّر**: هذه الجولة نقلت مصدرَ اللون لا اللونَ نفسه،
   * فالواجهةُ بعدها بكسلٌ ببكسل كما كانت. والسببُ أنّ لوناً مكتوباً في
   * جسد قاعدةٍ لا يُرى: `#dcd0bb` كان في ثلاثة أمكنةٍ متباعدة، ومن
   * يغيّر أحدها ينسى الاثنين، فتفترق الحقولُ عن الشرائح عن زرّ الإغلاق.
   * وحارسُ `parity/check-contrast.mjs` لا يقرأ إلا ما في `:root`.
   *
   * التعليقُ في آخر كل سطر اسمُ المتغيّر في ملفّ Figma
   * (`groYIYavbeyyL8gTdcI6N4`)؛ وما سُبق بـ`≈` أقربُ أصلٍ في السُّلَّم
   * لا رمزٌ دلاليٌّ مؤكَّد هناك بعد. */
  --line-soft: #f4ece0;          /* ≈ sand/250 */
  --readonly: #f4ece0;           /* color/bg/readonly */
  --brand-disabled: #9fbfb9;     /* color/bg/brand-disabled */
  --border-strong: #d8cbb4;      /* color/border/strong */
  --border-field: #dcd0bb;       /* color/border/field */
  --track: #efe4d4;              /* color/bg/track */
  --grab: #d6c9b3;               /* ≈ sand/350 */
  --spinner-track: #e6dac6;      /* ≈ line/200 */
  --on-brand: #ffffff;           /* color/text/on-brand */
  /* ── design kit 2026-10-10 (docs/design-kit-2026-10-10.md) ──
   * Meaning colours are literal: bad red, warn amber, info blue mean the same for every
   * company. The brand-following roles (good tone, filled-button face, flat tone) are
   * var()/color-mix() of the roles migration/brand-tenant.mjs recolours, never a literal;
   * their real values sit in the @supports block below, these are the fallbacks.
   * The old status-pending/approved/rejected tokens were folded into these tones. */
  --tone-bad-bg: #fbe4df;
  --tone-bad-ink: #8e2a1d;
  --tone-warn-bg: #fdebd8;
  --tone-warn-ink: #7a420c;
  --tone-info-bg: #e1ecf7;
  --tone-info-ink: #1c4770;
  --tone-flat-bg: var(--track);
  --tone-flat-ink: var(--ink);
  --tone-good-bg: var(--line-soft);
  --tone-good-ink: var(--ink);
  --brand-face: var(--teal);
  /* data colours (SegmentStrip, TargetBar, AlertRow dots); told apart by lightness too */
  --data-amber: #e08a2e;
  --data-red: #9e2b1f;
  --data-blue: #8db8e6;
  --sev-low: #3e7cb8;
  --notice-info-bg: #e3f0f6;     /* color/bg/info-subtle */
  --notice-info-ink: #1f5a75;    /* color/text/info */
  --notice-warn-bg: #fdf1d6;     /* color/bg/warning-subtle */
  --notice-warn-ink: #8a6209;    /* color/text/warning */
  --notice-danger-bg: #fbe0e0;   /* color/bg/danger-subtle */
  --notice-danger-ink: #93292d;  /* color/text/danger-strong */
  --notice-success-bg: #ddf0e4;  /* color/bg/success-subtle */
  --notice-success-ink: #23603b; /* color/text/success */
  --nav-height: 64px;

  /* ── سُلَّمُ المسافات — إيقاعُ الأربعة ──
   *
   * كانت المسافاتُ حرفيّةً كلَّها: ٦ و٧ و٩ و١٠ و١٣ و١٤ و١٨ و٢٦ متناثرةً
   * بلا إيقاع، فتُقاس كلُّ شاشةٍ بعينٍ لا بمسطرة. والرقمُ من هذا السُّلَّم
   * وحدَه من الآن. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  /* ── سُلَّمُ الخطّ ──
   *
   * كانت عشرةُ أحجامٍ مختلفة (١١ · ١٢ · ١٣ · ١٤ · ١٥ · ١٦ · ١٨ · ١٩ · ٢٢ · ٢٦)
   * في ملفٍّ واحد — وهذا تسرّبٌ لا سُلَّم. صارت سبعةً، وأربعةُ قياساتٍ
   * انزاحت إليها: ١١←١٢ (تسمياتُ الشريط السفليّ كانت تحت حدّ القراءة)،
   * و١٥←١٦ في ثلاثة مواضع، و١٩←١٨.
   *
   * ⚠️ **و`--text-md` هو حدُّ حقول الإدخال ولا ينزل عنه**: Safari على
   * iPhone يكبّر الصفحةَ عند التركيز على حقلٍ أصغرَ من ١٦ بكسل. */
  --text-xs: 12px;    /* التسمياتُ والشاراتُ والحالات */
  --text-sm: 13px;    /* عناوينُ الحقول، واسمُ العلامة تحت الشعار */
  --text-base: 14px;  /* الثانويُّ وخلايا الجداول */
  --text-md: 16px;    /* المتنُ، وكلُّ حقلِ إدخالٍ بلا استثناء */
  --text-lg: 18px;    /* عناوينُ الأوراق والأقسام */
  --text-xl: 22px;    /* عنوانُ الشاشة */
  --text-2xl: 26px;   /* الرقمُ الكبيرُ وحدَه */

  /* ── الاستدارة ──
   *
   * كانت ثمانيَ قيم (٢ · ٨ · ١٢ · ١٤ · ١٦ · ٢٠ · ٢٢ · ٩٩٩). صارت خمساً:
   * الزرُّ والحقلُ على استدارةٍ واحدة (١٢) فيُقرآن أسرةً واحدة، والأسطحُ
   * الكبيرةُ كلُّها ١٦. */
  --radius-xs: 2px;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  /* ── الطبقات — سُلَّمٌ معلَنٌ لا أرقامٌ في جسد القواعد ── */
  --z-topbar: 20;
  --z-nav: 30;
  --z-sheet: 40;
  --z-toast: 50;
  --z-lightbox: 60;
  /* ظلالٌ ناعمةٌ متدرّجة (Soft UI): عمقٌ هادئ لا حادّ */
  --shadow-sm: 0 1px 2px rgba(58, 50, 38, 0.05), 0 1px 3px rgba(58, 50, 38, 0.04);
  --shadow-md: 0 2px 6px rgba(58, 50, 38, 0.06), 0 6px 18px rgba(58, 50, 38, 0.07);
  --shadow-lg: 0 6px 16px rgba(58, 50, 38, 0.08), 0 18px 40px rgba(58, 50, 38, 0.10);
  --shadow-teal: 0 4px 12px rgba(75, 168, 157, 0.28);
  --ease: cubic-bezier(0.2, 0, 0, 1);
}

/* The brand-following kit roles, derived from the tenant's own --teal (tenant-theme.css
   overrides --teal; these resolve against it). Same ratios as Android's brand-tenant
   derivation: the button face is the brand darkened 25% (Product: ~#397e75, white on it
   ~5:1; white on the raw teal is 2.8:1). Engines without color-mix() keep the fallbacks
   above: the old teal button and a neutral good pill. Measured by parity/check-contrast.mjs. */
@supports (color: color-mix(in srgb, red 50%, blue)) {
  :root {
    --brand-face: color-mix(in srgb, var(--teal) 75%, #000);
    --tone-good-bg: color-mix(in srgb, var(--teal) 14%, #fff);
    --tone-good-ink: color-mix(in srgb, var(--teal) 50%, #000);
  }
}

/* ══ سُلَّمُ الخطّ يكبر مع الشاشة — لا رقمٌ واحدٌ للهاتف وللمرقاب ══
 *
 * الورقةُ مبنيّةٌ للهاتف أوّلاً، وقياساتُها أعلاه مضبوطةٌ على شاشةٍ في اليد.
 * وهي نفسُها على مرقابٍ ٢٣ إنشاً تُقرأ **صغيرةً**: المسافةُ إلى العين تتضاعف
 * والقياسُ لا يتغيّر. فالسُّلَّمُ يرتفع درجتين، والعمودُ يتّسع معه كي لا يطول
 * السطرُ أكثرَ ممّا تتبعه العين (٦٥–٧٥ حرفاً هو المريح).
 *
 * ⚠️ ولا ينزل `--text-md` عن ١٦ في أيّ درجة — هو حدُّ حقول الإدخال الذي يمنع
 * Safari على iPhone من تكبير الصفحة عند التركيز. وهو يصعد هنا لا ينزل. */

/* لابتوب ١٦–١٨ إنشاً */
@media (min-width: 1024px) {
  :root {
    --text-xs: 13px;
    --text-sm: 14px;
    --text-base: 15px;
    --text-md: 17px;
    --text-lg: 20px;
    --text-xl: 25px;
    --text-2xl: 30px;
  }
}

/* مرقابُ ٢١–٢٣ إنشاً — الأكثرُ استعمالاً هنا */
@media (min-width: 1440px) {
  :root {
    --text-xs: 14px;
    --text-sm: 15px;
    --text-base: 16px;
    --text-md: 18px;
    --text-lg: 22px;
    --text-xl: 28px;
    --text-2xl: 34px;
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: 'Tajawal', 'Segoe UI', Tahoma, sans-serif;
  font-size: var(--text-md);
  /* iPhone: المتصفّح يكبّر عند تدوير الجهاز بلا هذا */
  -webkit-text-size-adjust: 100%;
}

body { overscroll-behavior-y: none; }

/* ══ الهيكل ══ */

#app { min-height: 100dvh; display: flex; flex-direction: column; }

.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
  /* ‏`1fr auto 1fr` لا `space-between`: الوسطُ وسطُ الشريط مهما طال اسمُ
     الموظف — ومع `space-between` كان الشعارُ ينزاح باسمٍ طويل */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 10px;
  padding: max(10px, env(safe-area-inset-top)) 16px 10px;
  background: var(--sand);
  border-bottom: 1px solid var(--line);
}
.topbar-side { display: flex; align-items: center; gap: 8px; min-width: 0; }
.topbar-actions { justify-content: flex-end; }
.topbar .role {
  font-size: var(--text-xs);
  color: var(--muted);
  /* اسمٌ طويلٌ يُقصّ ولا يدفع الشعارَ عن مكانه */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ══ العلامة — الشعارُ في الوسط والاسمُ تحته ══ */

.brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  line-height: 1;
}
.brand-mark {
  /* الأصلُ 420×204؛ الارتفاعُ يقود والعرضُ يتبع فلا يشوّهه شيء */
  height: 30px;
  width: auto;
  display: block;
}
.brand-name {
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: .04em;
  color: var(--ink);
}
@media (max-width: 380px) {
  /* شاشةٌ ضيّقة: الشعارُ وحدَه — الاسمُ مكتوبٌ داخله أصلاً */
  .brand-mark { height: 26px; }
  .brand-name { display: none; }
  .topbar { padding-inline: 10px; }
}

main {
  flex: 1;
  padding: 14px 14px calc(var(--nav-height) + env(safe-area-inset-bottom) + 20px);
  max-width: 720px;
  width: 100%;
  margin: 0 auto;
}

/* ══ الشريط السفلي — ستة بنود تسع الشاشة بلا تمرير أفقي ══ */

.nav {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: var(--z-nav);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  background: var(--card);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.nav button {
  /* ٤٨ بكسل حدّ اللمس الآمن — تسعة أزرار كانت تنزل تحته في أندرويد */
  min-height: 56px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 500;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  cursor: pointer;
}
/* الأيقونةُ صارت SVG ترث `currentColor` — لا حجمَ خطٍّ لها */
.nav button .icon { display: block; }
.nav button[aria-current='page'] { color: var(--ink); font-weight: 700; }
.nav button[aria-current='page'] .icon { transform: translateY(-1px); }

/* ══ البطاقات ══ */

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 16px;
  margin-bottom: 12px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 180ms var(--ease), transform 180ms var(--ease);
}
/* البطاقةُ المقصودةُ برابطٍ من شاشةٍ أخرى — «سياسة التأخير والخصم» من كشوف
   الرواتب مثلاً. الشاشةُ تُمرَّر إليها، والإطارُ يقول «هذه هي» فلا يبحث
   القارئ عمّا وصل من أجله بين أربع عشرة بطاقة. بلونٍ من اللوحة لا جديد. */
/* ⚠️ **بطاقةٌ فيها قائمةٌ منسدلة لا تقصّ قائمتَها.**
 *
 * `overflow: hidden` أعلاه موجودةٌ لتقصّ شريطَ اللون (`.card.accent::before`)
 * عند الزوايا المستديرة. وهي تقصّ معه **`.listbox-popup`** — وهي مطلقةُ
 * الموضع تنزل `top: calc(100% + 4px)` بارتفاعٍ يبلغ ٢٨٠ بكسل، فتخرج عن صندوق
 * البطاقة. والنتيجةُ **ليست قائمةً تعلو البطاقة بل شريحةٌ مقصوصةٌ داخلها**،
 * وتتحوّل البطاقةُ إلى منطقة تمرير (قِيس: `scrollTop` صار ١٤١).
 *
 * ولا تُرفع `overflow` عن كلّ البطاقات — عندها تبرز زوايا شريط اللون المربّعةُ
 * خارج الاستدارة في كلّ بطاقةٍ ملوّنة. فتُرفع عن **البطاقات ذات القائمة وحدَها**،
 * ويستعيد شريطُها استدارتَه بنفسه بدل أن تقصّه البطاقة.
 *
 * و`:has()` تتلاشى بأمان: متصفّحٌ لا يعرفها يتجاهل القاعدتين فيبقى الحالُ كما
 * هو اليوم — مقصوصاً، لا أسوأ. */
.card:has(.listbox) { overflow: visible; }
.card:has(.listbox).accent::before {
  border-start-start-radius: var(--radius-lg);
  border-end-start-radius: var(--radius-lg);
}

.card.focused {
  border-color: var(--teal);
  box-shadow: 0 0 0 2px var(--teal);
}

/* Design kit 2026-10-10 (owner): plain white cards, no coloured edge stripe. `card(…, accent)`
   still sets --accent so a screen can read it, but nothing is drawn. Status is told by
   the StatusPill inside the card, never by the edge. */
.card.accent::before { content: none; }

.section-title { font-weight: 700; font-size: var(--text-lg); margin: 22px 2px 10px; }
.title { font-size: var(--text-xl); font-weight: 700; margin: 0 0 4px; }
.subtitle { color: var(--muted); font-size: var(--text-base); margin: 0; }
.caption { color: var(--muted); font-size: var(--text-xs); }
.money { font-size: var(--text-2xl); font-weight: 700; color: var(--brand-face); }

.row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 0; }
.row + .row { border-top: 1px solid var(--line-soft); }
.row .label { color: var(--muted); font-size: var(--text-base); }
.row .value { font-weight: 500; }

/* ══ ساعتا الحضور والانصراف الفعليّتان — أكبرُ ما في بطاقة الحضور ══
   والدوامُ المجدولُ سطرٌ خافتٌ تحتهما (`.shift-line`). */
.punch-times { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 22px; padding:8px 0 2px; }
.punch-times .punch { display:inline-flex; align-items:baseline; gap:6px; }
.punch-times .punch-label { color:var(--muted); font-size:var(--text-base); }
.punch-times .punch-time { font-size:var(--text-2xl); font-weight:700; color:var(--ink); line-height:1.2; }
.punch-times .punch-manual { color:var(--blue); font-size:var(--text-xs); }
.punch-times .punch-none { font-size:var(--text-lg); font-weight:700; color:var(--muted); }
.shift-line { margin:0 0 4px; }

/* ══ بطاقات السجلّ — ثلاث طبقات ══
   رأسٌ (اسمٌ + شارة) · رقمٌ حاسم · تفاصيلُ ثانويّة تحت خطّ. تُستعمل جنباً
   إلى جنب مع `.card`، ولا تمسّ `.row`. */
/* رأسُ البطاقة: اسمٌ/عنوانٌ يطوي لا يفيض، وشارةُ حالةٍ لا تُدفَع */
.record-head { display:flex; align-items:flex-start; justify-content:space-between; gap:var(--space-3); }
.record-head .name-wrap { min-width:0; overflow-wrap:anywhere; }
.record-title { font-size:var(--text-lg); font-weight:700; line-height:1.4; margin:0; }
.record-sub { font-size:var(--text-sm); color:var(--muted); margin-top:2px; }
/* رقمٌ حاسمٌ (مبلغٌ، أيّام) — بلون العلامة، أرقامٌ لاتينيةٌ مصطفّة (نفس منطق .money الحالي) */
.record-figure { font-size:var(--text-2xl); font-weight:700; color:var(--brand-face);
  font-family: system-ui, 'Segoe UI', Roboto, Tahoma, sans-serif; direction:ltr;
  unicode-bidi:isolate; font-variant-numeric:tabular-nums; white-space:nowrap; }
/* تفاصيلُ ثانويّة تحت خطّ فاصل — لا تتنافس مع الرأس */
.record-meta { display:flex; flex-wrap:wrap; gap:var(--space-2) var(--space-5);
  margin-top:var(--space-3); padding-top:var(--space-3); border-top:1px solid var(--line-soft); }
.record-meta > div { font-size:var(--text-sm); color:var(--muted); }
.record-meta > div b { color:var(--ink); font-weight:500; }

/* ══ الأزرار ══ */

button.primary, button.ghost, button.danger {
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: 700;
  border-radius: var(--radius-md);
  border: 0;
  padding: 15px 18px;
  width: 100%;
  cursor: pointer;
  min-height: 52px;
  transition: transform 140ms var(--ease), box-shadow 140ms var(--ease), background 140ms var(--ease), filter 140ms var(--ease);
}
button.primary:hover, button.danger:hover { filter: brightness(1.04); transform: translateY(-1px); }
button.primary:active, button.ghost:active, button.danger:active { transform: translateY(0) scale(0.99); }
button.ghost:hover { background: rgba(75, 168, 157, 0.08); border-color: var(--teal); }
/* kit: the filled face is the dark brand (white on the raw teal is 2.8:1), shadow <= 2px */
button.primary { background: var(--brand-face); color: var(--on-brand); box-shadow: var(--shadow-sm); }
button.primary.orange { background: var(--orange); }
/* ⚠️ **زرٌّ معطَّلٌ ليس زرّاً غيرَ مقروء.** كان `#f7f2e9` على `#cfc4b2`
   وتباينُهما **١٫٥٦:١** — نصٌّ غيرُ مرئيٍّ في غرفةٍ مضاءة، فكيف تحت شمس
   الأردن. وزرُّ البصمة يبقى معطّلاً حتى **اثنتي عشرة ثانية** وعليه
   «يُحدَّد الموقع…»، فيرى المندوبُ شريطاً بيجَ فارغاً فيظنّ التطبيق
   معطوباً، يضغط ثانيةً فلا شيء، ثم يغلقه. هذا السطرُ وحدَه قد يفصل بين
   من فتح التطبيق ومن بصم. صار ≈٤٫٦:١. (٢٧ آب ٢٠٢٦.) */
button.primary:disabled { background: var(--brand-disabled); color: var(--on-brand); }
/* kit secondary: white with a hairline border */
button.ghost { background: var(--card); color: var(--ink); border: 1px solid var(--border-field); }
button.danger { background: var(--coral); color: var(--on-brand); }
button.small { width: auto; padding: 9px 16px; font-size: var(--text-base); min-height: 44px; }

/* ══ النماذج ══ */

/* `.field` لا `label.field`: المكوّناتُ المركّبة (`.listbox`) تُبنى الآن في
   `<div class="field">` لا `<label>` — انظر التعليق في `field()` بـ`ui.js`. */
.field { display: block; margin-bottom: 12px; }
.field > span { display: block; font-size: var(--text-sm); color: var(--muted); margin-bottom: 6px; }

input, select, textarea {
  font-family: inherit;
  /* ١٦ بكسل حدٌّ أدنى: أقلّ منه يجعل Safari يكبّر الصفحة عند التركيز */
  font-size: var(--text-md);
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--border-field);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--ink);
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--teal); border-color: transparent; }
input.error, textarea.error { border-color: var(--coral); }
/* حقلٌ للقراءة وحدها يبدو كذلك — لا حقلاً أبيض يُضغط فلا يستجيب */
input[readonly] { background: var(--readonly); color: var(--muted); border-style: dashed; }

/* صندوق الاختيار: ٢٤ بكسل لا ١٣ الافتراضية — يُصيبه الإبهام، وبلون التطبيق */
input[type=checkbox], input[type=radio] {
  width: 24px;
  height: 24px;
  padding: 0;
  accent-color: var(--teal);
  flex: 0 0 auto;
}
label.field.check { display: flex; align-items: center; gap: 10px; cursor: pointer; }
label.field.check span { margin-bottom: 0; font-size: var(--text-md); color: var(--ink); }

/* ══ قائمة منسدلة مخصّصة — بديل `<select>` المرئيّ (العلة ١، بريف إعادة التصميم) ══
 *
 * `<select>` الأصلي يبقى في `.listbox` مخفيّاً بنمط «إخفاءٌ بصريّ» لا
 * `display:none` — القيمة تبقى قابلةً للقراءة، والقارئ الصوتيّ يتجاهله
 * لـ`aria-hidden`، فلا يُعلَن العنصرُ مرّتين. */
.listbox-native {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.listbox { position: relative; }
.listbox-trigger {
  font-family: inherit;
  font-size: var(--text-md);
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--border-field);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  cursor: pointer;
  text-align: start;
}
.listbox-trigger:focus-visible { outline: 3px solid var(--teal); outline-offset: 1px; }
.listbox-caret { flex: 0 0 auto; color: var(--muted); transition: transform 140ms var(--ease); }
.listbox-trigger[aria-expanded='true'] .listbox-caret { transform: rotate(180deg); }
/* ظلٌّ وقت الفتح فقط — ليتميّز عن حقلٍ ساكنٍ دون إزعاج الحقول المجاورة */
.listbox-trigger[aria-expanded='true'] { box-shadow: var(--shadow-sm); border-color: var(--border-strong); }

.listbox-popup {
  animation: listbox-in 120ms var(--ease);
  position: absolute;
  inset-inline: 0;
  top: calc(100% + 4px);
  z-index: var(--z-sheet);
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  max-height: 280px;
  overflow-y: auto;
}
.listbox-popup:focus { outline: none; }
@keyframes listbox-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
/* عنوانُ مجموعةٍ من `<optgroup>` — فاصلٌ حقيقيّ لا نصٌّ بين البنود */
.listbox-group {
  padding: 8px 10px 4px;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--muted);
}
.listbox-group:not(:first-child) { margin-top: 4px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
.listbox-option {
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  cursor: pointer;
}
/* ⚠️ **الفأرةُ والسهمُ لا يتشابهان.** كانا كلاهما `--line-soft` وحدَه، فمن
   يُسند فأرتَه على بندٍ ويتنقّل بالسهم إلى غيره يرى **سطرَين مُظلَّلَين
   بالتساوي** ولا شيء يقول أيَّهما يأخذه Enter. فالمُبرَزُ بالسهم — وهو
   وحدَه هدفُ Enter — يحمل حلقةً داخليّةً بلون العلامة زيادةً على الخلفيّة. */
.listbox-option.active {
  background: var(--line-soft);
  box-shadow: inset 0 0 0 2px var(--teal);
}

/* و`:hover` خلف `@media (hover: hover)`: هذه ورقةٌ للهاتف أوّلاً، ولمسةٌ على
   شاشةٍ تترك حالةَ التحويم **عالقةً** على البند بعد رفع الإصبع في iOS
   وأندرويد، فيبقى بندٌ مُظلَّلٌ بلا سبب. */
@media (hover: hover) {
  .listbox-option:hover { background: var(--line-soft); }
}
/* المختار يتميّز بلون العلامة — كان لا يتميّز إطلاقاً في القائمة الأصلية */
.listbox-option[aria-selected='true'] { background: var(--brand-face); color: var(--on-brand); font-weight: 700; }
.listbox-option[aria-selected='true'].active { filter: brightness(1.05); }
@media (hover: hover) {
  .listbox-option[aria-selected='true']:hover { filter: brightness(1.05); }
}

.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.chip {
  /* `inline-flex` لا `inline`: `min-height` لا تعمل على `<a class="chip">` بغيرها */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-field);
  background: var(--card);
  color: var(--ink);
  border-radius: var(--radius-pill);
  padding: 9px 16px;
  font-family: inherit;
  font-size: var(--text-base);
  cursor: pointer;
  min-height: 44px;
}
.chip[aria-pressed='true'] { background: var(--brand-face); color: var(--on-brand); border-color: var(--brand-face); }

/* ══ الأشرطة والحالات ══ */

.bar { height: 10px; background: var(--track); border-radius: var(--radius-pill); overflow: hidden; margin: 6px 0; }
.bar > i { display: block; height: 100%; background: var(--teal); border-radius: var(--radius-pill); }

/* ⚠️ `white-space: nowrap` — **شارةٌ على سطرين تُقرأ عطلاً لا حالة.** صارت
   الشارةُ عنصراً مرناً داخل `.record-head`، فانضغطت أمام اسمٍ طويلٍ وانكسرت
   «قيد المراجعة» إلى «قيد» و«المراجعة». والأولويّةُ الصحيحةُ عكسُها: الشارةُ
   تبقى كما هي **والاسمُ هو الذي يطوي** (له `min-width:0` و`overflow-wrap`). */
/* StatusPill (design kit): five tones. The old class names are aliases, listed first, so
   every screen that writes `status approved` / `pending` / `rejected` / `info` / `muted`
   draws the kit pill without being touched. 13/700, padding 4x10, never wraps. */
.status { border-radius: var(--radius-pill); padding: 4px 10px; font-size: var(--text-sm); font-weight: 700; display: inline-block; white-space: nowrap; line-height: 1.5; }
.record-head > .status,
.record-head > .record-figure { flex: 0 0 auto; }
.status.approved, .status.good { background: var(--tone-good-bg); color: var(--tone-good-ink); }
.status.rejected, .status.bad { background: var(--tone-bad-bg); color: var(--tone-bad-ink); }
.status.pending, .status.warn { background: var(--tone-warn-bg); color: var(--tone-warn-ink); }
.status.info { background: var(--tone-info-bg); color: var(--tone-info-ink); }
.status.muted, .status.flat { background: var(--tone-flat-bg); color: var(--tone-flat-ink); }

.notice { border-radius: var(--radius-md); padding: 12px 14px; font-size: var(--text-base); margin: 10px 0; }
/* أيقونةٌ اختياريّةٌ قبل نص التنبيه/الفقرة — بدل رمزٍ تعبيريّ */
.notice .icon, .icon-line .icon { vertical-align: -3px; }
.icon-line { display: flex; align-items: flex-start; gap: 4px; }
.icon-line .icon { flex: 0 0 auto; margin-top: 2px; }
.notice.info { background: var(--notice-info-bg); color: var(--notice-info-ink); }
.notice.warn { background: var(--notice-warn-bg); color: var(--notice-warn-ink); }
.notice.danger { background: var(--notice-danger-bg); color: var(--notice-danger-ink); }
.notice.success { background: var(--notice-success-bg); color: var(--notice-success-ink); }

.empty { text-align: center; color: var(--muted); padding: 40px 10px; }
.empty .icon { display: block; margin: 0 auto 10px; width: fit-content; opacity: 0.6; }

/* ══ الدخول ══ */

.login {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px;
}
.login .card { width: min(420px, 100%); text-align: center; padding: 30px 26px 26px; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.login .brand-logo { width: 76px; height: 76px; object-fit: contain; margin: 0 auto 14px; display: block; }
.login input { text-align: center; letter-spacing: 2px; margin-bottom: 12px; }
.login button.primary { margin-top: 4px; }
/* Forgot password (task-08): selfie capture on the login card, and the approver's two photos */
.login .forgot-link { width: 100%; }
.forgot .subtitle { line-height: 1.7; margin-bottom: 14px; }
.forgot button.ghost { margin-top: 10px; width: 100%; }
.selfie-picker { display: grid; gap: 8px; margin: 6px 0 12px; }
.selfie-frame { width: 100%; max-height: 320px; object-fit: cover; border-radius: var(--radius-md); background: var(--border); transform: scaleX(-1); }
img.selfie-frame { transform: none; }
.selfie-actions { display: grid; gap: 8px; }
.reset-photos { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 10px 0; }
.reset-photos figure { margin: 0; text-align: center; }
.reset-photos img, .reset-photos .no-photo { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; border-radius: var(--radius-md); background: var(--border); display: grid; place-items: center; color: var(--muted); }
.reset-photos figcaption { font-size: var(--text-sm); color: var(--muted); margin-top: 4px; }

/* ══ ورقة منزلقة ══ */

.sheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(58, 50, 38, 0.45);
  z-index: var(--z-sheet);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.sheet {
  background: var(--sand);
  width: min(560px, 100%);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 18px 18px calc(18px + env(safe-area-inset-bottom));
  max-height: 88dvh;
  overflow-y: auto;
  animation: rise 0.18s ease-out;
}
@keyframes rise { from { transform: translateY(24px); opacity: 0.6; } to { transform: none; opacity: 1; } }
/* فراغٌ في طرف العنوان لزرّ الإغلاق كي لا يعلوه عنوانٌ طويل */
.sheet h2 { margin: 4px 0 14px; font-size: var(--text-lg); padding-inline-end: 48px; outline: none; }
.sheet h2:focus-visible { outline: 3px solid var(--teal); outline-offset: 2px; border-radius: var(--radius-sm); }
.sheet .grab { width: 44px; height: 4px; background: var(--grab); border-radius: var(--radius-xs); margin: 0 auto 10px; }
/* زرُّ إغلاقٍ مرئيّ — ٤٤ بكسل حدّ اللمس، في طرف الترويسة */
.sheet { position: relative; }
.sheet-close {
  position: absolute;
  top: 12px;
  inset-inline-end: 12px;
  width: 44px;
  height: 44px;
  border: 1px solid var(--border-field);
  border-radius: 50%;
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.sheet-close:hover { background: rgba(75, 168, 157, 0.08); border-color: var(--teal); }

/* ══ التبويبات داخل الشاشة ══ */

/* a sixth tab (payroll hub) overflowed the page at 390px: the strip scrolls sideways, the page never does */
.tabs { display: flex; gap: 6px; margin-bottom: 12px; overflow-x: auto; }
.tabs button {
  flex: 1;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 12px 6px;
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.tabs button[aria-selected='true'] { color: var(--ink); border-bottom-color: var(--brand-face); }

.spinner {
  width: 22px; height: 22px;
  border: 3px solid var(--spinner-track);
  border-top-color: var(--teal);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  margin: 24px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

.toast {
  position: fixed;
  inset-inline: 16px;
  bottom: calc(var(--nav-height) + env(safe-area-inset-bottom) + 16px);
  z-index: var(--z-toast);
  background: var(--ink);
  color: var(--on-brand);
  padding: 13px 16px;
  border-radius: var(--radius-md);
  text-align: center;
  font-size: var(--text-base);
  animation: rise 0.15s ease-out;
}

@media (min-width: 720px) {
  .nav { position: sticky; border-radius: var(--radius-lg); margin: 0 auto 16px; max-width: 720px; border: 1px solid var(--line); }
  main { padding-bottom: 24px; }
}

/* ⚠️ **والعمودُ يبقى ٧٢٠ — جُرّب توسيعُه إلى ٨٢٠ ثمّ ٩٠٠ وأُلغي.**
 *
 * والسببُ الصامدُ بعد القياس **واحدٌ لا ثلاثة**: الأزرارُ `width:100%` صارت
 * ٨٧٠ بكسلاً، وزرٌّ بهذا العرض شريطٌ لا زرّ — عادت ٦٩٢ في الصفحة و٦٥٨ في
 * البطاقة.
 *
 * 🔴 **وهنا خطأُ قياسٍ وقعتُ فيه، يُكتب كي لا يُعاد:** نُسب إلى التوسعة أنّها
 * ضغطت صفَّ التفاصيل في الموافقات إلى سطرٍ واحدٍ متلاصق. **وهذا غلط.** لقطةُ
 * «قبل» كانت مأخوذةً من شجرةٍ **أقدمَ من كوميت إعادة تصميم البطاقات**، فما
 * ظهر فيها سطرين لم يكن أثرَ عرضٍ أوسع بل **الشكلَ القديم** (`.row`) قبل أن
 * يصير `.record-meta`. وقُيس الأمرُ مباشرةً: الصفُّ سطرٌ واحدٌ على ٧٢٠ وعلى
 * ٩٠٠ سواءً بسواء، بفجوةٍ ٢٤ بكسلاً في الحالتين. فالعرضُ لم يمسّه قطّ.
 * **الدرس: مقارنةُ لقطتين من شجرتين مختلفتين تنسب إلى المتغيّر ما ليس منه.**
 *
 * وثالثةٌ **باقيةٌ ولا شأن للعمود بها**: `justify-content: space-between` يترك
 * ٤٠٠–٦٠٠ بكسلٍ بين العنوان وقيمته حتى على ٧٢٠ (قُيس: «سلف مفتوحة» ← `0`
 * = ٥٥٩ بكسلاً). عيبٌ قائمٌ قبل هذه الجولة، زاده الخطُّ الأكبرُ وضوحاً، ولم
 * يُمَسّ لأنّه يمسّ `.row` في كلّ الشاشات — يُعالَج وحدَه بقرارٍ من المالك.
 *
 * والبطاقةُ مصمَّمةٌ لعمودٍ في عرض اليد: تكبيرُ الخطّ يخدمها وتوسيعُ العمود
 * يمطّها. فالمقبضان انفصلا عمداً — هذا أُبقي والآخرُ أُلغي. */

/* ══ تكبير صفحة الكتالوج ══ */

.lightbox-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);                 /* فوق الورقة المنزلقة (٤٠) والتنبيه (٥٠) */
  background: rgba(20, 16, 10, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: auto;
}
.lightbox-close {
  position: fixed;
  top: calc(12px + env(safe-area-inset-top));
  inset-inline-end: 16px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  font-size: var(--text-lg);
  cursor: pointer;
}

/* ── الإنذارات والتوقيع ── */

/* صفٌّ من الأزرار تحت البطاقة — يلتفّ على الشاشة الضيّقة بدل أن يخرج عنها */
.row-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.signature-pad { margin: 10px 0; }

/* التوقيع المعروض: الـSVG يُقاس ليملأ الإطار، والإطار يتبع عرض البطاقة */
.signature-view {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--card);
  padding: 6px;
  margin-top: 6px;
  overflow: hidden;
}
.signature-view svg { width: 100%; height: auto; display: block; }

/* بطاقة الموظف في تجميع الإنذارات — كلّها قابلة للضغط */
.card [role='button'] { cursor: pointer; }
.value.danger { color: var(--coral); }

/* شبكة «المزيد» — أربع خانات في الصف بأسماء كاملة.
   الشريط السفلي خمسةٌ فقط: اثنا عشر زرّاً على عرض ٣٦٠ بكسل تعني ثلاثين
   بكسلاً للزرّ، أصغر من حدّ اللمس الآمن (٤٤)، والعناوين تُبتر. */
.more-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
}

.more-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 92px;
  padding: 14px 8px;
  background: var(--surface, var(--card));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  width: auto;
}

.more-tile .icon { display: block; }
.more-tile:active { background: var(--line); }

/* ══════════════ الوصول — جولة UI/UX ٢٥ آب ٢٠٢٦ ══════════════
 *
 * ثلاثةُ مآخذَ رصدتها قائمةُ `ui-ux-pro-max`، وكلُّها صحيحة:
 */

/* ⚠️ **١) حلقةُ التركيز كانت على الحقول وحدها.**
 *
 * `input:focus` موجودةٌ منذ البداية، أمّا الأزرارُ وبطاقاتُ «المزيد»
 * والشرائحُ فلا شيء يقول أين أنت حين تتنقّل بـTab. ومن لا يستعمل الفأرة
 * — لإصابةٍ أو لأنّه على لوحة مفاتيح — يتحرّك في صفحةٍ عمياء.
 *
 * و`:focus-visible` لا `:focus`: المتصفّحُ يميّز التنقّلَ بالمفاتيح من
 * الضغط بالفأرة، فلا تظهر الحلقةُ لمن ضغط بيده ولا يظنّها عطلاً.
 */
button:focus-visible,
a:focus-visible,
[role='button']:focus-visible,
[tabindex]:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
  border-radius: var(--radius-md);
}

/* والحقولُ تُوحَّد معها — كانت `outline: 2px` بلا فراغ فتلتصق بالحدّ */
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 1px;
}

/* ⚠️ **٢) الجدولُ العريض كان يكسر الصفحة.**
 *
 * لا جداولَ في الويب اليوم، لكن أيَّ جدولٍ يُضاف غداً على شاشة ٣٦٠px
 * يدفع الصفحة أفقياً فيهرب الشريطُ السفليّ. يُلَفّ بحاويةٍ تمرّر وحدها.
 */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table-scroll table {
  width: 100%;
  border-collapse: collapse;
  min-width: 520px;      /* أضيقُ من هذا يعني أعمدةً بحرفٍ واحد */
}

/* جدولُ الكشوفات — أوّلُ جدولٍ حقيقيٍّ في الويب (`screens/reports-kashf.js`).
 * بلا حدودٍ حول كلّ خلية: سطرٌ رفيعٌ أسفل الصفّ يكفي لتتبّع العين، وشبكةٌ
 * كاملةٌ في كشفٍ بثمانية عشر عموداً تصير سياجاً يُتعِب. والترويسةُ لاصقةٌ
 * لأنّ كشفَ الحضور يطول مئاتِ الصفوف فتغيب أسماءُ الأعمدة عن الشاشة. */
.kashf {
  font-size: var(--text-sm);
}

/* DataTable (design kit): muted header, a hairline above each row, no zebra */
.kashf th,
.kashf td {
  padding: 10px 12px;
  border-top: 1px solid var(--line-soft);
}

.kashf thead th {
  position: sticky;
  top: 0;
  /* طبقةٌ **داخل الجدول** لا في سُلَّم الطبقات العامّ: ترفع الرأسَ فوق
     صفوفه وحدَها، ولا شأن لها بالشريط ولا بالورقة المنزلقة */
  z-index: 1;
  background: var(--card);
  color: var(--muted);
  font-weight: 700;
  white-space: nowrap;
  border-top: 0;
  border-bottom: 1px solid var(--line);
}

.kashf tfoot td {
  border-top: 2px solid var(--border-strong);
  border-bottom: 0;
}

/* ══ الأرقامُ داخل نصٍّ عربيّ ══
 *
 * **قِيس هذا في المتصفّح قبل كتابته** — والقياسُ نفى فرضيّتين شائعتين:
 *
 * ١) **`unicode-bidi: isolate` ليست الناقصة هنا.** خليّةُ الجدول معزولةٌ
 *    أصلاً بورقة أنماط المتصفّح (`td { unicode-bidi: isolate }`)، فالرقمُ
 *    داخلها لا يُعاد ترتيبُه. وتبقى القاعدةُ مكتوبةً من أجل `.money`
 *    وأمثالِها — `<span>` داخل فقرةٍ عربيّة، وهناك العزلُ ضروريٌّ فعلاً.
 *
 * ٢) **و`font-variant-numeric: tabular-nums` وحدَها لا تفعل شيئاً**، لأن
 *    **Tajawal لا يحمل ميزةَ `tnum` أصلاً**. القياس: `111.11` تشغل ٢٩٫٤٧
 *    بكسل و`000.00` تشغل ٤٢٫٣٤ — فرقُ ثلاثةَ عشرَ بكسلاً في العمود الواحد،
 *    وهو بعينه «الأرقام مش مصطفّة». والقيمتان لا تتغيّران بإضافة `tnum`.
 *
 * **فالعلاجُ خطُّ الأرقام لا خاصّيّتُها**: خانةٌ متساويةُ العرض تأتي من
 * خطّ النظام — Segoe UI على ويندوز و‏SF على آيفون و‏Roboto على أندرويد،
 * وثلاثتُها موحَّدةُ الخانة (قياساً: كلُّ رقمٍ من ستّ خاناتٍ ٤٠٫٧٨ بكسل).
 * والنصُّ العربيُّ يبقى Tajawal — الخليّةُ الرقميّةُ أرقامٌ لا كلمات.
 * و`tnum` تبقى لأنها تنفع حيث يدعمها الخطُّ (SF و‏Roboto).
 */
.num,
.money {
  direction: ltr;
  unicode-bidi: isolate;
  font-family: system-ui, 'Segoe UI', Roboto, Tahoma, sans-serif;
  font-variant-numeric: tabular-nums;
}

/* والعمودُ الرقميّ يُحاذى إلى طرفه — **ورأسُه معه**. كان الرأسُ
   `text-align:start` لكلّ الأعمدة، فيقف عنوانُ «المبلغ» في جهةٍ وأرقامُه
   في الجهة المقابلة. */
.kashf .num,
.kashf th.num {
  text-align: end;
}
/* ورأسُ العمود الرقميّ عنوانٌ عربيٌّ لا رقم — يبقى بخطّ النصّ */
.kashf th.num {
  font-family: inherit;
}
.kashf th,
.kashf td {
  white-space: nowrap;
}

/* ⚠️ **٣) الحركةُ لم تكن تحترم من يطلب إيقافها.**
 *
 * `rise` و`spin` تعملان دائماً. ومن ضبط نظامَه على «قلّل الحركة» فعل
 * ذلك لسببٍ — دوارٌ أو صداعٌ أو حساسيّةٌ دهليزية — لا لذوقٍ في التصميم.
 *
 * والدوّارةُ تبقى دوّارةً ببطء لا تتجمّد: مؤشّرُ انتظارٍ ساكنٌ يبدو عالقاً.
 */
@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;
  }

  /* ‏(`.listbox-popup` لا تحتاج سطراً خاصّاً هنا — قاعدةُ `*` أعلاه تشملها
     بنفس القيمة وبنفس `!important`. حُذف السطرُ المكرَّرُ بعد المراجعة.) */

  .spinner {
    animation: spin 1.6s linear infinite !important;
  }
}

/* The card a notification opened (`revealFocused` in ui.js) — an outline, not a fill,
   so the card keeps its own state colours; and a ring the eye finds after the scroll */
.focused {
  outline: 3px solid var(--teal);
  outline-offset: 2px;
}

/* ══════════════ Design kit 2026-10-10 — docs/design-kit-2026-10-10.md ══════════════
 * Components built once in js/kit.js and used by every screen. Brand-following colours
 * come only from var(--teal)-derived roles (--brand-face, --tone-good-*); red, amber and
 * blue are meaning colours. Every number sits in a .num (LTR, isolated). */

/* Section header: title + one muted line + optional actions at the far end */
.section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 0 0 12px; }
.section-head .section-head-text { min-width: 0; }
.section-head h3 { margin: 0; font-size: var(--text-lg); font-weight: 700; line-height: 1.4; }
.section-head p { margin: 2px 0 0; color: var(--muted); font-size: var(--text-base); }
.section-head .section-actions { display: flex; gap: 8px; flex: 0 0 auto; }

/* KpiCard grid: two per row on the phone, auto-fit wider */
.kpi-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
@media (min-width: 600px) { .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } }
.kpi {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: 14px; display: flex; flex-direction: column; gap: 6px;
  min-width: 0; font: inherit; color: var(--ink); text-align: start; width: 100%;
}
button.kpi { cursor: pointer; min-height: 44px; }
@media (hover: hover) { button.kpi:hover { border-color: var(--border-field); box-shadow: var(--shadow-md); } }
.kpi-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kpi-icon {
  width: 36px; height: 36px; flex: 0 0 auto; border-radius: var(--radius-md);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--tone-good-bg); color: var(--brand-face);
}
.kpi-title { font-size: var(--text-base); font-weight: 700; color: var(--muted); min-width: 0; line-height: 1.35; }
.kpi-head .status { margin-inline-start: auto; }
.kpi-value { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; min-width: 0; }
.kpi-value .kpi-num { font-size: var(--text-2xl); font-weight: 700; line-height: 1.2; overflow-wrap: anywhere; }
.kpi-value .kpi-num.bad { color: var(--tone-bad-ink); }
.kpi-unit { font-size: var(--text-md); font-weight: 700; color: var(--muted); }
.kpi-detail { font-size: var(--text-base); color: var(--muted); margin: 0; line-height: 1.45; }

/* SegmentStrip: one 18px bar split by counts, legend of dot + label + count + share */
.seg-strip { display: flex; height: 18px; border-radius: var(--radius-pill); overflow: hidden; background: var(--track); margin: 4px 0 12px; }
.seg-strip > i { display: block; height: 100%; }
.seg-legend { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 0; padding: 0; list-style: none; font-size: var(--text-base); }
.seg-legend li { display: inline-flex; align-items: center; gap: 6px; }
.seg-legend .dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.seg-legend .num { font-weight: 700; }
.seg-legend .share { color: var(--muted); }

/* TargetBar: label and value per row, a bar, an optional target line (2px ink at 55%) */
.tbar-list { display: grid; gap: 14px; }
.tbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; align-items: baseline; }
.tbar-label { font-size: var(--text-base); min-width: 0; overflow-wrap: anywhere; }
.tbar-value { font-weight: 700; white-space: nowrap; }
.tbar-value.off { color: var(--tone-bad-ink); }
.tbar-track { grid-column: 1 / -1; position: relative; height: 10px; background: var(--track); border-radius: var(--radius-pill); }
.tbar-fill { height: 100%; border-radius: var(--radius-pill); background: var(--brand-face); }
.tbar-fill.off { background: var(--data-amber); }
.tbar-target { position: absolute; top: -4px; bottom: -4px; width: 2px; background: var(--ink); opacity: .55; border-radius: 1px; }

/* AlertRow: severity dot + title + one detail line + due pill at the far end */
.alert-row {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 0; min-height: 44px;
  border: 0; border-top: 1px solid var(--line-soft); background: transparent; font: inherit; color: inherit; text-align: start;
}
button.alert-row { cursor: pointer; }
.sev-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.sev-dot.high { background: var(--data-red); }
.sev-dot.mid { background: var(--data-amber); }
.sev-dot.low { background: var(--sev-low); }
.alert-body { flex: 1; min-width: 0; }
.alert-title { font-weight: 700; font-size: var(--text-md); line-height: 1.4; overflow-wrap: anywhere; }
.alert-detail { color: var(--muted); font-size: var(--text-base); margin-top: 2px; overflow-wrap: anywhere; }
.alert-row > .status { flex: 0 0 auto; }

/* Stepper: numbered stages, done / now / waiting */
.stepper { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0; padding: 0; list-style: none; }
.step { display: inline-flex; align-items: center; gap: 8px; font-size: var(--text-base); color: var(--muted); }
.step-num { width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 700; background: var(--tone-flat-bg); color: var(--tone-flat-ink); }
.step.done .step-num { background: var(--brand-face); color: var(--on-brand); }
.step.now { color: var(--ink); font-weight: 700; }
.step.now .step-num { background: var(--card); color: var(--brand-face); box-shadow: inset 0 0 0 2px var(--brand-face); }

/* DataTable outside the reports sheet: same look as .kashf, scrolls inside its card */
.data-table { width: 100%; border-collapse: collapse; font-size: var(--text-base); }
.data-table th { color: var(--muted); font-weight: 700; text-align: start; padding: 10px 12px; white-space: nowrap; border-bottom: 1px solid var(--line); }
.data-table td { padding: 12px; border-top: 1px solid var(--line-soft); }
.data-table .code { color: var(--muted); font-size: var(--text-sm); }

/* PeriodChips: segmented control, selected = filled brand */
.chips.period { display: inline-flex; flex-wrap: nowrap; gap: 4px; padding: 4px; background: var(--line-soft); border-radius: var(--radius-pill); }
.chips.period .chip { border-color: transparent; background: transparent; }
.chips.period .chip[aria-pressed='true'] { background: var(--brand-face); color: var(--on-brand); }

/* Empty / loading / error: the same card and one muted line, never a blank area */
.state-card { text-align: center; color: var(--muted); }
.state-card .spinner { margin: 8px auto 12px; }
.state-card.error { color: var(--tone-bad-ink); }

/* A plain list row inside a card (title + trailing action) */
.list-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 8px 0; border: 0; background: transparent; font: inherit; color: inherit; text-align: start; cursor: pointer; }
.list-row .list-title { flex: 1; font-weight: 700; }
.list-row .list-action { color: var(--brand-face); font-weight: 700; }

/* ── phase 2B: performance/org/settings/fleet ── */
/* Group B screens (performance, org, settings, fleet list, entry). Classes carry the b- prefix
 * so they never collide with the group A block. Colours are roles only: var(--brand-face),
 * the tone tokens, the data tokens - never a literal. */

/* rows of pills that used to carry inline flex styles (rows of buttons: the existing .row-actions) */
.b-pills { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px; }
.b-pills.b-start { justify-content: flex-start; }
.b-pills.b-above { margin-top: 8px; }
.b-mt { margin-top: 10px; }
.b-mb { margin-bottom: 10px; }
.b-filter { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; }
.b-filter > .b-grow { flex: 1; min-width: 140px; }
.b-row-top { align-items: flex-start; }
/* the first row of a card: no hairline above, no padding above */
.row.b-head { border-top: 0; padding-top: 0; }

/* plates, codes and employee numbers: one unbroken left-to-right figure */
.b-plate { direction: ltr; unicode-bidi: isolate; white-space: nowrap; font-family: system-ui, 'Segoe UI', Roboto, Tahoma, sans-serif; }

/* sign-in card: spacing that used to be inline */
.login .subtitle { margin-bottom: 18px; }
.login .forgot-link, .login .forgot-hint { margin-top: 14px; }

/* a section header that follows other content gets the kit's section gap above it */
#view .section-head:not(:first-child) { margin-top: 20px; }
.b-gap { height: 10px; }

/* employee home: check-in / check-out times, product-of-the-day picture */
.b-clock { font-size: var(--text-xl); font-weight: 700; color: var(--brand-face); }
.b-clock.out { color: var(--tone-warn-ink); }
.b-end { text-align: end; }
.b-product-img { width: 100%; border-radius: var(--radius-lg); background: var(--card); }

/* fleet: a card that is one big button, photos, small money figures, inspection items */
.b-card-button { display: block; width: 100%; text-align: start; cursor: pointer; font: inherit; color: inherit; }
.b-photo { max-width: 100%; border-radius: var(--radius-sm); margin-top: 6px; }
.b-flat { margin: 0; }
.b-block { margin: 8px 0; }
.record-figure.b-sm { font-size: var(--text-lg); }
.b-check-item { padding: 8px 0; border-bottom: 1px solid var(--line-soft); }
.b-check-label { font-weight: 700; margin-bottom: 6px; }

/* month / period navigator (previous, title, next) */
.b-period-nav { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.b-period-title { font-weight: 700; font-size: var(--text-md); text-align: center; }

/* performance: score bar by band, the best-employee card, the coverage line */
.b-meter { height: 8px; border-radius: var(--radius-pill); background: var(--track); overflow: hidden; margin-top: 6px; }
.b-meter-fill { height: 100%; border-radius: var(--radius-pill); }
.b-meter-fill.good { background: var(--brand-face); }
.b-meter-fill.mid { background: var(--data-amber); }
.b-meter-fill.low { background: var(--data-red); }
.b-winner { text-align: center; padding: 6px 0; }
.b-winner-icon { display: flex; justify-content: center; color: var(--brand-face); }
.b-winner-name { font-size: var(--text-lg); }
.money.b-md { font-size: var(--text-xl); }
.b-cover-ok { color: var(--tone-good-ink); }
.b-cover-low { color: var(--tone-bad-ink); }

/* training: the month calendar (an orange-tinted day = a session runs that day; the tint follows the tenant) */
.b-month-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; margin: 8px 0; }
.b-center { text-align: center; }
.b-day { min-height: 48px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm); padding: 2px 4px; font-size: var(--text-xs); overflow: hidden; }
.b-day.busy { background: color-mix(in srgb, var(--orange) 14%, transparent); }
.b-day-item { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* org: a clickable header row, the dashed "add a department" invitation */
.row.b-click { cursor: pointer; }
.b-dashed { display: block; width: 100%; text-align: start; cursor: pointer; margin-bottom: 10px; padding: 12px 14px; border-radius: var(--radius-md); background: transparent; border: 1.6px dashed var(--brand-face); color: var(--brand-face); font: inherit; }

/* DataTable inside a card: scrolls sideways, the page never does */
.b-table-wrap { overflow-x: auto; }
.b-table-wrap .data-table { min-width: 520px; }
.b-table-wrap .data-table td, .b-table-wrap .data-table th { white-space: nowrap; }
.b-narrow { width: auto; max-width: 190px; }
.data-table td.b-end, .data-table th.b-end { text-align: end; }
.b-pre { white-space: pre-wrap; }
.icon-line strong, strong.icon-line { display: inline-flex; align-items: center; gap: 6px; }

/* documents: the viewer frame and image, the download chip */
.b-doc-frame { width: 100%; height: 60vh; border: 1px solid var(--line); border-radius: var(--radius-md); }
.b-doc-img { width: 100%; border-radius: var(--radius-md); }
.b-doc-preview { width: 100%; max-height: 240px; object-fit: contain; border-radius: var(--radius-md); background: var(--card); }
.b-download { margin-top: 8px; display: inline-flex; align-items: center; gap: 4px; }
.b-record-row { padding: 6px 0; border-top: 1px solid var(--line-soft); }

/* catalogue pages and the zoomed page */
.b-catalog-page { width: 100%; border-radius: var(--radius-md); margin-bottom: 10px; background: var(--card); cursor: zoom-in; }
.b-lightbox-img { max-width: 100%; max-height: 100%; border-radius: var(--radius-sm); background: var(--card); touch-action: pinch-zoom; transition: transform .15s ease; transform: scale(1); cursor: zoom-in; }

/* report hub: compact tiles (icon tile, title, star, one line, actions) */
.b-tiles { display: grid; grid-template-columns: 1fr; gap: 12px; margin-bottom: 16px; }
@media (min-width: 600px) { .b-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.b-tiles .card { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.b-tile-head { display: flex; align-items: center; gap: 10px; }
.b-tile-title { flex: 1; min-width: 0; font-size: var(--text-md); }
.b-tile .caption { font-size: var(--text-base); margin: 0; }
.b-tile .row-actions { margin-top: auto; padding-top: 6px; }
.b-star { flex: 0 0 auto; width: 44px; height: 44px; border: 0; background: transparent; color: var(--muted); border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.b-star[aria-pressed='true'] { color: var(--brand-face); }
.b-star[aria-pressed='true'] svg { fill: currentColor; }
.b-search { min-width: 200px; }
.b-grid { display: grid; gap: 6px; }
.b-grid.b-g160 { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 4px; }
.b-grid.b-g180 { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
.b-inline-check { margin-inline-end: 10px; }
.b-filter > .b-grow.b-search { flex: 1 1 200px; }
/* the totals row of a report (a tenant-following ground: --sand is the tenant's background) */
.kashf tfoot td { font-weight: 700; background: var(--sand); }

/* the hidden attribute always wins over a class's display (tabs, rows, cards) */
[hidden] { display: none !important; }

/* settings: the search box, a scrolling tab strip, a compact table, a locked field group */
.b-search-input { width: 100%; margin-bottom: 8px; }
.tabs.b-scroll { overflow-x: auto; }
.tabs.b-scroll button { flex: 0 0 auto; white-space: nowrap; }
.kashf.b-compact { min-width: 0; }
.b-fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }

/* empty states: the kit's plain card; inside a card it stays flat */
.empty { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 28px 16px; margin-bottom: 12px; }
.card .empty, .state-card .empty { background: transparent; border: 0; box-shadow: none; padding: 20px 10px; margin: 0; }

/* talent nine-box: three columns, nested cells flat */
.b-ninebox { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-top: 8px; }
.b-ninebox .card { margin: 0; padding: 8px; box-shadow: none; border: 1px solid var(--line-soft); min-width: 0; overflow-wrap: anywhere; }
/* ── end phase 2B ── */
/* ── phase 2A: people/requests/money ── */
/* A number, plate, code, phone, date or amount never breaks across two lines (the phase 1
   picture split the plate "10-55103"). Bidi isolation stays on .num / .money as before. */
.num, .money, .record-figure { white-space: nowrap; }
.kpi-value .kpi-num.num { white-space: normal; }

/* Screen header: a section header at the top of a screen, with room before the first card */
.screen-head { margin-bottom: 14px; }

/* Empty state: the same white card as every other state (kit rule 10), not loose text on the ground */
.empty {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: 28px 16px; margin-bottom: 12px;
}

/* A button that follows other content inside a card sits 8px below it (was an inline margin per button) */
.card > button:not(:first-child), .sheet > button + button, .row-actions + button { margin-top: 8px; }
.row-actions.start { margin-top: 0; }
.btn-stack { display: grid; gap: 8px; }
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.toolbar > button { width: auto; }
.search-bar { margin-bottom: 10px; }

/* A void record: struck through and dimmed (was an inline style from voidedStyle) */
.voided { opacity: .6; text-decoration: line-through; }

/* A plain row with no divider: the first row of a block, or the head of a card */
.row.bare { border: 0; }
.row.flush { padding-top: 0; }

/* Muted details line under a title inside a card */
.detail-note { color: var(--muted); font-size: var(--text-sm); margin: 4px 0 0; }

/* DataTable look for the older tables (.table): muted header, hairlines, scrolls inside its card */
.table { width: 100%; border-collapse: collapse; font-size: var(--text-base); }
.table th { color: var(--muted); font-weight: 700; text-align: start; padding: 8px 10px; white-space: nowrap; border-bottom: 1px solid var(--line); }
.table td { padding: 10px; border-top: 1px solid var(--line-soft); }
.table td.num, .table th.num { text-align: end; }

.caption.bad { color: var(--tone-bad-ink); }

/* weekly schedule editor rows (employee sheet): label, rest-day box, from/to */
.slot-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.slot-label { min-width: 64px; }
.slot-times { display: flex; gap: 8px; flex: 1 1 220px; min-width: 180px; }
/* a one-time code or password shown large (monospace on purpose: characters must be told apart) */
.code-display { font-size: 26px; font-weight: 800; letter-spacing: 3px; text-align: center; font-family: monospace; direction: ltr; }
.profile-row { padding: 8px 0; border-top: 1px solid var(--line-soft); }
.profile-row .status { margin-inline-start: 8px; }
.profile-progress { width: 100%; }
.chips-end { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

/* advance journey (collapsed stage list on an advance card): a dot per stage, filled when it happened */
.journey { margin-top: 8px; }
.journey summary { cursor: pointer; font-size: var(--text-sm); color: var(--muted); min-height: 44px; display: flex; align-items: center; }
.journey-body { padding: 4px 2px 2px; }
.journey-stage { display: flex; gap: 8px; align-items: flex-start; padding: 6px 0; border-top: 1px solid var(--line-soft); }
.journey-text { flex: 1; min-width: 0; }
.journey-text .faded { opacity: .7; }
.journey-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-top: 6px; flex: 0 0 auto; border: 2px solid var(--muted); background: transparent; }
.journey-dot.done { border-color: var(--brand-face); background: var(--brand-face); }
.journey-dot.rejected { border-color: var(--data-red); background: var(--data-red); }
input.narrow { max-width: 190px; }
.spacer { height: 10px; }
.attachment-preview { width: 100%; max-height: 220px; object-fit: contain; border-radius: var(--radius-md); margin-top: 6px; }
.gap-top { margin-top: 12px; }
.gap-block { margin: 2px 0 8px; }
.nowrap { white-space: nowrap; }
.grow { flex: 1; }

/* custody photos and video (ledger.js): a pair of columns, a grid of tiles, one remove mark per thumbnail */
.check-line { display: block; margin: 0 0 8px; }
.media-pair { display: flex; gap: 10px; align-items: flex-start; margin-top: 8px; }
.media-col { flex: 1; min-width: 0; }
.media-img { width: 100%; border-radius: var(--radius-md); background: var(--card); }
.media-img.tile { aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius-sm); }
.media-img.square { aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-sm); }
.media-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 6px; }
.media-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 0; }
.media-thumb { position: relative; }
.media-remove {
  position: absolute; top: 4px; inset-inline-start: 4px; width: 28px; height: 28px; border-radius: 50%;
  border: 0; background: rgba(0, 0, 0, .6); color: var(--on-brand); display: grid; place-items: center; padding: 0;
}
.media-remove::after { content: ''; position: absolute; inset: -8px; } /* 44px touch target around the 28px mark */
.no-photo { height: 96px; border-radius: var(--radius-md); background: var(--line); display: grid; place-items: center; font-size: var(--text-xs); color: var(--muted); }
.media-video { width: 100%; border-radius: var(--radius-sm); background: #000; }
.block { display: block; }
.date-end { text-align: end; }
.gap-top-sm { margin-top: 6px; }
.kpi-single { margin-bottom: 12px; }
.money.amount-md { font-size: var(--text-lg); }
.amount-bad { font-weight: 700; color: var(--tone-bad-ink); }
.full-row { flex: 1 1 100%; }
.notice-body { margin: 6px 0 0; white-space: pre-wrap; }
.card-pill { margin-top: 8px; }
.card-link { display: block; margin-top: 8px; }
.news-image { width: 100%; max-height: 280px; object-fit: contain; border-radius: var(--radius-md); background: var(--card); }
.card.dim { opacity: .65; }
.figure-line { display: flex; align-items: baseline; gap: 4px; }
.caption.flush { margin: 0; }
.notice-button { width: 100%; text-align: start; border: 0; font: inherit; cursor: pointer; min-height: 44px; }
/* an empty state already inside a card does not draw a second card */
.card .empty { border: 0; box-shadow: none; background: transparent; padding: 16px 8px; margin: 0; }
/* ── end phase 2A ── */
