/* ═══════════════════════════════════════════════════════════════════════════
   ZDA HRM · Design System
   ---------------------------------------------------------------------------
   THE single component library for the whole platform. Every admin/module page
   is built from the shells below — there is no second card, no second table, no
   second hero.

   Canonical prefix ......... .zd-*
   Legacy alias ............. .hse-*   (kept as a SELECTOR ALIAS only — the rule
                                        body is written once, here. 57 views and
                                        3 module stylesheets already ship
                                        .hse-* markup; renaming them is a
                                        separate mechanical pass. Nothing is
                                        defined twice.)

   Accent token ............. --hse-accent / --hse-accent-2
                              Historical name, kept deliberately: 40+ views set
                              it inline (style="--hse-accent:#e11d48") and three
                              module sheets re-point it to recolour the shells.
                              A page picks its accent by setting it on the page
                              root; every shell follows.

   Everything is token-driven (site.css :root + html[data-theme="modern"]), so
   light/dark, RTL/LTR and fa/ru all fall out of the same rules.
   Loaded globally from _Layout.cshtml, right after site.css.

   HOW TO ASSEMBLE A PAGE ... docs/design-system.md
                              Admin modules with statistics, filters and
                              navigation MUST follow the Admin Console layout:
                              hero → nav tabs → KPI cards → action toolbar →
                              filter panel → data grid, in that order, never
                              merged. Reference: Views/Hse/Vehicles.cshtml.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Accent (module colour) ─────────────────────────────────────────────
     Default stays teal so the clinic/HSE pages that rely on the root value
     keep their identity. .zd-page re-points it to brand blue. */
  --hse-accent: #0d9488;
  --hse-accent-2: #0891b2;
  --hse-ink: var(--text);
  --hse-soft: var(--text-soft);

  /* ── Spacing scale — 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 ──────────────── */
  --zd-1: .25rem;
  --zd-2: .5rem;
  --zd-3: .75rem;
  --zd-4: 1rem;
  --zd-5: 1.5rem;
  --zd-6: 2rem;
  --zd-7: 3rem;
  --zd-8: 4rem;

  /* ── Radius scale ─────────────────────────────────────────────────────── */
  --zd-r-xs: .5rem;    /* chips inside dense rows           */
  --zd-r-sm: .75rem;   /* inputs, buttons, small tiles      */
  --zd-r-md: 1rem;     /* nested panels, stat tiles         */
  --zd-r-lg: 1.35rem;  /* surfaces / cards                  */
  --zd-r-xl: 1.6rem;   /* hero                              */
  --zd-r-pill: 999px;

  /* ── Elevation ────────────────────────────────────────────────────────── */
  --zd-shadow-sm: 0 6px 18px rgba(15, 23, 42, .06);
  --zd-shadow-md: 0 18px 40px rgba(15, 23, 42, .08);
  --zd-shadow-lg: 0 26px 58px rgba(15, 23, 42, .16);
  /* Legacy aliases used by hse.css / reports-builder.css. */
  --hse-card-shadow: var(--zd-shadow-md);
  --hse-card-shadow-sm: var(--zd-shadow-sm);

  /* ── Typography scale ─────────────────────────────────────────────────── */
  --zd-display: clamp(1.5rem, 2vw, 2.1rem);
  --zd-h1: 1.5rem;
  --zd-h2: 1.15rem;
  --zd-h3: 1rem;
  --zd-title: .98rem;
  --zd-body: .95rem;
  --zd-label: .85rem;
  --zd-caption: .8rem;
  --zd-micro: .76rem;

  /* ── Readable "text on a tinted chip" recipe ───────────────────────────────
     A status colour used as-is for TEXT on its own 12–14% tint fails WCAG AA
     (e.g. #f59e0b on an amber tint is 2.3:1). Pulling the hue 55% toward the
     page's text colour keeps the semantic hue but lands ≥4.5:1 — and because it
     mixes toward --text it inverts correctly in the dark theme, where the tint
     is dark and the label must be light. */
  --zd-on-tint-mix: 45%;
  --zd-danger-text: color-mix(in srgb, var(--danger) 65%, var(--text));
  /* How far an outline-button label is pulled toward --text. Light theme needs a
     small nudge (the hue is already dark enough); the dark theme needs a big one
     to lift the hue off a near-black surface. */
  --zd-btn-mix: 85%;
}

html[data-theme="modern"] {
  /* Dark surfaces need the LABEL to stay light, i.e. LESS of the hue and more of
     --text (which is light in this theme). */
  --zd-btn-mix: 52%;
  --zd-on-tint-mix: 32%;
}

html[data-theme="modern"] {
  --zd-shadow-sm: 0 6px 18px rgba(2, 6, 23, .4);
  --zd-shadow-md: 0 18px 40px rgba(2, 6, 23, .5);
  --zd-shadow-lg: 0 26px 58px rgba(2, 6, 23, .6);
}

/* ═══════════════════════════════════════════════════════════════════════════
   1 · PAGE SHELL
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-page,
.hse-page {
  display: grid;
  /* minmax(0,1fr), not the implicit `auto` track. An auto track is sized to the
     MAX-CONTENT of its items, so one wide table (or a long unbreakable string)
     drags the whole page wider than the shell — and since .app-content clips
     overflow-x, the surplus is amputated rather than scrolled: on /OrganizationForms
     at 1366px the grid measured 1113px inside a 1038px column and the last table
     columns simply could not be reached. Pinning the track to the container makes
     .zd-tablewrap do its job and scroll instead. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--zd-4);
  padding: var(--zd-4) var(--zd-4) var(--zd-6);
  /* Pin the inherited text colour to the token. <body> still carries a literal
     light-theme colour, so un-styled descendants (a bare <strong>, <span>, <li>)
     were inheriting dark-on-dark in the "modern" theme. */
  color: var(--text);
}
@media (min-width: 1200px) {
  .zd-page,
  .hse-page { padding-inline: var(--zd-5); }
}

/* Brand-blue accent is the platform default; clinic/HSE pages keep teal via
   the :root value, module pages override --hse-accent themselves. */
.zd-page { --hse-accent: var(--brand); --hse-accent-2: #4f46e5; }

/* ── Breadcrumb ─────────────────────────────────────────────────────────── */
.zd-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zd-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--zd-caption);
}
.zd-breadcrumb__item { display: inline-flex; align-items: center; gap: var(--zd-2); }
.zd-breadcrumb__item a { color: inherit; text-decoration: none; opacity: .82; }
.zd-breadcrumb__item a:hover { color: inherit; opacity: 1; text-decoration: underline; }
.zd-breadcrumb__item[aria-current="page"] { font-weight: 700; }
.zd-breadcrumb__sep { opacity: .55; }
/* Inside the hero the crumbs sit on the gradient, so they inherit white. */
.zd-hero .zd-breadcrumb { color: rgba(255, 255, 255, .86); }

/* ═══════════════════════════════════════════════════════════════════════════
   2 · HERO
   Identical geometry on every page: same radius, same padding, same height
   rhythm, title + subtitle on the start side, actions on the end side.
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-hero,
.hse-hero {
  position: relative;
  overflow: hidden;
  display: grid;
  /* The action track used to be `minmax(15rem, auto)` against a `minmax(0, …)` copy
     track: with six buttons — and Russian labels are half again as long as the Persian
     ones — `auto` grew until the title had almost no width left and broke one word per
     line. Both tracks now have a real floor and the actions are capped at a share of the
     row, so long labels wrap inside their own column instead of eating the headline. */
  grid-template-columns: minmax(min(20rem, 100%), 1.7fr) minmax(min(15rem, 100%), 0.9fr);
  gap: var(--zd-4);
  padding: var(--zd-5);
  border-radius: var(--zd-r-xl);
  color: #fff;
  border: 1px solid color-mix(in srgb, var(--hse-accent) 30%, rgba(255, 255, 255, .7));
  background:
    radial-gradient(circle at 12% -10%, color-mix(in srgb, var(--hse-accent) 35%, #fff) 0, transparent 42%),
    linear-gradient(135deg, color-mix(in srgb, var(--hse-accent) 92%, #042f2e), color-mix(in srgb, var(--hse-accent-2) 78%, var(--brand)));
  box-shadow: 0 26px 58px color-mix(in srgb, var(--hse-accent) 22%, transparent);
}
.zd-hero::after,
.hse-hero::after {
  content: "";
  position: absolute;
  inset-inline-end: -3rem;
  inset-block-start: -3rem;
  width: 13rem;
  height: 13rem;
  border-radius: var(--zd-r-pill);
  background: rgba(255, 255, 255, .09);
  pointer-events: none;
}
/* Hero WITHOUT an action column. The Admin Console layout moves every action into
   the toolbar (section 5), so a hero that keeps only copy would otherwise leave the
   15rem action track standing empty. This collapses the grid to one column. */
.zd-hero--plain,
.hse-hero--plain { grid-template-columns: minmax(0, 1fr); }

.zd-hero__main,
.hse-hero__main {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--zd-3);
  align-content: center;
}
.zd-hero__eyebrow,
.hse-hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-2);
  width: fit-content;
  padding: var(--zd-1) var(--zd-3);
  border-radius: var(--zd-r-pill);
  font-size: var(--zd-caption);
  font-weight: 700;
  background: rgba(255, 255, 255, .16);
  border: 1px solid rgba(255, 255, 255, .2);
}
.zd-hero__eyebrow svg,
.hse-hero__eyebrow svg { width: 1.05rem; height: 1.05rem; }
.zd-hero__title,
.hse-hero__title {
  margin: 0;
  font-size: var(--zd-display);
  font-weight: 900;
  color: #fff;
}
.zd-hero__subtitle,
.hse-hero__subtitle {
  margin: 0;
  max-width: 46rem;
  color: rgba(255, 255, 255, .86);
  line-height: 1.85;
  font-size: var(--zd-body);
}
/* Status/metadata badges under the hero copy (Dashboard parity). */
.zd-hero__meta { display: flex; flex-wrap: wrap; gap: var(--zd-2); }
.zd-hero__badge {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-1);
  padding: var(--zd-1) var(--zd-3);
  border-radius: var(--zd-r-pill);
  font-size: var(--zd-micro);
  font-weight: 700;
  background: rgba(255, 255, 255, .16);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff;
}
.zd-hero__badge--solid { background: #fff; color: color-mix(in srgb, var(--hse-accent) 65%, #000); border-color: #fff; }

.zd-hero__actions,
.hse-hero__actions {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--zd-2);
  align-items: center;
  justify-content: flex-end;
  align-content: flex-start;
}
.zd-hero__btn,
.hse-hero__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-1);
  min-height: 2.7rem;
  padding-inline: var(--zd-4);
  border-radius: var(--zd-r-pill);
  font-weight: 700;
  font-size: var(--zd-label);
  border: 1px solid rgba(255, 255, 255, .3);
  background: rgba(255, 255, 255, .15);
  color: #fff;
  text-decoration: none;
  transition: background var(--duration-fast) var(--easing), transform var(--duration-fast) var(--easing);
}
.zd-hero__btn:hover,
.hse-hero__btn:hover { color: #fff; background: rgba(255, 255, 255, .26); transform: translateY(-1px); }
/* Always a DARK label on the white pill — the raw accent is too light on white
   in the dark theme (measured 2.65:1). */
.zd-hero__btn--solid,
.hse-hero__btn--solid { background: #fff; color: color-mix(in srgb, var(--hse-accent) 65%, #000); border-color: #fff; }
.zd-hero__btn--solid:hover,
.hse-hero__btn--solid:hover { background: #fff; color: color-mix(in srgb, var(--hse-accent) 65%, #000); }
.zd-hero__btn svg,
.hse-hero__btn svg { width: 1.05rem; height: 1.05rem; flex: 0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════
   3 · STAT CARDS
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-stats,
.hse-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--zd-3);
}
.zd-stats--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.zd-stats--auto { grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
@media (max-width: 991px) {
  .zd-stats,
  .hse-stats,
  .zd-stats--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .zd-stats,
  .hse-stats,
  .zd-stats--3 { grid-template-columns: 1fr; }
}

.zd-stat,
.hse-stat {
  display: flex;
  gap: var(--zd-3);
  align-items: center;
  padding: var(--zd-4);
  border-radius: var(--zd-r-md);
  background: var(--surface-1);
  border: 1px solid var(--border);
  box-shadow: var(--zd-shadow-sm);
  position: relative;
  overflow: hidden;
}
.zd-stat::before,
.hse-stat::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: .28rem;
  background: var(--hse-stat-c, var(--brand));
}
.zd-stat__icon,
.hse-stat__icon {
  width: 2.9rem;
  height: 2.9rem;
  border-radius: var(--zd-r-sm);
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  color: var(--hse-stat-c, var(--brand));
  /* surface-1 (not #fff) so the tint stays legible in the dark theme too. */
  background: color-mix(in srgb, var(--hse-stat-c, var(--brand)) 14%, var(--surface-1));
}
.zd-stat__icon svg,
.hse-stat__icon svg { width: 1.4rem; height: 1.4rem; }
.zd-stat__copy,
.hse-stat__copy { min-width: 0; display: grid; gap: .15rem; }
/* Amounts spelled out in Persian words ("دویست و نود و پنج میلیارد …") and long
   grouped numerals have no break opportunity, so they pushed straight out of the
   tile. Break them anywhere rather than overflow the card. */
.zd-stat__label,
.hse-stat__label { color: var(--text-soft); font-size: var(--zd-caption); overflow-wrap: anywhere; }
.zd-stat__value,
.hse-stat__value { font-size: var(--zd-h1); font-weight: 800; line-height: 1.1; color: var(--text); overflow-wrap: anywhere; }
.zd-stat__hint,
.hse-stat__hint { color: var(--text-soft); font-size: var(--zd-micro); overflow-wrap: anywhere; }

.zd-stat--brand,  .hse-stat--brand  { --hse-stat-c: var(--brand); }
.zd-stat--teal,   .hse-stat--teal   { --hse-stat-c: #0d9488; }
.zd-stat--ok,     .hse-stat--ok     { --hse-stat-c: var(--ok); }
.zd-stat--warn,   .hse-stat--warn   { --hse-stat-c: var(--warn); }
.zd-stat--danger, .hse-stat--danger { --hse-stat-c: var(--danger); }
.zd-stat--info,   .hse-stat--info   { --hse-stat-c: var(--info); }
.zd-stat--violet, .hse-stat--violet { --hse-stat-c: #7c3aed; }
.zd-stat--slate,  .hse-stat--slate  { --hse-stat-c: #64748b; }

/* Clickable stat (filter tile). Works as <a> or <button>. */
.zd-stat--link,
.hse-statcard {
  text-decoration: none;
  color: inherit;
  transition: transform var(--duration-fast) var(--easing), box-shadow var(--duration-fast) var(--easing);
}
.zd-stat--link:hover,
.hse-statcard:hover { transform: translateY(-2px); box-shadow: var(--zd-shadow-md); color: inherit; }
.zd-stat--active,
.hse-statcard--active { outline: 2px solid var(--hse-accent); outline-offset: 1px; }

/* A shell rendered as a real <button>: strip UA chrome so it is pixel-identical
   to the <div>/<a> version while staying keyboard-operable. */
button.zd-stat, button.zd-tab, button.zd-chip,
button.hse-stat, button.hse-tab, button.hse-chip {
  font: inherit;
  text-align: start;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
button.zd-stat, button.hse-stat { color: inherit; }
button.zd-stat, button.hse-stat {
  transition: transform var(--duration-fast) var(--easing), box-shadow var(--duration-fast) var(--easing);
}
button.zd-stat:hover, button.hse-stat:hover { transform: translateY(-2px); box-shadow: var(--zd-shadow-md); }

/* Compact numeric tile (no icon) — register/summary headers. */
.zd-tiles,
.hse-riskgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--zd-3); }
.zd-tile,
.hse-riskstat {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-md);
  padding: var(--zd-3) var(--zd-4);
  box-shadow: var(--zd-shadow-sm);
}
.zd-tile__value,
.hse-riskstat__val { font-size: 1.7rem; font-weight: 900; line-height: 1; color: var(--text); }
.zd-tile__label,
.hse-riskstat__label { font-size: var(--zd-micro); color: var(--text-soft); margin-top: var(--zd-1); font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════════════════
   4 · SURFACE (the one and only card)
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-surface,
.hse-surface {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-lg);
  box-shadow: var(--zd-shadow-md);
  overflow: hidden;
}
.zd-surface__head,
.hse-surface__head {
  display: flex;
  align-items: center;
  gap: var(--zd-3);
  justify-content: space-between;
  flex-wrap: wrap;
  padding: var(--zd-4) var(--zd-5);
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
}
.zd-surface__titles { min-width: 0; }
.zd-surface__title,
.hse-surface__title {
  margin: 0;
  font-size: var(--zd-h3);
  font-weight: 800;
  display: inline-flex;
  align-items: center;
  gap: var(--zd-2);
  color: var(--text);
}
.zd-surface__title svg,
.hse-surface__title svg { width: 1.15rem; height: 1.15rem; color: var(--hse-accent); flex: 0 0 auto; }
.zd-surface__sub,
.hse-surface__sub { margin: .15rem 0 0; color: var(--text-soft); font-size: var(--zd-caption); line-height: 1.7; }
.zd-surface__tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--zd-2); }
.zd-surface__body,
.hse-surface__body { padding: var(--zd-5); }
.zd-surface__body--flush,
.hse-surface__body--flush { padding: 0; }
.zd-surface__body--tight { padding: var(--zd-4); }

/* A surface whose head is a <summary>, i.e. the whole card collapses. Same
   disclosure affordances as .zd-details, applied to the full-size shell. */
.zd-surface > summary.zd-surface__head { cursor: pointer; list-style: none; }
.zd-surface > summary.zd-surface__head::-webkit-details-marker { display: none; }
.zd-surface > summary.zd-surface__head::after {
  content: "▾";
  opacity: .6;
  margin-inline-start: var(--zd-2);
}
.zd-surface[open] > summary.zd-surface__head::after { content: "▴"; }
.zd-surface > summary.zd-surface__head:hover { background: var(--surface-2); }
.zd-surface > summary.zd-surface__head:focus-visible { outline: 2px solid var(--hse-accent); outline-offset: -2px; }
/* Collapsed: the head is the only visible child, so drop its divider rule. */
.zd-surface:not([open]) > summary.zd-surface__head { border-bottom: 0; }
/* A status pill in a COLLAPSIBLE head has to be pushed to the end itself. The ::after
   chevron makes the header a three-item flex row, and space-between then parks the pill
   in the middle of the card with the title stranded on the far side. (A plain
   div.zd-surface__head has only two children, so it never had this problem.) */
.zd-surface > summary.zd-surface__head > .zd-pill { margin-inline-start: auto; }

/* A surface that hosts a dropdown / popover cannot clip its children, or the
   menu is cut off at the card edge. Overflow goes visible and the first/last
   children re-apply the corner rounding that overflow:hidden used to provide. */
.zd-surface--popover { overflow: visible; }
.zd-surface--popover > :first-child {
  border-start-start-radius: var(--zd-r-lg);
  border-start-end-radius: var(--zd-r-lg);
}
.zd-surface--popover > :last-child {
  border-end-start-radius: var(--zd-r-lg);
  border-end-end-radius: var(--zd-r-lg);
}
/* Second body block inside the same surface — rule instead of an inline border. */
.zd-surface__body--divided { border-top: 1px solid var(--border); }
.zd-surface__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zd-2);
  padding: var(--zd-3) var(--zd-5);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

/* Section icon badge, shared by surface heads and form sections. */
.zd-surface__icon,
.zd-form__section-icon,
.hse-form__section-icon {
  width: 2.1rem;
  height: 2.1rem;
  border-radius: var(--zd-r-xs);
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  color: var(--hse-accent);
  background: color-mix(in srgb, var(--hse-accent) 14%, var(--surface-1));
}
.zd-surface__icon svg,
.zd-form__section-icon svg,
.hse-form__section-icon svg { width: 1.2rem; height: 1.2rem; }

/* ── Layout grids ───────────────────────────────────────────────────────── */
.zd-grid-2,
.hse-grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: var(--zd-4); }
.zd-grid-even { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--zd-4); }
.zd-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--zd-4); }
/* Narrow settings column + wide working area (1 : 2). */
.zd-grid-sidebar { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--zd-4); align-items: start; }
.zd-grid-auto { display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); gap: var(--zd-4); }
@media (max-width: 991px) {
  .zd-grid-2, .hse-grid-2,
  .zd-grid-even,
  .zd-grid-sidebar,
  .zd-grid-3 { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   5 · TOOLBAR
   One structure everywhere: [primary actions] [secondary] … [search] [filters]
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zd-2);
  padding: var(--zd-3) var(--zd-5);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.zd-toolbar--flush { padding-inline: 0; background: transparent; border-bottom: 0; }
/* STANDALONE toolbar. In the Admin Console layout the action bar is its own band
   between the KPI row and the filter panel — it is not nested in a surface, so it
   carries its own border, radius and elevation instead of a single bottom rule. */
.zd-toolbar--card {
  padding: var(--zd-3) var(--zd-4);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-lg);
  box-shadow: var(--zd-shadow-sm);
}
/* Label that names the cluster to its side ("عملیات:" / "خروجی:"). */
.zd-toolbar__label {
  font-size: var(--zd-micro);
  font-weight: 700;
  color: var(--text-soft);
  white-space: nowrap;
}
/* Hairline between two action clusters inside one toolbar. */
.zd-toolbar__divider {
  width: 1px;
  align-self: stretch;
  min-height: 1.6rem;
  background: var(--border);
}
.zd-toolbar__group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--zd-2); }
.zd-toolbar__spacer { flex: 1 1 auto; }
.zd-toolbar__search {
  display: flex;
  align-items: center;
  gap: var(--zd-2);
  flex: 1 1 18rem;
  min-width: min(100%, 14rem);
  margin: 0;
}
.zd-toolbar__search .form-control { flex: 1 1 auto; }
.zd-toolbar__count {
  font-size: var(--zd-caption);
  color: var(--text-soft);
  white-space: nowrap;
}

/* Search field with a leading icon. */
.zd-search { position: relative; flex: 1 1 18rem; min-width: min(100%, 14rem); }
.zd-search input { padding-inline-start: 2.4rem; }
.zd-search__icon {
  position: absolute;
  inset-inline-start: .8rem;
  inset-block-start: 50%;
  transform: translateY(-50%);
  width: 1.05rem;
  height: 1.05rem;
  color: var(--text-soft);
  pointer-events: none;
}

/* ── Filter grid (12 columns, declarative spans) ─────────────────────────── */
.zd-filter,
.hse-filter {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--zd-3);
  align-items: end;
}
.zd-filter .form-label,
.hse-filter .form-label {
  font-size: var(--zd-caption);
  color: var(--text-soft);
  margin-bottom: var(--zd-1);
  font-weight: 600;
}
.zd-filter .form-control, .zd-filter .form-select,
.hse-filter .form-control, .hse-filter .form-select { border-radius: var(--zd-r-sm); }
.zd-filter__actions,
.hse-filter__actions { display: flex; gap: var(--zd-2); flex-wrap: wrap; }
/* Filter buttons are for clicking, not for filling a track. Left to stretch,
   a two-button action cell became a 370px slab on a 27" screen. */
.zd-filter__actions > .btn,
.hse-filter__actions > .btn { flex: 0 1 auto; max-width: 14rem; }
/* The "until end of month" checkbox that site.js injects next to a date range —
   its own cell, so it never inflates the date field's cell (see site.js). */
.zd-filter__endmonth { grid-column: span 3; align-self: end; padding-bottom: var(--zd-2); }
.zd-filter__col,     .hse-filter__col    { grid-column: span 12; }
.zd-filter__col--2,  .hse-filter__col--2 { grid-column: span 2; }
.zd-filter__col--3,  .hse-filter__col--3 { grid-column: span 3; }
.zd-filter__col--4,  .hse-filter__col--4 { grid-column: span 4; }
.zd-filter__col--5                       { grid-column: span 5; }
.zd-filter__col--6,  .hse-filter__col--6 { grid-column: span 6; }
.zd-filter__col--8,  .hse-filter__col--8 { grid-column: span 8; }

/* ═══════════════════════════════════════════════════════════════════════════
   6 · TABS · CHIPS
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-tabs,
.hse-tabs { display: flex; flex-wrap: wrap; gap: var(--zd-2); }
.zd-tabs--bar {
  padding: var(--zd-3) var(--zd-5);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.zd-tab,
.hse-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-2);
  padding: var(--zd-2) var(--zd-4);
  border-radius: var(--zd-r-pill);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-soft);
  font-weight: 700;
  font-size: var(--zd-label);
  text-decoration: none;
  transition: color var(--duration-fast) var(--easing),
              border-color var(--duration-fast) var(--easing),
              background var(--duration-fast) var(--easing);
}
.zd-tab svg, .hse-tab svg { width: 1rem; height: 1rem; flex: 0 0 auto; }
.zd-tab:hover,
.hse-tab:hover { color: var(--hse-accent); border-color: var(--hse-accent); }
/* Inside a tab BAR the rest sits on --surface-2, so idle tabs lift to --surface-1.
   Scoped with :not(active) — otherwise this more-specific rule would repaint the
   selected tab white and leave its white label unreadable. */
.zd-tabs--bar .zd-tab:not(.zd-tab--active):not(.active):not(.is-active):not([aria-selected="true"]) {
  background: var(--surface-1);
}
/* ── Module navigation bar ───────────────────────────────────────────────────
   Step 2 of the Admin Console layout: the bar that moves between a module's
   SIBLING PAGES (خودروها / مدارک / پیمانکاران / API). It is deliberately a
   different shell from .zd-tabs--bar, which switches between VIEWS OF THE SAME
   DATA inside a surface — one answers "where am I?", the other "which slice?".

   Idle tabs stay transparent so only the current page carries weight; the
   :not() chain mirrors .zd-tabs--bar so the active tab keeps its accent fill. */
.zd-navtabs {
  padding: var(--zd-2);
  border-radius: var(--zd-r-lg);
  background: var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: var(--zd-shadow-sm);
}
.zd-navtabs .zd-tab:not(.zd-tab--active):not(.active):not(.is-active):not([aria-selected="true"]) {
  background: transparent;
  border-color: transparent;
}
.zd-navtabs .zd-tab:not(.zd-tab--active):not(.active):not(.is-active):not([aria-selected="true"]):hover {
  background: var(--surface-1);
  border-color: var(--hse-accent);
}

/* `.is-active` is the permission grids' state class (roles + users access editors). It is listed
   here so those tabs are ordinary design-system tabs rather than relying on a bespoke rule that
   the :not() chain above outranks. */
.zd-tab--active, .zd-tab.active, .zd-tab.is-active, .zd-tab[aria-selected="true"],
.zd-tabs--bar .zd-tab--active,
.zd-tabs--bar .zd-tab.active,
.zd-tabs--bar .zd-tab.is-active,
.zd-tabs--bar .zd-tab[aria-selected="true"],
.hse-tab--active { background: var(--hse-accent); border-color: var(--hse-accent); color: #fff; }
.zd-tab__count,
.hse-tab__count {
  min-width: 1.4rem;
  height: 1.4rem;
  padding: 0 var(--zd-1);
  border-radius: var(--zd-r-pill);
  display: inline-grid;
  place-items: center;
  font-size: var(--zd-micro);
  font-weight: 800;
  background: color-mix(in srgb, var(--text) 12%, transparent);
}
/* Solid white chip with accent text, NOT translucent white on the accent fill —
   white-on-lightened-accent measured 2.9:1 and failed AA. */
.zd-tab--active .zd-tab__count,
.zd-tab.active .zd-tab__count,
.zd-tab[aria-selected="true"] .zd-tab__count,
.hse-tab--active .hse-tab__count { background: #fff; color: color-mix(in srgb, var(--hse-accent) 60%, #000); }
.zd-tab__count--danger { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--zd-danger-text); }
.zd-tab--active .zd-tab__count--danger,
.zd-tab[aria-selected="true"] .zd-tab__count--danger { background: #fff; color: var(--danger); }

/* Tab panels driven by the shared controller in site.js. */
.zd-tabpanel[hidden] { display: none !important; }

.zd-chips,
.hse-chips { display: flex; flex-wrap: wrap; gap: var(--zd-1); }
.zd-chip,
.hse-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-1);
  padding: var(--zd-1) var(--zd-3);
  border-radius: var(--zd-r-pill);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--zd-caption);
  text-decoration: none;
  transition: all var(--duration-fast) var(--easing);
}
.zd-chip:hover,
.hse-chip:hover {
  background: color-mix(in srgb, var(--hse-accent) 12%, var(--surface-1));
  border-color: var(--hse-accent);
  color: var(--hse-accent);
}
.zd-chip svg, .hse-chip svg { width: .9rem; height: .9rem; opacity: .7; }
.zd-chip--active, .zd-chip--active:hover,
.hse-chip--active, .hse-chip--active:hover {
  background: var(--hse-accent);
  border-color: var(--hse-accent);
  color: #fff;
}

/* ═══════════════════════════════════════════════════════════════════════════
   7 · TABLE
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-tablewrap,
.hse-tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.zd-table,
.hse-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  margin: 0;
  font-size: var(--zd-label);
}
.zd-table thead th,
.hse-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-2);
  color: var(--text-soft);
  font-weight: 700;
  font-size: var(--zd-caption);
  text-align: start;
  padding: var(--zd-3) var(--zd-4);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.zd-table tbody td,
.hse-table tbody td {
  padding: var(--zd-3) var(--zd-4);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  color: var(--text);
}
.zd-table tbody tr:last-child td,
.hse-table tbody tr:last-child td { border-bottom: 0; }
.zd-table tbody tr:hover td,
.hse-table tbody tr:hover td { background: var(--surface-2); }
.zd-table--dense tbody td,
.zd-table--dense thead th { padding: var(--zd-2) var(--zd-3); }
.zd-table tfoot td { padding: var(--zd-3) var(--zd-4); background: var(--surface-2); font-weight: 700; }

/* Sortable column header — the one sorting affordance in the app. */
.zd-table__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-1);
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}
.zd-table__sort:hover { color: var(--hse-accent); }
.zd-table__sort-arrow { font-size: .7em; color: var(--hse-accent); }
.zd-table__sort[aria-sort="none"] .zd-table__sort-arrow { opacity: 0; }
.zd-table__sort:hover .zd-table__sort-arrow { opacity: .5; }
.zd-table__sort[aria-sort="ascending"] .zd-table__sort-arrow,
.zd-table__sort[aria-sort="descending"] .zd-table__sort-arrow { opacity: 1; }

/* Row helpers */
.zd-table__idx, .zd-muted, .hse-muted { color: var(--text-soft); }
.zd-nowrap { white-space: nowrap; }
.zd-table__num { font-variant-numeric: tabular-nums; }
.zd-row-danger td { background: color-mix(in srgb, var(--danger) 7%, transparent) !important; }
.zd-row-warn td { background: color-mix(in srgb, var(--warn) 9%, transparent) !important; }

.zd-actions,
.hse-actions { display: inline-flex; flex-wrap: wrap; gap: var(--zd-1); align-items: center; }
.zd-actions form { margin: 0; }
/* Inside a table the action cluster must NOT wrap: a column squeezed by wide
   neighbours would stack its buttons, making that row taller than the rest and
   the whole table ragged. The row keeps one line and .zd-tablewrap scrolls
   horizontally instead — the same trade-off the wide tables already make. */
.zd-table .zd-actions,
.zd-table .hse-actions { flex-wrap: nowrap; }
.zd-table td:last-child { white-space: nowrap; }

/* Inline disclosure form inside a table row (reset password, quick edit).
   Revealed by the shared [data-rowtoggle] handler in site.js. */
.zd-rowform {
  margin-top: var(--zd-2);
  padding: var(--zd-2);
  max-width: 18rem;
  border: 1px solid var(--border);
  border-radius: var(--zd-r-sm);
  background: var(--surface-2);
}
.zd-rowform__row { display: flex; gap: var(--zd-1); align-items: center; }
.zd-rowform__stack { display: grid; gap: var(--zd-1); }

/* Repeating input rows — visitors, vehicles, line items: a group the user adds to and
   removes from, each row holding a full .zd-fields grid.
   This exists because such groups used to be wrapped in .zd-rowform, whose 18rem cap is
   right for the one-input-plus-button forms that live inside a table cell and wrong here:
   it squeezed a five-field row into a single narrow column with unusable inputs. */
.zd-rowset { display: grid; gap: var(--zd-2); }
.zd-rowset__row {
  padding: var(--zd-3);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-sm);
  background: var(--surface-2);
}
.zd-rowset__row + .zd-rowset__row { margin: 0; }
/* Tighter than a page form: these columns are narrow by design. */
.zd-rowset__row .zd-fields { gap: var(--zd-2) var(--zd-3); }
/* The row's button sits on the inputs' baseline instead of under a blank label. */
.zd-field--action { align-self: end; }
.zd-field--action .btn { width: 100%; }

/* Two-line cell: strong title + muted meta. */
.zd-cell { display: grid; gap: .1rem; min-width: 0; }
.zd-cell__title { font-weight: 600; color: var(--text); }
.zd-cell__meta { font-size: var(--zd-micro); color: var(--text-soft); }

/* Person cell with avatar/initial. */
.zd-person,
.hse-table .hse-person { display: inline-flex; align-items: center; gap: var(--zd-2); font-weight: 600; }
.zd-person__avatar,
.hse-table .hse-person__avatar {
  width: 2rem;
  height: 2rem;
  border-radius: var(--zd-r-pill);
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  object-fit: cover;
  background: color-mix(in srgb, var(--hse-accent) 16%, var(--surface-1));
  color: var(--hse-accent);
  font-weight: 800;
  font-size: var(--zd-caption);
}
.zd-person__avatar--lg { width: 3rem; height: 3rem; font-size: var(--zd-label); }
/* Profile-sized avatar used on account/profile screens. */
.zd-avatar-xl {
  width: 5rem;
  height: 5rem;
  border-radius: var(--zd-r-pill);
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  object-fit: cover;
  background: color-mix(in srgb, var(--hse-accent) 14%, var(--surface-1));
  color: var(--hse-accent);
  border: 2px solid var(--border);
}
.zd-person a,
.hse-table .hse-person a { color: var(--text); text-decoration: none; }
.zd-person a:hover,
.hse-table .hse-person a:hover { color: var(--brand); text-decoration: underline; }

/* Click-to-copy chip (device id, token, user-agent) + brief "copied" feedback.
   Driven by the delegated [data-copy-text] handler in site.js. */
.zd-copy { cursor: pointer; border-bottom: 1px dashed color-mix(in srgb, var(--text-soft) 70%, transparent); }
.zd-copy:hover { color: var(--hse-accent); }
.zd-copy:focus-visible { outline: 2px solid var(--hse-accent); outline-offset: 2px; }
.zd-copied { background: var(--ok) !important; color: #fff !important; border-radius: var(--zd-r-xs); }
/* Full, selectable/wrapping cell for long values (user-agent strings). */
.zd-ua {
  display: inline-block;
  max-width: 24rem;
  white-space: normal;
  word-break: break-word;
  user-select: text;
}

/* Monospace identifier (IP, device id, token). */
.zd-mono {
  font-family: var(--font-mono);
  font-size: var(--zd-micro);
  direction: ltr;
  unicode-bidi: isolate;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-xs);
  padding: .1rem .4rem;
  display: inline-block;
}

/* ── Pagination ─────────────────────────────────────────────────────────── */
.zd-pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--zd-2);
  padding: var(--zd-3) var(--zd-5);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.zd-pager__info { font-size: var(--zd-caption); color: var(--text-soft); }
.zd-pager__btns { display: flex; flex-wrap: wrap; gap: var(--zd-1); }
.zd-pager__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.2rem;
  min-height: 2.2rem;
  padding: 0 var(--zd-3);
  border-radius: var(--zd-r-sm);
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text);
  font-size: var(--zd-caption);
  font-weight: 700;
  text-decoration: none;
  transition: all var(--duration-fast) var(--easing);
}
.zd-pager__btn:hover { border-color: var(--hse-accent); color: var(--hse-accent); }
.zd-pager__btn--active,
.zd-pager__btn--active:hover {
  background: var(--hse-accent);
  border-color: var(--hse-accent);
  color: #fff;
}
.zd-pager__btn.is-disabled,
.zd-pager__btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.zd-pager__gap { align-self: center; padding-inline: var(--zd-1); color: var(--text-soft); }

/* ═══════════════════════════════════════════════════════════════════════════
   8 · PILLS / STATUS BADGES
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-pill,
.hse-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--zd-1);
  padding: var(--zd-1) var(--zd-3);
  border-radius: var(--zd-r-pill);
  font-size: var(--zd-micro);
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
  background: color-mix(in srgb, var(--zd-pill-c, #64748b) 14%, var(--surface-1));
  color: color-mix(in srgb, var(--zd-pill-c, #64748b) var(--zd-on-tint-mix), var(--text));
  border: 1px solid color-mix(in srgb, var(--zd-pill-c, #64748b) 26%, transparent);
}
.zd-pill svg, .hse-pill svg { width: .85rem; height: .85rem; }
.zd-pill--ok,     .hse-pill--ok     { --zd-pill-c: var(--ok);      --hse-pill-c: var(--ok); }
.zd-pill--warn,   .hse-pill--warn   { --zd-pill-c: var(--warn);    --hse-pill-c: var(--warn); }
.zd-pill--danger, .hse-pill--danger { --zd-pill-c: var(--danger);  --hse-pill-c: var(--danger); }
.zd-pill--info,   .hse-pill--info   { --zd-pill-c: var(--info);    --hse-pill-c: var(--info); }
.zd-pill--brand,  .hse-pill--brand  { --zd-pill-c: var(--brand);   --hse-pill-c: var(--brand); }
.zd-pill--muted,  .hse-pill--muted  { --zd-pill-c: #64748b;        --hse-pill-c: #64748b; }
.zd-pill--teal,   .hse-pill--teal   { --zd-pill-c: #0d9488;        --hse-pill-c: #0d9488; }
.zd-pill--violet                    { --zd-pill-c: #7c3aed; }
.zd-pill--accent                    { --zd-pill-c: var(--hse-accent); }
/* .hse-pill kept reading its own variable so inline --hse-pill-c still works. */
.hse-pill { --zd-pill-c: var(--hse-pill-c, #64748b); }

/* Solid counter badge (e.g. "3 مورد"). */
.zd-count {
  display: inline-grid;
  place-items: center;
  min-width: 1.6rem;
  height: 1.6rem;
  padding: 0 var(--zd-2);
  border-radius: var(--zd-r-pill);
  background: color-mix(in srgb, var(--hse-accent) 12%, var(--surface-1));
  color: var(--hse-accent);
  font-size: var(--zd-micro);
  font-weight: 800;
}

/* ═══════════════════════════════════════════════════════════════════════════
   9 · FORMS
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-form,
.hse-form { display: grid; gap: var(--zd-4); }

.zd-form__section,
.hse-form__section {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-lg);
  box-shadow: var(--zd-shadow-sm);
  overflow: hidden;
}
.zd-form__section-head,
.hse-form__section-head {
  display: flex;
  align-items: center;
  gap: var(--zd-3);
  flex-wrap: wrap;
  padding: var(--zd-4) var(--zd-5);
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
}
.zd-form__section-title,
.hse-form__section-title { font-weight: 800; font-size: var(--zd-title); color: var(--text); }
.zd-form__section-sub { font-size: var(--zd-caption); color: var(--text-soft); margin: .1rem 0 0; line-height: 1.7; }
.zd-form__body,
.hse-form__body { padding: var(--zd-5); }
.zd-form__footer,
.hse-form__footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zd-2);
  align-items: center;
  padding: var(--zd-3) var(--zd-5);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

/* Field grid: 12 columns, same spans as the filter grid. */
.zd-fields { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--zd-4); }
.zd-field { grid-column: span 12; display: grid; gap: var(--zd-1); min-width: 0; }
.zd-field--1 { grid-column: span 1; }
.zd-field--2 { grid-column: span 2; }
.zd-field--3 { grid-column: span 3; }
.zd-field--4 { grid-column: span 4; }
.zd-field--5 { grid-column: span 5; }
.zd-field--6 { grid-column: span 6; }
.zd-field--7 { grid-column: span 7; }
.zd-field--8 { grid-column: span 8; }
.zd-field--9 { grid-column: span 9; }
.zd-field__label,
.zd-page .form-label,
.hse-form .form-label {
  font-weight: 600;
  font-size: var(--zd-label);
  color: var(--text-soft);
  margin-bottom: var(--zd-1);
}
.zd-field__hint,
.zd-page .form-text { font-size: var(--zd-micro); color: var(--text-soft); line-height: 1.7; }
.zd-field__error { font-size: var(--zd-micro); color: var(--zd-danger-text); font-weight: 600; }
/* Machine translation of what the input holds — informational, never the value
   itself, so it reads as an annotation rather than as editable content. */
.zd-field__hint--translated {
  border-inline-start: 2px solid color-mix(in srgb, var(--hse-accent) 45%, transparent);
  padding-inline-start: var(--zd-2);
  background: color-mix(in srgb, var(--hse-accent) 5%, transparent);
  border-radius: var(--zd-r-xs);
}
.zd-field__hint--translated strong { color: var(--hse-accent); font-weight: 800; }
.zd-field__req { color: var(--danger); font-weight: 700; }

/* Controls: one radius, one height, one focus ring across the platform. */
.zd-page .form-control,
.zd-page .form-select,
.hse-form .form-control,
.hse-form .form-select {
  border-radius: var(--zd-r-sm);
  min-height: 2.6rem;
}
.zd-page .form-control:focus,
.zd-page .form-select:focus,
.hse-form .form-control:focus,
.hse-form .form-select:focus {
  box-shadow: var(--focus);
  border-color: var(--hse-accent);
}
.zd-page .form-control[readonly],
.hse-form input[readonly] { background: var(--surface-2); }
.zd-page textarea.form-control { min-height: 5.5rem; }
.zd-page .input-group-text { border-radius: var(--zd-r-sm); background: var(--surface-2); }

/* Checkbox / radio / switch */
.zd-page .form-check-input:focus { box-shadow: var(--focus); border-color: var(--hse-accent); }
.zd-page .form-check-input:checked { background-color: var(--hse-accent); border-color: var(--hse-accent); }
.zd-switch {
  display: flex;
  align-items: flex-start;
  gap: var(--zd-3);
  padding: var(--zd-3) var(--zd-4);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-md);
  background: var(--surface-2);
}
.zd-switch .form-check { margin: 0; min-height: auto; padding-inline-start: 2.6rem; }
.zd-switch .form-check-input { margin-inline-start: -2.6rem; }
.zd-switch__copy { display: grid; gap: var(--zd-1); min-width: 0; }
.zd-switch__label { font-weight: 700; font-size: var(--zd-label); color: var(--text); }
.zd-switch__hint { font-size: var(--zd-micro); color: var(--text-soft); line-height: 1.8; }

/* Radio cards — two or three mutually exclusive choices that each need a line of
   explanation to be understood (a bare <select> hides exactly that difference).
   Grid, so they wrap to one per row on a phone instead of squeezing. */
.zd-choice {
  display: grid;
  gap: var(--zd-2);
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
}
.zd-choice__item {
  display: flex;
  align-items: flex-start;
  gap: var(--zd-2);
  margin: 0;
  padding: var(--zd-2) var(--zd-3);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-md);
  background: var(--surface-2);
  cursor: pointer;
}
.zd-choice__item:hover { border-color: color-mix(in srgb, var(--hse-accent) 45%, var(--border)); }
.zd-choice__item:has(input:checked) {
  border-color: var(--hse-accent);
  background: color-mix(in srgb, var(--hse-accent) 8%, var(--surface-2));
}
.zd-choice__item:has(input:focus-visible) { box-shadow: var(--focus); }
.zd-choice__item input[type="radio"] { margin-block-start: .3rem; accent-color: var(--hse-accent); flex: 0 0 auto; }
.zd-choice__body { display: grid; gap: var(--zd-1); min-width: 0; }
.zd-choice__title { font-weight: 700; font-size: var(--zd-label); color: var(--text); }
.zd-choice__hint { font-size: var(--zd-micro); color: var(--text-soft); line-height: 1.8; }

/* Verdict banner — one loud yes/no, for a screen someone reads across a counter
   while a person waits at the barrier. Colour comes from --zd-verdict-c. */
.zd-verdict {
  display: flex;
  align-items: center;
  gap: var(--zd-3);
  padding: var(--zd-4);
  border-radius: var(--zd-r-md);
  border: 1px solid color-mix(in srgb, var(--zd-verdict-c, var(--ok)) 35%, transparent);
  background: color-mix(in srgb, var(--zd-verdict-c, var(--ok)) 12%, var(--surface-1));
  color: color-mix(in srgb, var(--zd-verdict-c, var(--ok)) var(--zd-on-tint-mix), var(--text));
}
.zd-verdict--ok { --zd-verdict-c: var(--ok); }
.zd-verdict--danger { --zd-verdict-c: var(--danger); }
.zd-verdict--muted { --zd-verdict-c: #64748b; }
.zd-verdict__icon {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  flex: 0 0 auto;
  border-radius: 50%;
  background: color-mix(in srgb, var(--zd-verdict-c, var(--ok)) 22%, transparent);
}
.zd-verdict__icon svg { width: 1.7rem; height: 1.7rem; }
.zd-verdict__copy { display: grid; gap: var(--zd-1); min-width: 0; }
.zd-verdict__title { font-weight: 800; font-size: var(--zd-h3, 1.05rem); }
.zd-verdict__text { font-size: var(--zd-caption); opacity: .9; line-height: 1.9; }

/* File upload */
.zd-upload {
  display: grid;
  gap: var(--zd-2);
  padding: var(--zd-4);
  border: 1px dashed color-mix(in srgb, var(--hse-accent) 40%, var(--border));
  border-radius: var(--zd-r-md);
  background: color-mix(in srgb, var(--hse-accent) 4%, var(--surface-2));
}
.zd-upload__preview {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--zd-3);
  min-height: 6rem;
  padding: var(--zd-3);
  border-radius: var(--zd-r-md);
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.zd-upload__preview img { max-height: 5rem; max-width: 100%; object-fit: contain; }
.zd-upload__preview--compact { min-height: 4rem; }
/* Favicons are tiny by nature — never upscale them into a blurry block. */
.zd-favicon-preview { max-height: 4rem; max-width: 4rem; }

/* Inline explanatory note used next to switches and connection settings. */
.zd-note {
  font-size: var(--zd-micro);
  line-height: 1.9;
  color: var(--text-soft);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-inline-start: 3px solid color-mix(in srgb, var(--hse-accent) 55%, transparent);
  border-radius: var(--zd-r-xs);
  padding: var(--zd-2) var(--zd-3);
}
.zd-note--warn { border-inline-start-color: var(--warn); }
.zd-note--danger { border-inline-start-color: var(--danger); }

/* Collapsible detail block (raw logs, advanced settings). */
.zd-details {
  border: 1px solid var(--border);
  border-radius: var(--zd-r-md);
  background: var(--surface-2);
  overflow: hidden;
}
.zd-details > summary {
  cursor: pointer;
  padding: var(--zd-3) var(--zd-4);
  font-weight: 700;
  font-size: var(--zd-label);
  color: var(--text);
  list-style: none;
}
.zd-details > summary::-webkit-details-marker { display: none; }
.zd-details > summary::after { content: "▾"; float: inline-end; opacity: .6; }
.zd-details[open] > summary::after { content: "▴"; }
.zd-details > summary:focus-visible { outline: 2px solid var(--hse-accent); outline-offset: -2px; }
/* Plain list inside a disclosure panel. */
.zd-list {
  margin: 0;
  padding: var(--zd-3) var(--zd-5);
  border-top: 1px solid var(--border);
  background: var(--surface-1);
  font-size: var(--zd-label);
  line-height: 2;
  columns: 18rem;
}
.zd-details pre {
  margin: 0;
  padding: var(--zd-3) var(--zd-4);
  border-top: 1px solid var(--border);
  background: var(--surface-1);
  font-size: var(--zd-micro);
  white-space: pre-wrap;
  word-break: break-word;
  direction: ltr;
  text-align: start;
}

/* ═══════════════════════════════════════════════════════════════════════════
   10 · BUTTONS
   Bootstrap's .btn stays the base (it is used platform-wide); .zd-btn is the
   shared refinement that gives every button the same radius, weight and icon
   rhythm. No competing button system.
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-btn,
.hse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--zd-1);
  border-radius: var(--zd-r-sm);
  font-weight: 700;
}
.zd-btn svg,
.hse-btn svg { width: 1rem; height: 1rem; flex: 0 0 auto; }
.zd-page .btn { border-radius: var(--zd-r-sm); font-weight: 700; }
.zd-page .btn:focus-visible { box-shadow: var(--focus); }
.zd-page .btn-sm { border-radius: var(--zd-r-xs); }
/* Bootstrap 5.1's outline buttons draw their label in the raw theme colour, which
   on white fails WCAG AA for the lighter hues (btn-outline-warning measured
   1.63:1). Darken only the RESTING label — the filled hover state is untouched,
   so the buttons still look like Bootstrap, just readable. */
.zd-page .btn-outline-warning   { color: color-mix(in srgb, #ffc107 calc(var(--zd-btn-mix) - 45%), var(--text)); }
.zd-page .btn-outline-success   { color: color-mix(in srgb, var(--ok) calc(var(--zd-btn-mix) - 23%), var(--text)); }
.zd-page .btn-outline-info      { color: color-mix(in srgb, var(--info) calc(var(--zd-btn-mix) - 30%), var(--text)); }
.zd-page .btn-outline-primary   { color: color-mix(in srgb, var(--brand) var(--zd-btn-mix), var(--text)); }
.zd-page .btn-outline-secondary { color: color-mix(in srgb, #6c757d var(--zd-btn-mix), var(--text)); }
.zd-page .btn-outline-dark      { color: var(--text); border-color: color-mix(in srgb, var(--text) 45%, transparent); }
.zd-page .btn-outline-danger    { color: var(--zd-danger-text); }
/* The inverted label belongs ONLY to the states Bootstrap actually FILLS:
   :hover, :active/.active and .show (an open dropdown toggle). :focus must NOT
   be in this list — Bootstrap 5.1 leaves a focused outline button transparent,
   so a white label there renders white-on-white and the button reads as an
   empty box (hit on the «بیشتر» toggle, which keeps focus after a click).
   That also made every outline button vanish while tabbing through it. */
.zd-page .btn-outline-warning:hover,
.zd-page .btn-outline-warning:active,
.zd-page .btn-outline-warning.active,
.zd-page .btn-outline-warning.show { color: #000; }
.zd-page .btn-outline-success:hover,
.zd-page .btn-outline-success:active,
.zd-page .btn-outline-success.active,
.zd-page .btn-outline-success.show,
.zd-page .btn-outline-info:hover,
.zd-page .btn-outline-info:active,
.zd-page .btn-outline-info.active,
.zd-page .btn-outline-info.show,
.zd-page .btn-outline-primary:hover,
.zd-page .btn-outline-primary:active,
.zd-page .btn-outline-primary.active,
.zd-page .btn-outline-primary.show,
.zd-page .btn-outline-secondary:hover,
.zd-page .btn-outline-secondary:active,
.zd-page .btn-outline-secondary.active,
.zd-page .btn-outline-secondary.show,
.zd-page .btn-outline-dark:hover,
.zd-page .btn-outline-dark:active,
.zd-page .btn-outline-dark.active,
.zd-page .btn-outline-dark.show,
.zd-page .btn-outline-danger:hover,
.zd-page .btn-outline-danger:active,
.zd-page .btn-outline-danger.active,
.zd-page .btn-outline-danger.show { color: #fff; }

/* Dark theme RESTING labels are handled by the generic rules above, and must NOT be
   overridden here.
   History: this block used to force a DARK label under data-theme="modern", because
   site.css then kept outline buttons on a near-WHITE translucent fill. site.css now
   flips that fill DARK in the modern theme
   (`html[data-theme="modern"] .btn-outline-primary, .btn-outline-secondary
     { background: rgba(15,23,42,.36) }`),
   so the forced-dark label became dark-on-dark: measured 1.3:1 for
   .btn-outline-secondary and 1.4:1 for .btn-outline-danger — every outline button on
   every admin page was effectively invisible in dark mode.
   The generic rules already do the right thing in BOTH themes: they mix the hue toward
   --text, and --zd-btn-mix drops to 52% under "modern" precisely so the label lifts off
   a dark surface. The hover/.show rules below stay — Bootstrap really does FILL those
   states, so the label must invert there. */
html[data-theme="modern"] .zd-page .btn-outline-primary:hover,
html[data-theme="modern"] .zd-page .btn-outline-primary.show,
html[data-theme="modern"] .zd-page .btn-outline-secondary:hover,
html[data-theme="modern"] .zd-page .btn-outline-secondary.show,
html[data-theme="modern"] .zd-page .btn-outline-success:hover,
html[data-theme="modern"] .zd-page .btn-outline-success.show,
html[data-theme="modern"] .zd-page .btn-outline-info:hover,
html[data-theme="modern"] .zd-page .btn-outline-info.show,
html[data-theme="modern"] .zd-page .btn-outline-danger:hover,
html[data-theme="modern"] .zd-page .btn-outline-danger.show,
html[data-theme="modern"] .zd-page .btn-outline-dark:hover,
html[data-theme="modern"] .zd-page .btn-outline-dark.show { color: #fff; }
html[data-theme="modern"] .zd-page .btn-outline-warning:hover,
html[data-theme="modern"] .zd-page .btn-outline-warning.show { color: #000; }

/* Accent-coloured primary that follows the page accent instead of hardcoding blue. */
.zd-btn--accent {
  background: var(--hse-accent);
  border: 1px solid var(--hse-accent);
  color: #fff;
}
.zd-btn--accent:hover { background: color-mix(in srgb, var(--hse-accent) 85%, #000); color: #fff; }

/* ═══════════════════════════════════════════════════════════════════════════
   11 · FLASH / ALERTS
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-flash,
.hse-flash {
  display: flex;
  align-items: center;
  gap: var(--zd-2);
  padding: var(--zd-3) var(--zd-4);
  border-radius: var(--zd-r-md);
  font-weight: 600;
  font-size: var(--zd-label);
  background: color-mix(in srgb, var(--zd-flash-c, var(--ok)) 12%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--zd-flash-c, var(--ok)) 30%, transparent);
  color: color-mix(in srgb, var(--zd-flash-c, var(--ok)) var(--zd-on-tint-mix), var(--text));
}
.zd-flash svg,
.hse-flash svg { width: 1.2rem; height: 1.2rem; flex: 0 0 auto; }
.zd-flash--info { --zd-flash-c: var(--info); }
.zd-flash--warn { --zd-flash-c: var(--warn); }
.zd-flash--danger { --zd-flash-c: var(--danger); }
.zd-flash--brand { --zd-flash-c: var(--brand); }

/* ═══════════════════════════════════════════════════════════════════════════
   12 · EMPTY · ERROR · LOADING · SKELETON
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-empty,
.hse-empty {
  display: grid;
  justify-items: center;
  gap: var(--zd-1);
  text-align: center;
  padding: var(--zd-6) var(--zd-4);
  color: var(--text-soft);
}
.zd-empty__icon,
.hse-empty__icon {
  width: 3.2rem;
  height: 3.2rem;
  margin: 0 auto var(--zd-2);
  color: var(--hse-accent);
  opacity: .7;
}
.zd-empty__icon svg,
.hse-empty__icon svg { width: 100%; height: 100%; }
.zd-empty__title { font-weight: 800; font-size: var(--zd-h3); color: var(--text); }
.zd-empty__text { font-size: var(--zd-label); max-width: 34rem; line-height: 1.9; }
.zd-empty__actions { display: flex; flex-wrap: wrap; gap: var(--zd-2); margin-top: var(--zd-2); }
.zd-empty--error .zd-empty__icon { color: var(--danger); opacity: 1; }
.zd-empty--error .zd-empty__title { color: var(--zd-danger-text); }

/* Spinner */
.zd-loading { display: inline-flex; align-items: center; gap: var(--zd-2); color: var(--text-soft); font-size: var(--zd-label); }
.zd-spinner {
  width: 1.1rem;
  height: 1.1rem;
  border-radius: var(--zd-r-pill);
  border: 2px solid color-mix(in srgb, var(--hse-accent) 25%, transparent);
  border-top-color: var(--hse-accent);
  animation: zd-spin .7s linear infinite;
}
@keyframes zd-spin { to { transform: rotate(360deg); } }

/* Skeleton placeholders */
.zd-skeleton {
  border-radius: var(--zd-r-xs);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: zd-shimmer 1.4s ease infinite;
}
.zd-skeleton--text { height: .8rem; margin-block: .35rem; }
.zd-skeleton--title { height: 1.2rem; width: 40%; }
.zd-skeleton--row { height: 2.6rem; margin-block: var(--zd-1); }
.zd-skeleton--tile { height: 5.5rem; border-radius: var(--zd-r-md); }
@keyframes zd-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ═══════════════════════════════════════════════════════════════════════════
   13 · METER · READOUT · TIMELINE
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-meter,
.hse-meter {
  display: grid;
  grid-template-columns: 3.4rem 1fr auto;
  gap: var(--zd-2);
  align-items: center;
  padding: var(--zd-1) 0;
}
.zd-meter__track,
.hse-meter__track { height: 1.1rem; border-radius: var(--zd-r-pill); background: var(--surface-3); overflow: hidden; }
.zd-meter__bar,
.hse-meter__bar {
  height: 100%;
  border-radius: var(--zd-r-pill);
  background: var(--c, var(--hse-accent));
  min-width: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-inline-end: var(--zd-1);
  color: #fff;
  font-size: var(--zd-micro);
  font-weight: 700;
}
.zd-meter__desc,
.hse-meter__desc { font-size: var(--zd-micro); color: var(--text-soft); }
.zd-progress { height: .7rem; border-radius: var(--zd-r-pill); background: var(--surface-3); overflow: hidden; }
.zd-progress__fill { height: 100%; border-radius: var(--zd-r-pill); background: linear-gradient(90deg, var(--hse-accent), var(--hse-accent-2)); }

.zd-readout,
.hse-readout { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--zd-3); }
@media (max-width: 991px) { .zd-readout, .hse-readout { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 520px) { .zd-readout, .hse-readout { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.zd-readout__cell,
.hse-readout__cell {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--zd-r-sm);
  padding: var(--zd-3);
}
.zd-readout__label,
.hse-readout__label { font-size: var(--zd-micro); color: var(--text-soft); }
.zd-readout__value,
.hse-readout__value { font-weight: 800; font-size: 1.05rem; margin-top: .15rem; word-break: break-word; }

/* Facts — the read-only counterpart of a form, for record pages.
   `.zd-readout` boxes every value in a card of a fixed 6-column grid, which is right for
   a handful of headline numbers and wrong for a record: a visit with four filled fields
   and four empty ones rendered as eight big boxes half of them holding «—». Facts pack to
   content width, separate with hairlines instead of boxes, and the VIEW simply does not
   emit a fact it has no value for. */
/* Flex, not a fixed grid: a record with two facts should read as two facts sitting
   together, not as two filled cells beside four empty tracks. Items take their content
   width and wrap; one hairline above the group keeps it tidy at any count. */
.zd-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zd-3) var(--zd-6);
  padding-top: var(--zd-3);
  border-top: 1px solid var(--border);
}
.zd-fact {
  display: grid;
  gap: .1rem;
  align-content: start;
  min-width: 8rem;
  max-width: 100%;
}
.zd-fact__label { font-size: var(--zd-micro); color: var(--text-soft); }
.zd-fact__value {
  font-weight: 700;
  font-size: var(--zd-label);
  color: var(--text);
  word-break: break-word;
}
.zd-fact__value .zd-cell__meta { font-weight: 500; }
/* A fact that needs the full width (a long note) rather than a column. */
.zd-fact--wide { flex-basis: 100%; }

.zd-timeline,
.hse-timeline { display: grid; gap: .1rem; position: relative; margin: 0; padding: 0; list-style: none; }
.zd-timeline__item,
.hse-timeline__item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--zd-3);
  align-items: start;
  padding: var(--zd-3) 0;
  border-bottom: 1px solid var(--border);
}
.zd-timeline__item:last-child,
.hse-timeline__item:last-child { border-bottom: 0; }
.zd-timeline__dot,
.hse-timeline__dot {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--zd-r-pill);
  display: inline-grid;
  place-items: center;
  color: #fff;
  background: var(--c, var(--hse-accent));
}
.zd-timeline__dot svg,
.hse-timeline__dot svg { width: 1.1rem; height: 1.1rem; }
.zd-timeline__title,
.hse-timeline__title { font-weight: 700; }
.zd-timeline__meta,
.hse-timeline__meta { color: var(--text-soft); font-size: var(--zd-caption); margin-top: .15rem; }
.zd-timeline__date,
.hse-timeline__date { color: var(--text-soft); font-size: var(--zd-caption); white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════
   13b · PERMISSION MATRIX
   Used by the role editor and the user access editor. The class names are kept
   (.permission-*) because the grant scripts query them; the styling is now
   token-driven and shares the surface/pill/tab vocabulary above, so both
   editors read as part of one system instead of two bespoke screens.
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-stack { display: grid; gap: var(--zd-4); }
.zd-stack--tight { gap: var(--zd-3); }

.permission-admin-shell .permission-tab.is-active,
.permission-tab.is-active {
  background: var(--hse-accent);
  border-color: var(--hse-accent);
  color: #fff;
}

.permission-group-panel {
  border: 1px solid var(--border);
  border-radius: var(--zd-r-md);
  background: var(--surface-1);
  overflow: hidden;
}
.permission-group-panel.is-hidden,
.permission-row.is-hidden { display: none !important; }

.permission-group-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--zd-3);
  flex-wrap: wrap;
  padding: var(--zd-3) var(--zd-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.permission-group-panel__title { margin: 0; font-size: var(--zd-title); font-weight: 800; color: var(--text); }
.permission-group-panel__count { font-size: var(--zd-micro); color: var(--text-soft); }
.permission-group-panel__actions { display: flex; flex-wrap: wrap; gap: var(--zd-2); }

/* The module panel collapses. The registry declares ~105 grantable permissions across 17 modules,
   so an editor with every panel open is five screens of scrolling before the save button — and the
   modules an account has nothing in are most of them. Same header, now a disclosure, with the same
   affordances as .zd-surface > summary.zd-surface__head so the two read as one component. */
.permission-group-panel > summary.permission-group-panel__header { cursor: pointer; list-style: none; }
.permission-group-panel > summary.permission-group-panel__header::-webkit-details-marker { display: none; }
.permission-group-panel > summary.permission-group-panel__header::after {
  content: "▾";
  opacity: .6;
  margin-inline-start: var(--zd-2);
}
.permission-group-panel[open] > summary.permission-group-panel__header::after { content: "▴"; }
.permission-group-panel > summary.permission-group-panel__header:hover { background: var(--surface-3); }
.permission-group-panel > summary.permission-group-panel__header:focus-visible { outline: 2px solid var(--hse-accent); outline-offset: -2px; }
/* Collapsed: the header is the only visible child, so its divider has nothing to divide. */
.permission-group-panel:not([open]) > summary.permission-group-panel__header { border-bottom: 0; }
/* «N مؤثر» sits next to the chevron, not adrift in the middle — same three-item flex
   problem as the collapsible surface head above. */
.permission-group-panel > summary.permission-group-panel__header > .zd-pill { margin-inline-start: auto; }

.permission-list { display: grid; }
.permission-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--zd-3);
  align-items: start;
  padding: var(--zd-3) var(--zd-4);
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}
.permission-row:last-child { border-bottom: 0; }
.permission-row:hover { background: var(--surface-2); }
.permission-row--matrix { grid-template-columns: minmax(0, 1.4fr) minmax(14rem, 1fr) auto; cursor: default; }
.permission-row__main { display: grid; gap: .18rem; min-width: 0; }
.permission-row__main strong { font-size: var(--zd-title); }
.permission-row__main small { color: var(--text-soft); line-height: 1.7; }
.permission-row__toggle,
.permission-row__toggle-label { display: inline-flex; align-items: center; gap: var(--zd-2); }
.permission-row__toggle-label { white-space: nowrap; font-weight: 700; font-size: var(--zd-label); cursor: pointer; }

/* Declared permission dependencies, shown in the grant UI so an administrator sees
   the full effect of a checkbox BEFORE saving. */
.permission-note {
  display: inline-block;
  font-size: var(--zd-micro);
  line-height: 1.6;
  border-radius: var(--zd-r-xs);
  padding: .05rem var(--zd-1);
  margin-top: .15rem;
}
.permission-note--implies { color: color-mix(in srgb, #0d9488 55%, var(--text)); background: color-mix(in srgb, #0d9488 12%, transparent); }
.permission-note--implied-by,
.permission-note--implied { color: color-mix(in srgb, #7c3aed 60%, var(--text)); background: color-mix(in srgb, #7c3aed 12%, transparent); }
.permission-note--deprecated { color: color-mix(in srgb, #d97706 50%, var(--text)); background: color-mix(in srgb, #d97706 14%, transparent); font-weight: 700; }

/* A row switched on by another permission rather than ticked directly. */
.permission-row--implied { background: color-mix(in srgb, #7c3aed 6%, transparent); }

.permission-source-badges { display: flex; flex-wrap: wrap; gap: var(--zd-1); align-items: flex-start; }
.permission-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--zd-1) var(--zd-2);
  border-radius: var(--zd-r-pill);
  font-size: var(--zd-micro);
  font-weight: 700;
  white-space: nowrap;
  background: color-mix(in srgb, var(--zd-pb-c, #64748b) 14%, var(--surface-1));
  color: color-mix(in srgb, var(--zd-pb-c, #64748b) var(--zd-on-tint-mix), var(--text));
  border: 1px solid color-mix(in srgb, var(--zd-pb-c, #64748b) 26%, transparent);
}
.permission-badge--direct { --zd-pb-c: var(--brand); }
.permission-badge--role { --zd-pb-c: #7c3aed; }
.permission-badge--effective { --zd-pb-c: var(--ok); }
.permission-badge--implied { --zd-pb-c: #7c3aed; }
.permission-badge--muted { --zd-pb-c: #64748b; }

html[data-theme="modern"] .permission-note--implies { color: #5eead4; }
html[data-theme="modern"] .permission-note--implied-by,
html[data-theme="modern"] .permission-note--implied { color: #c4b5fd; }
html[data-theme="modern"] .permission-note--deprecated { color: #fcd34d; }

@media (max-width: 991px) {
  .permission-row,
  .permission-row--matrix { grid-template-columns: 1fr; }
  .permission-row__toggle-label { white-space: normal; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   14 · DIALOG (Bootstrap modal, harmonised)
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-dialog .modal-content,
.modal .zd-dialog {
  border: 1px solid var(--border);
  border-radius: var(--zd-r-lg);
  box-shadow: var(--zd-shadow-lg);
  background: var(--surface-1);
  overflow: hidden;
}
.zd-dialog .modal-header {
  padding: var(--zd-4) var(--zd-5);
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
}
.zd-dialog .modal-title { font-size: var(--zd-h3); font-weight: 800; }
.zd-dialog .modal-body { padding: var(--zd-5); }
.zd-dialog .modal-footer {
  padding: var(--zd-3) var(--zd-5);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  gap: var(--zd-2);
}

/* ═══════════════════════════════════════════════════════════════════════════
   15 · ACCESSIBILITY
   ═══════════════════════════════════════════════════════════════════════════ */
.zd-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* One visible focus ring on every interactive shell (WCAG 2.4.7). */
.zd-stat:focus-visible,
.zd-chip:focus-visible,
.zd-tab:focus-visible,
.zd-pager__btn:focus-visible,
.zd-table__sort:focus-visible,
.zd-hero__btn:focus-visible,
.zd-person a:focus-visible,
.hse-stat:focus-visible,
.hse-chip:focus-visible,
.hse-tab:focus-visible,
.hse-statcard:focus-visible {
  outline: 2px solid var(--hse-accent);
  outline-offset: 2px;
  border-radius: var(--zd-r-xs);
}
/* On the coloured hero the accent ring would disappear — use white. */
.zd-hero__btn:focus-visible,
.hse-hero__btn:focus-visible,
.zd-hero a:focus-visible { outline-color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .zd-stat, .zd-stat--link, .zd-chip, .zd-tab, .zd-hero__btn, .zd-pager__btn,
  button.zd-stat, button.zd-stat:hover,
  button.hse-stat, button.hse-stat:hover,
  .hse-statcard, .hse-statcard:hover, .hse-chip {
    transition: none;
    transform: none;
  }
  .zd-skeleton, .zd-spinner { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   16 · RESPONSIVE
   Phones: the hero stacks, filters go full width, toolbars wrap, tables scroll
   instead of squashing — the same behaviour the Dashboard already has.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
  .zd-page,
  .hse-page { padding: var(--zd-3) var(--zd-3) var(--zd-6); gap: var(--zd-3); }

  .zd-hero,
  .hse-hero { grid-template-columns: 1fr; padding: var(--zd-4); }
  .zd-hero__actions,
  .hse-hero__actions { justify-content: flex-start; }
  .zd-hero__btn,
  .hse-hero__actions .hse-hero__btn { flex: 1 1 auto; justify-content: center; }

  .zd-filter,
  .hse-filter { grid-template-columns: 1fr; }
  .zd-filter > *,
  .hse-filter > * { grid-column: 1 / -1 !important; }
  .zd-fields { grid-template-columns: 1fr; }
  .zd-fields > * { grid-column: 1 / -1 !important; }

  .zd-surface__head,
  .zd-toolbar,
  .zd-tabs--bar,
  .zd-pager,
  .zd-form__section-head,
  .zd-form__footer { padding-inline: var(--zd-4); }
  .zd-surface__body,
  .zd-form__body { padding: var(--zd-4); }

  .zd-pager { justify-content: center; }
  .zd-toolbar__search, .zd-search { flex-basis: 100%; }

  /* Wide admin tables: give them a readable width so .zd-tablewrap scrolls them
     sideways instead of crushing every column into the viewport. Without this the
     multi-column Users / Roles / Login-audit grids become unreadable on a phone. */
  .zd-table { min-width: 44rem; }
  .zd-table--narrow { min-width: 0; }

  /* Tabs scroll horizontally rather than wrapping into a tall block. */
  .zd-tabs--scroll {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .zd-tabs--scroll::-webkit-scrollbar { display: none; }
  .zd-tabs--scroll .zd-tab { flex: 0 0 auto; }
}

/* ===== Searchable single-person picker (.zd-pick) ==============================
   یک انتخابگرِ تک‌مقداری که آنچه نشان می‌دهد «نام آدم» است و آنچه پست می‌کند کد
   پرسنلی. datalist بومی این کار را نمی‌کند: مقدارِ ورودی همان چیزی است که پست
   می‌شود، پس کاربر بعد از انتخاب یک عدد می‌دید. رفتار در person-picker.js. */
.zd-pick { position: relative; }

.zd-pick__field {
  display: flex;
  align-items: center;
  gap: .35rem;
  padding-inline-end: .35rem;
}

.zd-pick.is-open .zd-pick__field {
  border-color: var(--brand, #2563eb);
  box-shadow: 0 0 0 .2rem var(--brand-soft, rgba(37, 99, 235, .25));
}

.zd-pick__search {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text, #1e293b);
  font: inherit;
  padding: 0;
}

.zd-pick__search::placeholder { color: var(--text-soft, #94a3b8); }

.zd-pick__clear {
  flex: 0 0 auto;
  display: none;
  align-items: center;
  justify-content: center;
  width: 1.35rem;
  height: 1.35rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, .08);
  color: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.zd-pick.is-chosen .zd-pick__clear { display: inline-flex; }
.zd-pick__clear { background: color-mix(in srgb, var(--text-soft, #94a3b8) 22%, transparent); }
.zd-pick__clear:hover, .zd-pick__clear:focus { background: rgba(220, 38, 38, .85); color: #fff; outline: none; }

.zd-pick__menu {
  position: absolute;
  z-index: 30;
  inset-inline: 0;
  top: calc(100% + .25rem);
  max-height: 16rem;
  overflow-y: auto;
  background: var(--surface-1, #fff);
  border: 1px solid var(--border, #e2e8f0);
  border-radius: .6rem;
  box-shadow: 0 12px 28px rgba(15, 23, 42, .18);
  padding: .3rem;
}

.zd-pick__option {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  width: 100%;
  text-align: start;
  padding: .45rem .6rem;
  border: 0;
  border-radius: .45rem;
  background: transparent;
  color: var(--text, #1e293b);
  font: inherit;
  cursor: pointer;
}

.zd-pick__option:hover,
.zd-pick__option:focus,
.zd-pick__option.is-active {
  background: var(--brand-soft, #dbeafe);
  color: var(--brand-hover, #1d4ed8);
  outline: none;
}

.zd-pick__option-name { font-weight: 600; }
.zd-pick__option-meta { font-size: var(--zd-micro, .72rem); color: var(--text-soft, #94a3b8); white-space: nowrap; }
.zd-pick__option:hover .zd-pick__option-meta,
.zd-pick__option.is-active .zd-pick__option-meta { color: inherit; }

.zd-pick__noresults { padding: .55rem .65rem; color: var(--text-soft, #94a3b8); font-size: var(--text-sm, .9rem); }

/* خطِ زیرِ فیلد: کد پرسنلیِ نفرِ انتخاب‌شده. کد پنهان نمی‌شود — فقط دیگر «چیزی که
   کاربر می‌خواند» نیست. */
.zd-pick__meta { display: none; margin-top: .25rem; font-size: var(--zd-micro, .72rem); color: var(--text-soft, #94a3b8); }
.zd-pick.is-chosen .zd-pick__meta { display: block; }

/* ===== ردیف‌های «واحد ذی‌ربط ← نفر» (.zd-unitrow) =============================
   جدولِ ۳ستونی برای این کار غلط بود: ستون‌ها با عرضِ محتوا می‌جنگیدند و فیلدِ
   انتخاب نفر — که مهم‌ترین چیز ردیف است — باریک‌ترین می‌شد. گرید عرض را صریح
   تقسیم می‌کند و روی موبایل ردیف را به کارت تبدیل می‌کند. */
.zd-unitrows { display: flex; flex-direction: column; gap: .5rem; }

.zd-unitrow {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) minmax(0, 1.2fr) 2rem;
  align-items: start;
  gap: .6rem;
  padding: .5rem;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: .7rem;
  background: var(--surface-1, #fff);
}

.zd-unitrow__num {
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(2.5rem + 2px);
  font-weight: 700;
  color: var(--text-soft, #94a3b8);
  font-variant-numeric: tabular-nums;
}

.zd-unitrow__remove {
  align-self: center;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: var(--text-soft, #94a3b8);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
}

.zd-unitrow__remove:hover,
.zd-unitrow__remove:focus { background: rgba(220, 38, 38, .12); color: #dc2626; outline: none; }

/* ورودیِ بدون قاب برای عنوان واحد: عنوان‌ها از تنظیمات می‌آیند و معمولاً دست
   نمی‌خورند، پس نباید مثل یک فیلدِ خالیِ منتظرِ تایپ به‌نظر برسند. */
.zd-input--flush {
  border-color: transparent;
  background: transparent;
  font-weight: 600;
}
.zd-input--flush:focus { border-color: var(--brand, #2563eb); background: var(--surface-1, #fff); }

.zd-input--code { font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.zd-input--muted { color: var(--text-soft, #94a3b8); background: var(--surface-2, #f8fafc); }

/* پاورقی فرم با دکمه‌های چپ/راست (بعدی و قبلی). */
.zd-form__footer--split { display: flex; justify-content: space-between; gap: .5rem; }

@media (max-width: 720px) {
  .zd-unitrow {
    grid-template-columns: 2rem minmax(0, 1fr) 2rem;
    grid-template-areas: "num unit remove" ".  person person";
    row-gap: .4rem;
  }
  .zd-unitrow__num { grid-area: num; height: auto; }
  /* هدف لمسی بر حسب px نه rem: فونتِ ریشه روی این قالب ۱۴px است، پس 2.5rem
     می‌شد ۳۵px و باز هم زیر حداقلِ ۴۴px لمسی می‌ماند. */
  .zd-unitrow__remove { width: 44px; height: 44px; font-size: 1.4rem; }
  .zd-unitrow__unit { grid-area: unit; }
  .zd-unitrow__person { grid-area: person; }
  .zd-unitrow__remove { grid-area: remove; }
}

/* ===== جدولِ قابل ویرایش روی موبایل (.zd-table--stack) ========================
   جدول‌های *خواندنی* روی موبایل افقی اسکرول می‌شوند و مشکلی ندارد؛ ولی جدولی که
   داخلش فرم است با اسکرول افقی غیرقابل‌استفاده می‌شود — کاربر باید برای هر ردیف
   چپ و راست برود. این مودیفایر هر ردیف را به یک کارت تبدیل می‌کند و برچسبِ هر
   سلول را از data-label می‌گیرد. (نسخه عمومیِ همان کاری که .ins-members-edit
   برای بیمه تکمیلی می‌کرد.) */
@media (max-width: 820px) {
  .zd-table--stack { min-width: 0; }
  .zd-table--stack thead { display: none; }
  .zd-table--stack, .zd-table--stack tbody, .zd-table--stack tr, .zd-table--stack td { display: block; width: 100%; }

  .zd-table--stack tr {
    border: 1px solid var(--border, #e2e8f0);
    border-radius: .7rem;
    padding: .5rem .65rem;
    margin-bottom: .6rem;
    background: var(--surface-1, #fff);
  }

  .zd-table--stack td {
    border: 0;
    padding: .25rem 0;
    display: grid;
    grid-template-columns: minmax(6.5rem, 38%) minmax(0, 1fr);
    align-items: center;
    gap: .5rem;
  }

  .zd-table--stack td::before {
    content: attr(data-label);
    font-size: var(--zd-micro, .72rem);
    font-weight: 700;
    color: var(--text-soft, #94a3b8);
  }

  /* سلولی که برچسب ندارد (شماره ردیف) تیتر کارت می‌شود. */
  .zd-table--stack td:not([data-label]) {
    display: block;
    font-weight: 800;
    color: var(--text-soft, #94a3b8);
    border-bottom: 1px dashed var(--border, #e2e8f0);
    margin-bottom: .35rem;
    padding-bottom: .35rem;
  }
}
