/* ═══════════════════════════════════════════════════════════════════════
   زیباتو — کتابخانهٔ کامپوننت  ·  [LEAD 2026-09-04]
   قرارداد کامل: docs/audit/UI-ELEMENT-SPEC.md

   چرا این فایل هست: ممیزی نشان داد هفت المان (تایم‌لاین، دراپ‌داون، تب،
   آواتار، تولتیپ، صفحه‌بندی، سوییچ) در قالب‌ها استفاده می‌شوند ولی هیچ
   تعریفی ندارند — پس هر صفحه‌ای که لازمشان داشت، نسخهٔ درجای خودش را
   می‌ساخت. نتیجه: ۸۱هزار کاراکتر CSS داخلِ ۳۵ قالب و رابطی که «بی‌نظم»
   خوانده می‌شود. این فایل تنها خانهٔ مجاز کامپوننت‌هاست.

   ⚠️ قواعد الزامی برای هر ایجنتی که این‌جا اضافه می‌کند:
     ۱. هیچ هگز خامی — فقط توکن. رنگِ معنایی (سبز/قرمز) استثناست.
     ۲. هر انیمیشن گاردِ `prefers-reduced-motion` دارد.
     ۳. فقط `transform` و `opacity` متحرک می‌شوند.
     ۴. RTL بومی: `inset-inline-*` و `margin-inline-*`، نه left/right.
     ۵. هدفِ لمس ≥ ۴۴px. متنِ زیر ۱۳px ممنوع.

   این فایل روی **هر دو** سیستم کار می‌کند:
     قبل‌ورود (`--zh-*`)  ·  بعدورود (`--c-*`)
   با `var(--c-primary, var(--zh-accent, …))` هر کدام موجود بود برنده است.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
    /* ── پل بین دو سیستم ─────────────────────────────────────────────── */
    --zb-brand:      var(--c-primary,   var(--zh-accent,      #d6336c));
    --zb-brand-deep: var(--c-primary-dark, var(--zh-accent-deep, #a02454));
    --zb-brand-soft: var(--c-bg-light,  var(--zh-accent-soft, #f2edf1));
    --zb-gold:       var(--zh-gold, #7c4fe0);
    --zb-gold-soft:  var(--zh-gold-soft, #f3ead9);
    --zb-gold-deep:  var(--zh-gold-deep, #5b32b8);

    --zb-ink:   var(--zh-ink,   #231f26);
    --zb-ink-2: var(--zh-ink-2, #57505c);
    --zb-ink-3: var(--zh-ink-3, #8b838f);
    --zb-line:  var(--zh-line,  #e9e4e6);
    --zb-line-soft: var(--zh-line-soft, #f3eff0);
    --zb-surface: #ffffff;
    --zb-bg:    var(--zh-bg, #fcfaf8);

    /* رنگِ معنایی — ثابت، هرگز تم‌پذیر نمی‌شود (UI-ELEMENT-SPEC §۱٫۱) */
    --zb-ok:   #1e9e5a;
    --zb-ok-bg: #e8f6ee;
    --zb-err:  #d33a3a;
    --zb-err-bg: #fdecec;
    --zb-warn: #b7791f;
    --zb-warn-bg: #fdf4e3;
    --zb-info: #2b6cb0;
    --zb-info-bg: #e8f0f9;

    /* ── فاصله — مقیاس ۴ پایه. عددِ جادویی ممنوع. ────────────────────── */
    --zb-s1: 4px;   --zb-s2: 8px;   --zb-s3: 12px;  --zb-s4: 16px;
    --zb-s5: 24px;  --zb-s6: 32px;  --zb-s7: 48px;  --zb-s8: 64px;

    /* ── تایپوگرافی — مقیاس ۱٫۲۵، کف ۱۳px ───────────────────────────── */
    --zb-t-xs:   .8125rem;   /* ۱۳px — کف مطلق */
    --zb-t-sm:   .875rem;    /* ۱۴ */
    --zb-t-body: .9375rem;   /* ۱۵ */
    --zb-t-lg:   1.0625rem;  /* ۱۷ */
    --zb-t-h2:   1.375rem;   /* ۲۲ */
    --zb-t-h1:   1.75rem;    /* ۲۸ */

    /* ── شعاع، سایه، حرکت ───────────────────────────────────────────── */
    --zb-r-sm: 9px;  --zb-r-md: 12px;  --zb-r-lg: 18px;  --zb-r-pill: 999px;
    --zb-shadow:    0 1px 2px rgba(35,31,38,.05), 0 10px 28px -12px rgba(35,31,38,.14);
    --zb-shadow-lg: 0 2px 6px rgba(35,31,38,.06), 0 30px 64px -24px rgba(35,31,38,.20);
    --zb-ease:    cubic-bezier(.16, 1, .3, 1);
    --zb-ease-io: cubic-bezier(.4, 0, .2, 1);
}

/* ═══ ۱. تایم‌لاین — ستون فقرات همهٔ پرونده‌ها ═══════════════════════════
   نوبت، تراکنش، تاریخچهٔ مشتری. خط در سمت راست (RTL بومی). */
.zb-timeline { position: relative; padding-inline-end: 22px; margin: 0; list-style: none; }
.zb-timeline::before {
    content: ''; position: absolute; inset-inline-end: 5px; top: 7px; bottom: 7px;
    width: 1px; background: var(--zb-line);
}
.zb-timeline-item { position: relative; padding-bottom: var(--zb-s5); }
.zb-timeline-item:last-child { padding-bottom: 0; }
.zb-timeline-dot {
    position: absolute; inset-inline-end: -21px; top: 4px;
    width: 11px; height: 11px; border-radius: 50%;
    background: var(--zb-brand); box-shadow: 0 0 0 3px var(--zb-surface);
}
/* آینده: توخالی — «هنوز نشده» */
.zb-timeline-item--future .zb-timeline-dot { background: var(--zb-surface); border: 2px solid var(--zb-line); }
.zb-timeline-item--future .zb-timeline-title { color: var(--zb-ink-3); }
/* ناموفق: قرمز — رنگِ معنایی */
.zb-timeline-item--fail .zb-timeline-dot { background: var(--zb-err); }
/* جاری: نبض */
.zb-timeline-item--now .zb-timeline-dot::after {
    content: ''; position: absolute; inset: 0; border-radius: 50%;
    background: var(--zb-brand); animation: zbPulse 2.2s ease-out infinite;
}
@keyframes zbPulse { 0% { opacity:.6; transform:scale(1); } 100% { opacity:0; transform:scale(2.6); } }
.zb-timeline-time  { font-size: var(--zb-t-xs); color: var(--zb-ink-3); }
.zb-timeline-title { font-size: var(--zb-t-sm); font-weight: 700; color: var(--zb-ink); margin-top: 2px; }
.zb-timeline-desc  { font-size: var(--zb-t-xs); color: var(--zb-ink-2); margin-top: var(--zb-s1); line-height: 1.9; }

/* ═══ ۲. دراپ‌داون ═══════════════════════════════════════════════════════
   ظاهرِ یکسان با ورودی + فلشِ سفارشی. فلش با data-URI تا رنگ ثابت نماند. */
.zb-select {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 48px; padding: 0 var(--zb-s4);
    padding-inline-start: var(--zb-s8);
    font: inherit; font-size: 16px;      /* ۱۶px: iOS وگرنه زوم می‌کند */
    color: var(--zb-ink); background: var(--zb-surface);
    border: 1.5px solid var(--zb-line); border-radius: var(--zb-r-md);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='none' stroke='%238b838f' stroke-width='2'%3E%3Cpath d='M3 5l4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: left var(--zb-s4) center;
    transition: border-color .2s var(--zb-ease-io), box-shadow .2s var(--zb-ease-io);
}
.zb-select:focus {
    outline: none; border-color: var(--zb-brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--zb-brand) 18%, transparent);
}
.zb-select:disabled { background: var(--zb-line-soft); color: var(--zb-ink-3); cursor: not-allowed; }
.zb-select--error { border-color: var(--zb-err); }

/* ═══ ۳. تب ═══════════════════════════════════════════════════════════ */
.zb-tabs { display: flex; gap: var(--zb-s1); border-bottom: 1px solid var(--zb-line); overflow-x: auto; }
.zb-tab {
    flex-shrink: 0; position: relative; padding: var(--zb-s3) var(--zb-s4);
    font-size: var(--zb-t-sm); font-weight: 600; color: var(--zb-ink-3);
    background: none; border: 0; cursor: pointer; font-family: inherit;
    transition: color .2s var(--zb-ease-io);
}
.zb-tab:hover { color: var(--zb-ink-2); }
.zb-tab::after {
    content: ''; position: absolute; inset-inline: var(--zb-s3); bottom: -1px; height: 2px;
    background: var(--zb-brand); border-radius: 2px 2px 0 0;
    transform: scaleX(0); transition: transform .3s var(--zb-ease);
}
.zb-tab[aria-selected="true"] { color: var(--zb-brand); font-weight: 700; }
.zb-tab[aria-selected="true"]::after { transform: scaleX(1); }
.zb-tab-panel[hidden] { display: none; }

/* ═══ ۴. آواتار ═══════════════════════════════════════════════════════
   سه پیاده‌سازی متفاوت داشت (مشتری/آرایشگر/کاربر). یکی می‌شود. */
.zb-avatar {
    display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%;
    overflow: hidden; background: var(--zb-brand-soft); color: var(--zb-brand);
    font-weight: 700; font-size: var(--zb-t-sm); line-height: 1;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,.05);
}
.zb-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.zb-avatar--sm { width: 28px; height: 28px; font-size: .6875rem; }
.zb-avatar--lg { width: 64px; height: 64px; font-size: var(--zb-t-lg); }
.zb-avatar--xl { width: 96px; height: 96px; font-size: var(--zb-t-h2); }
.zb-avatar--square { border-radius: var(--zb-r-md); }
/* پشته: چند آواتار روی هم، برای «۴ آرایشگر» */
.zb-avatar-stack { display: inline-flex; }
.zb-avatar-stack .zb-avatar + .zb-avatar { margin-inline-start: -12px; box-shadow: 0 0 0 2px var(--zb-surface); }

/* ═══ ۵. تولتیپ ═══════════════════════════════════════════════════════
   فقط CSS. متن در `data-tip`. روی لمس نمایش داده نمی‌شود (عمدی —
   روی موبایل باید برچسبِ واقعی باشد نه تولتیپ). */
.zb-tip { position: relative; }
.zb-tip::after {
    content: attr(data-tip);
    position: absolute; bottom: calc(100% + 8px); inset-inline-start: 50%;
    transform: translateX(50%) translateY(4px);
    padding: 6px 10px; border-radius: var(--zb-r-sm);
    background: var(--zb-ink); color: #fff;
    font-size: var(--zb-t-xs); font-weight: 600; white-space: nowrap;
    opacity: 0; pointer-events: none;
    transition: opacity .2s var(--zb-ease-io), transform .2s var(--zb-ease-io);
    z-index: 60;
}
.zb-tip:hover::after, .zb-tip:focus-visible::after { opacity: 1; transform: translateX(50%) translateY(0); }
@media (hover: none) { .zb-tip::after { display: none; } }

/* ═══ ۶. صفحه‌بندی ═══════════════════════════════════════════════════ */
.zb-pagination { display: flex; align-items: center; justify-content: center; gap: var(--zb-s1); flex-wrap: wrap; }
.zb-page {
    min-width: 40px; height: 40px; padding: 0 var(--zb-s3);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: var(--zb-t-sm); font-weight: 600; color: var(--zb-ink-2);
    background: var(--zb-surface); border: 1px solid var(--zb-line);
    border-radius: var(--zb-r-sm); text-decoration: none;
    font-variant-numeric: tabular-nums;
    transition: border-color .2s var(--zb-ease-io), color .2s var(--zb-ease-io);
}
.zb-page:hover { border-color: var(--zb-brand); color: var(--zb-brand); }
.zb-page[aria-current="page"] { background: var(--zb-brand); border-color: var(--zb-brand); color: #fff; }
.zb-page--disabled { opacity: .4; pointer-events: none; }
.zb-page-gap { color: var(--zb-ink-3); padding: 0 var(--zb-s1); }

/* ═══ ۷. سوییچ ═══════════════════════════════════════════════════════
   ۴۴×۲۴ رویه + ناحیهٔ لمسِ کامل. `<input type=checkbox class=zb-switch>` */
.zb-switch {
    -webkit-appearance: none; appearance: none;
    position: relative; flex-shrink: 0;
    width: 44px; height: 24px; border-radius: var(--zb-r-pill);
    background: var(--zb-line); cursor: pointer; margin: 0;
    transition: background-color .22s var(--zb-ease-io);
}
.zb-switch::after {
    content: ''; position: absolute; top: 3px; inset-inline-start: 3px;
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--zb-surface); box-shadow: 0 1px 3px rgba(0,0,0,.2);
    transition: transform .22s var(--zb-ease-io);
}
.zb-switch:checked { background: var(--zb-ok); }
.zb-switch:checked::after { transform: translateX(-20px); }  /* RTL: به چپ */
.zb-switch:focus-visible { outline: 2px solid var(--zb-brand); outline-offset: 2px; }
.zb-switch:disabled { opacity: .5; cursor: not-allowed; }

/* ═══ ۸. حالت خالی — اجباری برای هر لیست ════════════════════════════ */
.zb-empty { text-align: center; padding: var(--zb-s7) var(--zb-s4); }
.zb-empty-ico { color: var(--zb-ink-3); opacity: .3; margin: 0 auto var(--zb-s3); }
.zb-empty-title { font-size: var(--zb-t-lg); font-weight: 700; color: var(--zb-ink-2); }
.zb-empty-text { font-size: var(--zb-t-sm); color: var(--zb-ink-3); margin: var(--zb-s2) 0 var(--zb-s4); line-height: 1.9; }

/* ═══ ۹. اسکلتون — به‌جای اسپینر ═════════════════════════════════════
   شکلِ محتوای واقعی را می‌گیرد، پس جهش چیدمان ندارد. */
.zb-skel {
    background: linear-gradient(90deg, var(--zb-line-soft) 25%, var(--zb-line) 37%, var(--zb-line-soft) 63%);
    background-size: 400% 100%; border-radius: var(--zb-r-sm);
    animation: zbShimmer 1.4s ease-in-out infinite;
}
@keyframes zbShimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.zb-skel--text { height: 12px; margin-bottom: var(--zb-s2); }
.zb-skel--title { height: 20px; width: 45%; margin-bottom: var(--zb-s3); }
.zb-skel--avatar { width: 40px; height: 40px; border-radius: 50%; }
.zb-skel--card { height: 120px; }

/* ═══ ۱۰. نشان وضعیت ═══════════════════════════════════════════════ */
.zb-badge {
    display: inline-flex; align-items: center; gap: var(--zb-s1);
    padding: 2px 10px; border-radius: var(--zb-r-pill);
    font-size: var(--zb-t-xs); font-weight: 700; line-height: 1.7; white-space: nowrap;
}
.zb-badge--pending   { background: var(--zb-warn-bg); color: var(--zb-warn); }
.zb-badge--confirmed { background: var(--zb-ok-bg);   color: var(--zb-ok); }
.zb-badge--completed { background: var(--zb-info-bg); color: var(--zb-info); }
.zb-badge--cancelled { background: var(--zb-err-bg);  color: var(--zb-err); }
.zb-badge--gold      { background: var(--zb-gold-soft); color: var(--zb-gold-deep);
                       border: 1px solid color-mix(in srgb, var(--zb-gold) 40%, transparent); }
.zb-badge--neutral   { background: var(--zb-line-soft); color: var(--zb-ink-2); }

/* ═══ ۱۱. نقطهٔ وضعیت — برای جدول و فهرست ═════════════════════════ */
.zb-dot { display: inline-block; flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; }
.zb-dot--ok  { background: var(--zb-ok);  box-shadow: 0 0 0 3px color-mix(in srgb, var(--zb-ok) 14%, transparent); }
.zb-dot--err { background: var(--zb-err); box-shadow: 0 0 0 3px color-mix(in srgb, var(--zb-err) 12%, transparent); }
.zb-dot--idle{ background: var(--zb-ink-3); }

/* ═══ ۱۲. گاردِ کاهش حرکت — سراسری ═════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
    .zb-skel { animation: none; background: var(--zb-line-soft); }
    .zb-timeline-item--now .zb-timeline-dot::after { animation: none; }
    .zb-tab::after, .zb-switch, .zb-switch::after, .zb-tip::after { transition: none; }
}

/* ═══ ۱۳. کارت — چهار نقش، نه هفت نام ═══════════════════════════════
   ممیزی هفت املای موازی پیدا کرد (card/glass-card/zh-card/stat-hero/
   mini-stat/link-card/report-card) که سه‌تای اولش یک چیزند. این نسخهٔ
   واحد است؛ کارت‌های تازه باید از این بیایند. */
.zb-card {
    background: linear-gradient(180deg, var(--zb-surface) 0%,
                color-mix(in srgb, var(--zb-bg) 55%, var(--zb-surface)) 100%);
    border: 1px solid var(--zb-line);
    border-radius: var(--zb-r-lg);
    padding: var(--zb-s5);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.9), var(--zb-shadow);
    transition: transform .35s var(--zb-ease), box-shadow .35s var(--zb-ease);
}
.zb-card--hover:hover { transform: translateY(-3px);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.9), var(--zb-shadow-lg); }
.zb-card--flat { box-shadow: none; background: var(--zb-surface); }
/* لبهٔ تأکید — همیشه سمت راست (RTL). چپ و راست قاطی نشود. */
.zb-card--accent { border-inline-end: 3px solid var(--zb-brand); }
.zb-card--ok  { border-inline-end: 3px solid var(--zb-ok); }
.zb-card--err { border-inline-end: 3px solid var(--zb-err); }

.zb-card-head { display: flex; align-items: center; justify-content: space-between;
    gap: var(--zb-s3); margin-bottom: var(--zb-s4); }
.zb-card-title { font-size: var(--zb-t-lg); font-weight: 700; color: var(--zb-ink); }
.zb-card-sub { font-size: var(--zb-t-xs); color: var(--zb-ink-3); margin-top: 2px; }

/* کارتِ کلیک‌پذیر — کل سطح لینک است، فلش در انتها حرکت می‌کند */
.zb-card--link { display: flex; align-items: center; gap: var(--zb-s3);
    text-decoration: none; color: inherit; }
.zb-card--link .zb-card-arrow { margin-inline-start: auto; color: var(--zb-ink-3);
    transition: transform .3s var(--zb-ease), color .3s var(--zb-ease); }
.zb-card--link:hover .zb-card-arrow { transform: translateX(-4px); color: var(--zb-brand); }

/* کاشیِ آیکونِ کارت */
.zb-card-ico { flex-shrink: 0; width: 44px; height: 44px; border-radius: var(--zb-r-md);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--zb-brand-soft); color: var(--zb-brand); }

/* ═══ ۱۴. آیکون ═══════════════════════════════════════════════════════
   خطی · ضخامت ۱٫۸ · currentColor. رنگِ ثابت روی آیکون ممنوع —
   وگرنه در تمِ سالن اشتباه درمی‌آید. */
.zb-ico { width: 24px; height: 24px; flex-shrink: 0; stroke-width: 1.8;
    fill: none; stroke: currentColor; }
.zb-ico--sm { width: 18px; height: 18px; }
.zb-ico--lg { width: 32px; height: 32px; }
.zb-ico--xl { width: 48px; height: 48px; stroke-width: 1.4; }
/* کاشیِ آیکون با تینتِ معنایی */
.zb-ico-tile { width: 40px; height: 40px; border-radius: var(--zb-r-md);
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.zb-ico-tile--brand { background: var(--zb-brand-soft); color: var(--zb-brand); }
.zb-ico-tile--ok   { background: var(--zb-ok-bg);   color: var(--zb-ok); }
.zb-ico-tile--err  { background: var(--zb-err-bg);  color: var(--zb-err); }
.zb-ico-tile--warn { background: var(--zb-warn-bg); color: var(--zb-warn); }
.zb-ico-tile--gold { background: var(--zb-gold-soft); color: var(--zb-gold-deep); }

/* ═══ ۱۵. ناوبری ═════════════════════════════════════════════════════ */

/* دکمهٔ بازگشت — «هیچ بن‌بستی» (ARCHITECTURE-UX-AUDIT اصل ۴).
   الان فقط ۶ صفحه از ۳۵ صفحهٔ پنل دارندش. */
.zb-back {
    display: inline-flex; align-items: center; gap: var(--zb-s2);
    min-height: 40px; padding: 0 var(--zb-s3) 0 var(--zb-s2);
    font-size: var(--zb-t-sm); font-weight: 600; color: var(--zb-ink-2);
    background: none; border: 0; border-radius: var(--zb-r-md);
    text-decoration: none; cursor: pointer; font-family: inherit;
    transition: background-color .2s var(--zb-ease-io), color .2s var(--zb-ease-io);
}
.zb-back:hover { background: var(--zb-line-soft); color: var(--zb-ink); }
.zb-back svg { transition: transform .25s var(--zb-ease); }
.zb-back:hover svg { transform: translateX(3px); }

/* بردکرامب */
.zb-crumbs { display: flex; align-items: center; flex-wrap: wrap; gap: var(--zb-s2);
    font-size: var(--zb-t-xs); color: var(--zb-ink-3); }
.zb-crumbs a { color: var(--zb-brand); font-weight: 600; text-decoration: none; }
.zb-crumbs a:hover { text-decoration: underline; }
.zb-crumbs [aria-current="page"] { color: var(--zb-ink-2); font-weight: 600; }
.zb-crumbs-sep { color: var(--zb-line); }

/* پیوندِ ناوبری با زیرخطِ کشیده */
.zb-navlink { position: relative; font-size: var(--zb-t-sm); font-weight: 600;
    color: var(--zb-ink-2); text-decoration: none; padding: var(--zb-s2) 0;
    transition: color .2s var(--zb-ease-io); }
.zb-navlink:hover { color: var(--zb-ink); }
.zb-navlink::after { content: ''; position: absolute; inset-inline: 0; bottom: 0;
    height: 1.5px; background: var(--zb-brand); border-radius: 2px;
    transform: scaleX(0); transform-origin: right;
    transition: transform .35s var(--zb-ease); }
.zb-navlink:hover::after { transform: scaleX(1); transform-origin: left; }
.zb-navlink[aria-current]::after { transform: scaleX(1); }

/* پیوندِ سایدبار — حالت فعال با نوارِ داخلیِ سمت راست */
.zb-side-link { display: flex; align-items: center; gap: var(--zb-s3);
    padding: var(--zb-s3) var(--zb-s4); border-radius: var(--zb-r-md);
    font-size: var(--zb-t-sm); font-weight: 500; color: var(--zb-ink-2);
    text-decoration: none;
    transition: background-color .2s var(--zb-ease-io), color .2s var(--zb-ease-io); }
.zb-side-link:hover { background: var(--zb-line-soft); color: var(--zb-ink); }
.zb-side-link[aria-current] { font-weight: 700; color: var(--zb-brand);
    background: var(--zb-brand-soft); box-shadow: inset 3px 0 0 var(--zb-brand); }
.zb-side-badge { margin-inline-start: auto; min-width: 20px; height: 20px; padding: 0 6px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--zb-r-pill); background: var(--zb-brand); color: #fff;
    font-size: .6875rem; font-weight: 700; }

/* سربرگِ بخشِ سایدبار */
.zb-side-section { font-size: .625rem; font-weight: 700; letter-spacing: .04em;
    color: var(--zb-ink-3); text-transform: uppercase;
    padding: var(--zb-s4) var(--zb-s4) var(--zb-s2); }

/* ═══ ۱۶. مودال ═══════════════════════════════════════════════════════
   با <dialog> بومی کار می‌کند (قفلِ فوکوس و Esc رایگان) و با div هم.
   قانون: هر کنشِ برگشت‌ناپذیر باید بگوید دقیقاً چه چیزی حذف می‌شود. */
.zb-modal { border: 0; padding: 0; background: transparent; max-width: min(520px, 92vw); width: 100%; }
.zb-modal::backdrop { background: rgba(35,31,38,.45); backdrop-filter: blur(3px); }
.zb-modal-panel {
    background: var(--zb-surface); border-radius: var(--zb-r-lg);
    box-shadow: var(--zb-shadow-lg); overflow: hidden;
    animation: zbModalIn .28s var(--zb-ease);
}
@keyframes zbModalIn { from { opacity: 0; transform: translateY(12px) scale(.98); }
                       to   { opacity: 1; transform: none; } }
.zb-modal-head { display: flex; align-items: flex-start; gap: var(--zb-s3);
    padding: var(--zb-s5) var(--zb-s5) var(--zb-s3); }
.zb-modal-title { font-size: var(--zb-t-lg); font-weight: 800; color: var(--zb-ink); }
.zb-modal-body { padding: 0 var(--zb-s5) var(--zb-s5); font-size: var(--zb-t-sm);
    color: var(--zb-ink-2); line-height: 2; }
.zb-modal-foot { display: flex; gap: var(--zb-s2); justify-content: flex-start;
    padding: var(--zb-s4) var(--zb-s5); background: var(--zb-bg);
    border-top: 1px solid var(--zb-line); }
.zb-modal-close { margin-inline-start: auto; background: none; border: 0; cursor: pointer;
    color: var(--zb-ink-3); padding: var(--zb-s1); border-radius: var(--zb-r-sm);
    line-height: 0; }
.zb-modal-close:hover { background: var(--zb-line-soft); color: var(--zb-ink); }
/* مودالِ خطرناک: عنوان قرمز و کاشیِ قرمز، نه کلِ مودالِ قرمز */
.zb-modal--danger .zb-modal-title { color: var(--zb-err); }

/* ═══ ۱۷. توست ═══════════════════════════════════════════════════════ */
.zb-toast-wrap { position: fixed; top: var(--zb-s4); inset-inline: 0; z-index: 200;
    display: flex; flex-direction: column; align-items: center; gap: var(--zb-s2);
    pointer-events: none; padding: 0 var(--zb-s4); }
.zb-toast { pointer-events: auto; display: flex; align-items: center; gap: var(--zb-s3);
    max-width: 460px; width: 100%; padding: var(--zb-s3) var(--zb-s4);
    border-radius: var(--zb-r-md); background: var(--zb-surface);
    border: 1px solid var(--zb-line); box-shadow: var(--zb-shadow-lg);
    font-size: var(--zb-t-sm); font-weight: 600; color: var(--zb-ink);
    animation: zbToastIn .3s var(--zb-ease); }
@keyframes zbToastIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
.zb-toast--ok   { border-inline-end: 3px solid var(--zb-ok); }
.zb-toast--err  { border-inline-end: 3px solid var(--zb-err); }
.zb-toast--warn { border-inline-end: 3px solid var(--zb-warn); }
.zb-toast--info { border-inline-end: 3px solid var(--zb-brand); }

@media (prefers-reduced-motion: reduce) {
    .zb-modal-panel, .zb-toast { animation: none; }
    .zb-back svg, .zb-navlink::after, .zb-card, .zb-card--link .zb-card-arrow { transition: none; }
}

/* ═══ ۱۸. سکشن — ریتم عمودی صفحه ═══════════════════════════════════════
   UI-ELEMENT-SPEC اصل ۴: بخش‌ها یک‌درمیان زمینه عوض می‌کنند. این تنها
   چیزی است که به صفحهٔ بلند «فصل‌بندی» می‌دهد بدون خط کشیدن. */
.zb-section { padding: var(--zb-s8) 0; }
.zb-section--tight { padding: var(--zb-s6) 0; }
.zb-section--alt { background: var(--zb-bg); }
.zb-wrap { max-width: 1080px; margin: 0 auto; padding-inline: clamp(1.25rem, 5vw, 2.5rem); }
.zb-wrap--narrow { max-width: 720px; }

.zb-section-head { margin-bottom: var(--zb-s6); }
.zb-section-head--center { text-align: center; }
/* روتیتر با خطِ طلاییِ کوتاه — جزئیاتِ گران، یک پیکسل */
.zb-eyebrow { display: inline-flex; align-items: center;
    font-size: var(--zb-t-xs); font-weight: 700; color: var(--zb-brand);
    letter-spacing: .02em; }
.zb-eyebrow::before { content: ''; display: inline-block; width: 26px; height: 1px;
    margin-inline-end: var(--zb-s2);
    background: linear-gradient(90deg, var(--zb-gold), transparent); }
.zb-section-title { font-size: var(--zb-t-h2); font-weight: 800; color: var(--zb-ink);
    margin-top: var(--zb-s2); line-height: 1.6; }
.zb-section-lead { font-size: var(--zb-t-body); color: var(--zb-ink-2);
    margin-top: var(--zb-s3); line-height: 2; max-width: 62ch; }

/* ═══ ۱۹. سربرگ صفحه — پنل ═══════════════════════════════════════════ */
.zb-pagehead { display: flex; align-items: flex-start; gap: var(--zb-s4);
    flex-wrap: wrap; margin-bottom: var(--zb-s5);
    padding-bottom: var(--zb-s4); border-bottom: 1px solid var(--zb-line); }
.zb-pagehead-main { min-width: 0; flex: 1; }
.zb-pagehead-title { font-size: var(--zb-t-h1); font-weight: 800; color: var(--zb-ink);
    line-height: 1.5; }
.zb-pagehead-sub { font-size: var(--zb-t-sm); color: var(--zb-ink-3); margin-top: var(--zb-s1); }
/* اکشن‌ها همیشه در انتهای خط، روی موبایل تمام‌عرض */
.zb-pagehead-actions { display: flex; align-items: center; gap: var(--zb-s2);
    margin-inline-start: auto; flex-wrap: wrap; }
@media (max-width: 640px) {
    .zb-pagehead-actions { width: 100%; margin-inline-start: 0; }
    .zb-pagehead-actions > * { flex: 1; justify-content: center; }
}

/* ═══ ۲۰. نوار اکشن ═════════════════════════════════════════════════════
   ردیفِ کنش‌های یک فهرست: جست‌وجو + فیلتر + دکمهٔ اصلی. */
.zb-actionbar { display: flex; align-items: center; gap: var(--zb-s2);
    flex-wrap: wrap; margin-bottom: var(--zb-s4); }
.zb-actionbar-grow { flex: 1; min-width: 200px; }
.zb-actionbar-end { margin-inline-start: auto; display: flex; gap: var(--zb-s2); }

/* چیپِ فیلتر — حالت فعال با رنگِ برند پر می‌شود */
.zb-chip { display: inline-flex; align-items: center; gap: var(--zb-s1);
    min-height: 36px; padding: 0 var(--zb-s3);
    font-size: var(--zb-t-xs); font-weight: 600; color: var(--zb-ink-2);
    background: var(--zb-surface); border: 1px solid var(--zb-line);
    border-radius: var(--zb-r-pill); text-decoration: none; cursor: pointer;
    transition: border-color .2s var(--zb-ease-io), color .2s var(--zb-ease-io); }
.zb-chip:hover { border-color: var(--zb-brand); color: var(--zb-brand); }
.zb-chip[aria-pressed="true"], .zb-chip--on {
    background: var(--zb-brand); border-color: var(--zb-brand); color: #fff; }

/* ═══ ۲۱. بنر ═════════════════════════════════════════════════════════
   اعلان در جریانِ صفحه (نه توست). چهار لحن، لبهٔ رنگی سمت راست. */
.zb-banner { display: flex; align-items: flex-start; gap: var(--zb-s3);
    padding: var(--zb-s4); border-radius: var(--zb-r-md);
    background: var(--zb-surface); border: 1px solid var(--zb-line);
    font-size: var(--zb-t-sm); color: var(--zb-ink-2); line-height: 1.9; }
.zb-banner-title { font-weight: 700; color: var(--zb-ink); margin-bottom: 2px; }
.zb-banner--info { border-inline-end: 3px solid var(--zb-brand); background: var(--zb-brand-soft); }
.zb-banner--ok   { border-inline-end: 3px solid var(--zb-ok);   background: var(--zb-ok-bg); }
.zb-banner--warn { border-inline-end: 3px solid var(--zb-warn); background: var(--zb-warn-bg); }
.zb-banner--err  { border-inline-end: 3px solid var(--zb-err);  background: var(--zb-err-bg); }
/* بنرِ تبلیغاتیِ تمام‌عرض — بازارگاه */
.zb-banner--hero { padding: var(--zb-s6); border: 0; color: #fff;
    background: linear-gradient(135deg, var(--zb-brand), var(--zb-brand-deep));
    border-radius: var(--zb-r-lg); }
.zb-banner--hero .zb-banner-title { color: #fff; font-size: var(--zb-t-lg); }

/* ═══ ۲۲. تاریخ و زمانِ شمسی ═══════════════════════════════════════════
   ⚠️ قانون: تاریخ همیشه با |jalali_date یا |jalali_datetime رندر می‌شود و
   عدد همیشه با |to_persian. این کلاس‌ها فقط **نمایش** را استاندارد
   می‌کنند؛ تبدیل کارِ فیلترِ سمت سرور است، نه CSS.
   ساعت و کدِ رزرو `dir="ltr"` می‌گیرند وگرنه در RTL جابه‌جا خوانده می‌شوند. */
.zb-date { font-variant-numeric: tabular-nums; white-space: nowrap; }
.zb-date-sm { font-size: var(--zb-t-xs); color: var(--zb-ink-3); }
.zb-time { font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: isolate;
    display: inline-block; white-space: nowrap; }
/* بازهٔ ساعت: «۱۰:۰۰ – ۱۱:۳۰» — جداکنندهٔ en-dash با فاصلهٔ نازک */
.zb-timerange { direction: ltr; unicode-bidi: isolate; display: inline-block;
    font-variant-numeric: tabular-nums; white-space: nowrap; }

/* کاشیِ تاریخ — روز بزرگ، ماه کوچک. برای کارت نوبت. */
.zb-datetile { display: inline-flex; flex-direction: column; align-items: center;
    justify-content: center; flex-shrink: 0;
    width: 52px; height: 56px; border-radius: var(--zb-r-md);
    background: var(--zb-brand-soft); color: var(--zb-brand); line-height: 1.3; }
.zb-datetile-day { font-size: var(--zb-t-lg); font-weight: 800; font-variant-numeric: tabular-nums; }
.zb-datetile-mon { font-size: .625rem; font-weight: 600; opacity: .85; }
.zb-datetile--today { background: var(--zb-brand); color: #fff; }
.zb-datetile--past { background: var(--zb-line-soft); color: var(--zb-ink-3); }

/* ═══ ۲۳. تقویم ═════════════════════════════════════════════════════════
   شبکهٔ هفت‌ستونه، RTL بومی (شنبه اولِ هفته است، پس ستونِ اول سمت راست). */
.zb-cal { --zb-cal-gap: 6px; }
.zb-cal-head { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--zb-cal-gap);
    margin-bottom: var(--zb-s2); }
.zb-cal-dow { text-align: center; font-size: .6875rem; font-weight: 700;
    color: var(--zb-ink-3); padding: var(--zb-s1) 0; }
.zb-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--zb-cal-gap); }
.zb-cal-day {
    position: relative; aspect-ratio: 1; min-height: 44px;   /* هدفِ لمس */
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; border-radius: var(--zb-r-md);
    background: var(--zb-surface); border: 1px solid var(--zb-line);
    font-size: var(--zb-t-sm); font-weight: 600; color: var(--zb-ink);
    font-variant-numeric: tabular-nums;
    cursor: pointer; text-decoration: none;
    transition: border-color .2s var(--zb-ease-io), transform .2s var(--zb-ease-io);
}
.zb-cal-day:hover { border-color: var(--zb-brand); transform: translateY(-1px); }
.zb-cal-day--muted { color: var(--zb-ink-3); background: var(--zb-bg); }
.zb-cal-day--today { border-color: var(--zb-brand); border-width: 2px; font-weight: 800; }
.zb-cal-day--selected { background: var(--zb-brand); border-color: var(--zb-brand); color: #fff; }
/* روزِ بی‌ظرفیت: خاموش و غیرقابل‌کلیک — نه قرمز.
   نبودِ ظرفیت یک واقعیت است، نه خطا. */
.zb-cal-day--full { background: var(--zb-line-soft); color: var(--zb-ink-3);
    cursor: not-allowed; pointer-events: none; }
/* نقطهٔ ظرفیت زیر عدد */
.zb-cal-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--zb-ok); }
.zb-cal-day--selected .zb-cal-dot { background: #fff; }
.zb-cal-day--full .zb-cal-dot { background: var(--zb-ink-3); }

/* اسلاتِ ساعت — شبکهٔ انتخاب زمان */
.zb-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
    gap: var(--zb-s2); }
.zb-slot { min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--zb-r-md); background: var(--zb-surface);
    border: 1px solid var(--zb-line); cursor: pointer; text-decoration: none;
    font-size: var(--zb-t-sm); font-weight: 700; color: var(--zb-ink);
    font-variant-numeric: tabular-nums; direction: ltr;
    transition: border-color .2s var(--zb-ease-io), transform .2s var(--zb-ease-io); }
.zb-slot:hover { border-color: var(--zb-brand); transform: translateY(-1px); }
.zb-slot--selected { background: var(--zb-brand); border-color: var(--zb-brand); color: #fff; }
.zb-slot--taken { background: var(--zb-line-soft); color: var(--zb-ink-3);
    text-decoration: line-through; cursor: not-allowed; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
    .zb-cal-day, .zb-slot, .zb-chip { transition: none; }
}

/* ═══ [IMPL-NAV J3/J5] سایدبار گروهی — گروه‌های بازشو با وضعیت ذخیره ═══
   LAYOUT-NAVIGATION-SPEC §۴: گروه‌ها باز و بسته می‌شوند، حالتشان در
   localStorage می‌ماند و گروهِ صفحهٔ فعلی خودکار باز می‌شود (JS در
   dashboard_base.html). تعریف فقط این‌جا — نه <style> صفحه (UI §۰). */
.zb-navgroup { margin: 1px 0; }
.zb-navgroup-head {
    display: flex; align-items: center; gap: var(--zb-s2);
    width: 100%; padding: 7px var(--zb-s3); margin-top: var(--zb-s2);
    border: 0; border-radius: var(--zb-r-sm); background: transparent;
    cursor: pointer; text-align: start;
    font-family: inherit; font-size: var(--zb-t-xs); font-weight: 700;
    letter-spacing: .02em; color: var(--zb-ink-3);
}
.zb-navgroup-head:hover { background: var(--zb-brand-soft); color: var(--zb-ink-2); }
.zb-navgroup-caret { margin-inline-start: auto; width: 14px; height: 14px; flex-shrink: 0;
    transition: transform .2s var(--zb-ease-io); }
.zb-navgroup--open .zb-navgroup-caret { transform: rotate(180deg); }
.zb-navgroup-items { display: none; }
.zb-navgroup--open .zb-navgroup-items { display: block; }

@media (prefers-reduced-motion: reduce) {
    .zb-navgroup-caret { transition: none; }
}

/* ═══ [LEAD K3/K4] «نوبت بعدی» و هدف‌های لمسیِ آرایشگر ═══════════════════
   LAYOUT-NAVIGATION-SPEC §۵ — سناریو: «بین دو مشتری، با گوشی».

   دو یافتهٔ ممیزی که این بلوک جواب می‌دهد:
     ۱. مهم‌ترین سؤالِ آرایشگر («بعدی کیه؟») در بلوکِ چهارم بود، زیر سه
        کارت نمودار. صفحه بر اساس «چه داده‌ای داریم» چیده شده بود، نه
        «کاربر چه می‌خواهد».
     ۲. دکمه‌های «تأیید / تکمیل / عدم حضور» با `padding` سه‌پیکسلی و متنِ
        ۱۰px ساخته شده بودند — هم زیر کفِ ۱۳px متن، هم حدود ۲۲px ارتفاع.
        دستِ آرایشگر ممکن است خیس یا دستکش‌دار باشد؛ هدف ۴۸px است نه ۴۴.
   ══════════════════════════════════════════════════════════════════════ */
.zb-next {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--zb-s4);
    padding: var(--zb-s4) var(--zb-s5);
    border-radius: var(--zb-r-lg);
    background: linear-gradient(135deg, var(--zb-brand), var(--zb-brand-deep));
    color: #fff;
    box-shadow: var(--zb-shadow-lg);
    position: relative; overflow: hidden;
}
/* همان بافتِ لوزیِ سربرگ رسید — برندینگ در هر نقطه (§۸) */
.zb-next::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: repeating-linear-gradient(45deg,
        rgba(255,255,255,.05) 0 2px, transparent 2px 9px);
}
.zb-next > * { position: relative; }
.zb-next-when {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-width: 82px; padding: var(--zb-s2) var(--zb-s3);
    border-radius: var(--zb-r-md);
    background: rgba(255,255,255,.14);
    border: 1px solid rgba(255,255,255,.22);
}
.zb-next-time { font-size: var(--zb-t-h2); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.2; }
.zb-next-day  { font-size: var(--zb-t-xs); opacity: .82; margin-top: 2px; }
.zb-next-main { flex: 1 1 220px; min-width: 0; }
.zb-next-eyebrow {
    font-size: var(--zb-t-xs); font-weight: 700; letter-spacing: .02em;
    opacity: .78; margin-bottom: var(--zb-s1);
}
.zb-next-who { font-size: var(--zb-t-lg); font-weight: 800; margin: 0 0 2px; }
.zb-next-what { font-size: var(--zb-t-sm); opacity: .86; margin: 0; }
.zb-next-note {
    margin-top: var(--zb-s2); padding: var(--zb-s2) var(--zb-s3);
    border-radius: var(--zb-r-sm);
    background: rgba(0,0,0,.16);
    font-size: var(--zb-t-xs); line-height: 1.9;
}
.zb-next-acts { display: flex; flex-wrap: wrap; gap: var(--zb-s2); }

/* نوارِ امروز — «۵ نوبت · ۳ انجام‌شده · ۲ مانده» */
.zb-daystrip {
    display: flex; flex-wrap: wrap; gap: var(--zb-s2);
    padding: var(--zb-s3) var(--zb-s4);
    border: 1px solid var(--zb-line); border-radius: var(--zb-r-md);
    background: var(--zb-surface);
}
.zb-daystrip-cell { flex: 1 1 90px; text-align: center; }
.zb-daystrip-num {
    font-size: var(--zb-t-h2); font-weight: 800; line-height: 1.1;
    font-variant-numeric: tabular-nums; color: var(--zb-ink);
}
.zb-daystrip-num--ok  { color: var(--zb-ok); }
.zb-daystrip-num--now { color: var(--zb-brand); }
.zb-daystrip-lbl { font-size: var(--zb-t-xs); color: var(--zb-ink-3); margin-top: 2px; }

/* هدفِ لمسی ۴۸px — قاعدهٔ الزامیِ §۵ */
.zb-touch {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--zb-s2);
    min-height: 48px; min-width: 48px; padding: 0 var(--zb-s4);
    border: 1px solid transparent; border-radius: var(--zb-r-sm);
    background: var(--zb-brand); color: #fff;
    font-family: inherit; font-size: var(--zb-t-sm); font-weight: 700;
    cursor: pointer; text-decoration: none;
    transition: transform .16s var(--zb-ease), filter .16s var(--zb-ease-io);
}
.zb-touch:hover  { filter: brightness(1.06); }
.zb-touch:active { transform: translateY(1px); }
.zb-touch--ghost {
    background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.3); color: #fff;
}
.zb-touch--ghost:hover { background: rgba(255,255,255,.26); }
.zb-touch--ok    { background: var(--zb-ok-bg);  color: #14663b; border-color: rgba(30,158,90,.3); }
.zb-touch--err   { background: var(--zb-err-bg); color: #8f2020; border-color: rgba(211,58,58,.28); }
.zb-touch--muted { background: var(--zb-line-soft); color: var(--zb-ink-2); border-color: var(--zb-line); }

@media (prefers-reduced-motion: reduce) {
    .zb-touch { transition: none; }
    .zb-touch:active { transform: none; }
}

/* ═══ [LEAD] پروفایل عمومی، تخصص‌ها و روزهای کاری ════════════════════════
   دستور مالک ۲۰۲۶-۰۹-۰۵: «تنظیم منوی خدمات و تخصص‌ها و خدمات باید همه‌جا
   بازطراحی شوند».

   یافتهٔ ممیزی: منوی خدمات **یک‌بار درست ساخته شده بود** — `zh-svc` در
   صفحهٔ سالن: بندانگشتی، نقطه‌چینِ رهنما مثل منوی رستوران، قیمتِ خط‌خورده،
   برچسب و مدت. ولی صفحهٔ آرایشگر نسخهٔ خودش (`sp-svc`) را داشت: یک ردیفِ
   ساده با ۲۵ خط `<style>` داخل صفحه. پس راه‌حل «طراحیِ سوم» نیست؛ همان
   منوی خوب باید همه‌جا برود. این بلوک فقط چیزی را می‌سازد که `zh-*` ندارد.
   ══════════════════════════════════════════════════════════════════════ */
.zb-prof {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--zb-s5);
    padding: var(--zb-s6) 0 var(--zb-s5);
}
.zb-prof-avatar {
    width: 132px; height: 132px; border-radius: 50%; object-fit: cover;
    flex-shrink: 0; background: var(--zb-brand-soft);
    border: 4px solid var(--zb-surface);
    box-shadow: 0 0 0 1px var(--zb-line), var(--zb-shadow-lg);
}
.zb-prof-avatar--mono {
    display: flex; align-items: center; justify-content: center;
    font-size: 2.75rem; font-weight: 800;
    background: var(--zb-brand); color: #fff;
}
.zb-prof-main { flex: 1 1 260px; min-width: 0; }
.zb-prof-name { font-size: var(--zb-t-h1); font-weight: 800; color: var(--zb-ink); margin: 0; }
.zb-prof-headline { font-size: var(--zb-t-body); color: var(--zb-ink-2); margin: var(--zb-s2) 0 0; }
.zb-prof-meta {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--zb-s2) var(--zb-s4);
    margin-top: var(--zb-s3); font-size: var(--zb-t-sm); color: var(--zb-ink-3);
}
.zb-prof-meta b { color: var(--zb-ink); font-weight: 700; }
.zb-prof-cta { display: flex; flex-wrap: wrap; gap: var(--zb-s2); margin-top: var(--zb-s4); }

/* تخصص‌ها — چیپِ خواناتر از برچسبِ ریزِ کنارِ نام. تخصص یک ادعای حرفه‌ای
   است، نه یک فراداده؛ اندازه‌اش باید همان را بگوید. */
.zb-specs { display: flex; flex-wrap: wrap; gap: var(--zb-s2); margin-top: var(--zb-s3); }
.zb-spec {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 7px var(--zb-s3); border-radius: var(--zb-r-pill);
    background: var(--zb-brand-soft); color: var(--zb-brand);
    border: 1px solid color-mix(in srgb, var(--zb-brand) 22%, transparent);
    font-size: var(--zb-t-xs); font-weight: 700;
}
.zb-spec::before {
    content: ''; width: 5px; height: 5px; border-radius: 50%;
    background: currentColor; opacity: .55;
}

/* نوارِ ارقام — امتیاز، تجربه، نظر، خدمت */
.zb-facts {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: var(--zb-s2);
    padding: var(--zb-s4); margin-top: var(--zb-s3);
    border: 1px solid var(--zb-line); border-radius: var(--zb-r-lg);
    background: var(--zb-surface);
}
.zb-fact { text-align: center; }
.zb-fact-num {
    font-size: var(--zb-t-h2); font-weight: 800; color: var(--zb-ink);
    font-variant-numeric: tabular-nums; line-height: 1.15;
}
.zb-fact-lbl { font-size: var(--zb-t-xs); color: var(--zb-ink-3); margin-top: 3px; }

/* روزهای کاری — هفت خانه، همیشه هفت. روزِ تعطیل حذف نمی‌شود، خاموش
   می‌شود؛ جای خالی خواننده را مجبور می‌کند بشمارد. */
.zb-week { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: var(--zb-s2); }
.zb-weekday {
    padding: var(--zb-s3) var(--zb-s2); border-radius: var(--zb-r-md);
    border: 1px solid var(--zb-line); background: var(--zb-surface);
    text-align: center;
}
.zb-weekday-name { font-size: var(--zb-t-xs); font-weight: 700; color: var(--zb-ink); }
.zb-weekday-hrs {
    font-size: var(--zb-t-xs); color: var(--zb-ok); margin-top: 3px;
    font-variant-numeric: tabular-nums; direction: ltr;
}
.zb-weekday--off { background: var(--zb-line-soft); border-color: transparent; }
.zb-weekday--off .zb-weekday-name { color: var(--zb-ink-3); }
.zb-weekday--off .zb-weekday-hrs { color: var(--zb-ink-3); direction: rtl; }

/* گالریِ نمونه‌کار */
.zb-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--zb-s2); }
.zb-gallery img {
    width: 100%; aspect-ratio: 1; object-fit: cover;
    border-radius: var(--zb-r-md); display: block;
    background: var(--zb-line-soft);
}

/* ═══ [LEAD K4] ردیفِ تایم‌لاینِ نوبت — روزِ سالن در یک نگاه ═════════════
   LAYOUT-NAVIGATION-SPEC §۴ ردیف ۳. جدولِ هشت‌ستونیِ قبلی داده را نشان
   می‌داد ولی **شکلِ روز** را نه: کجای روز شلوغ است، کدام نوبت گذشته و
   ثبت نشده، بعدی کیست. تایم‌لاین همان داده را در همان فضا می‌گوید.

   دو حالتِ تازه که کامپوننتِ پایه نداشت:
     · `--done` سبز  — انجام شد (رنگِ معنایی، تم‌پذیر نیست)
     · `--late` کهربایی — ساعتش گذشته و هنوز تکمیل نشده. این یک
       **سیگنالِ کاری** است نه تزیین: یا مشتری نیامده یا کسی یادش
       رفته ثبت کند. سالن‌دار باید ببیندش. */
.zb-timeline-item--done .zb-timeline-dot { background: var(--zb-ok); }
.zb-timeline-item--late .zb-timeline-dot { background: var(--zb-warn); }
.zb-timeline-item--late .zb-tlrow { background: var(--zb-warn-bg); border-color: rgba(183,121,31,.22); }

.zb-tlrow {
    display: flex; align-items: center; gap: var(--zb-s3);
    padding: var(--zb-s3); border-radius: var(--zb-r-md);
    border: 1px solid var(--zb-line); background: var(--zb-surface);
    text-decoration: none; color: inherit;
    transition: border-color .16s var(--zb-ease-io), transform .16s var(--zb-ease);
}
.zb-tlrow:hover { border-color: var(--zb-brand); transform: translateX(-2px); }
.zb-tlrow-time {
    flex-shrink: 0; min-width: 52px; text-align: center;
    font-size: var(--zb-t-sm); font-weight: 800; color: var(--zb-ink);
    font-variant-numeric: tabular-nums; direction: ltr;
}
.zb-tlrow-main { flex: 1; min-width: 0; }
.zb-tlrow-who {
    font-size: var(--zb-t-sm); font-weight: 700; color: var(--zb-ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.zb-tlrow-what {
    font-size: var(--zb-t-xs); color: var(--zb-ink-3); margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.zb-tlrow-end { flex-shrink: 0; display: flex; align-items: center; gap: var(--zb-s2); }
.zb-tlrow-sum { font-size: var(--zb-t-xs); color: var(--zb-ink-2); font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
    .zb-tlrow-sum { display: none; }   /* روی گوشی نام و ساعت مهم‌ترند */
}

/* ═══ [LEAD] گام‌نمای چرخهٔ نوبت ═══════════════════════════════════════
   ایدهٔ خام از پنلِ dicardo (دستور مالک ۲۰۲۶-۰۹-۰۵): در فهرست سفارش‌ها،
   هر ردیف یک نوارِ چهارگامی دارد و کاربر بدون باز کردنِ سفارش می‌بیند
   کارش کجاست.

   چرا برای زیباتو مهم است: مشتری تا امروز فقط یک **نشانِ وضعیت** می‌دید
   («تأیید شده»). نشان می‌گوید الان کجاست، ولی نمی‌گوید **بعدش چه
   می‌شود** و **منتظر کیست**. سؤالِ واقعیِ مشتری همین دومی است.

   چهار گامِ زیباتو: ثبت ← تأیید سالن ← پرداخت ← انجام.
   `--done` سبز (رنگِ معنایی) · `--now` برندی با نبض · بقیه خاکستری.

   لغوشده گام‌نما نمی‌گیرد: گام‌نما یعنی «در جریان است»، و برای نوبتی
   که لغو شده دروغ می‌گوید. آن‌جا نوارِ قرمزِ ساده می‌آید.
   ══════════════════════════════════════════════════════════════════ */
.zb-steps {
    display: flex; align-items: flex-start;
    list-style: none; margin: 0; padding: 0;
}
.zb-step { flex: 1; position: relative; text-align: center; min-width: 0; }
/* ریل بین گام‌ها — از مرکزِ هر نقطه تا مرکزِ بعدی */
.zb-step::before {
    content: ''; position: absolute; top: 6px; height: 2px;
    inset-inline-start: 50%; width: 100%;
    background: var(--zb-line);
}
.zb-step:last-child::before { display: none; }
/* ریل فقط وقتی سبز می‌شود که **دو سرش** تمام شده باشند.
   قاعدهٔ ساده‌ی «بعد از هر گامِ تمام‌شده سبز کن» دروغ می‌گفت: پرداخت و
   تأییدِ سالن در زیباتو **مستقل**اند و به هر ترتیبی رخ می‌دهند، پس
   الگوی ●◉●○ واقعی است — ولی ریلِ سبزِ منتهی به یک گامِ انجام‌نشده
   مثل باگ دیده می‌شد. `:has` این را دقیق می‌کند. */
.zb-step--done:has(+ .zb-step--done)::before { background: var(--zb-ok); }

.zb-step-dot {
    position: relative; z-index: 1;
    display: block; width: 14px; height: 14px; margin: 0 auto;
    border-radius: 50%;
    background: var(--zb-surface);
    box-shadow: 0 0 0 2px var(--zb-line) inset;
}
.zb-step--done .zb-step-dot { background: var(--zb-ok); box-shadow: none; }
.zb-step--now  .zb-step-dot { background: var(--zb-brand); box-shadow: none; }
.zb-step--now  .zb-step-dot::after {
    content: ''; position: absolute; inset: -3px; border-radius: 50%;
    border: 2px solid var(--zb-brand); opacity: .45;
    animation: zbStepPulse 2.2s ease-out infinite;
}
@keyframes zbStepPulse {
    0%   { transform: scale(.8); opacity: .5; }
    100% { transform: scale(1.7); opacity: 0; }
}
.zb-step-label {
    display: block; margin-top: 7px;
    font-size: var(--zb-t-xs); color: var(--zb-ink-3);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.zb-step--done .zb-step-label { color: var(--zb-ink-2); }
.zb-step--now  .zb-step-label { color: var(--zb-brand); font-weight: 700; }

/* خطِ «یعنی چه» — نامِ وضعیت کافی نیست، مشتری می‌خواهد بداند
   منتظرِ کیست و خودش باید کاری بکند یا نه (CONTENT-SPEC: «بگو چه کار کنم») */
.zb-steps-note {
    margin-top: var(--zb-s3); padding: var(--zb-s2) var(--zb-s3);
    border-radius: var(--zb-r-sm);
    background: var(--zb-brand-soft); color: var(--zb-ink-2);
    font-size: var(--zb-t-xs); line-height: 1.9;
}
.zb-steps-note--warn { background: var(--zb-warn-bg); color: #7a5410; }
.zb-steps-note--err  { background: var(--zb-err-bg);  color: #8f2020; }

@media (prefers-reduced-motion: reduce) {
    .zb-step--now .zb-step-dot::after { animation: none; }
}

/* چیپِ فیلتر با شمارنده — شمارنده داخلِ خودِ چیپ، و چیپِ صفر هم می‌ماند
   تا کاربر بداند آن حالت وجود دارد و خالی است. */
.zb-filters { display: flex; flex-wrap: wrap; gap: var(--zb-s2); }
.zb-filter {
    display: inline-flex; align-items: center; gap: var(--zb-s2);
    min-height: 40px; padding: 0 var(--zb-s3);
    border: 1px solid var(--zb-line); border-radius: var(--zb-r-pill);
    background: var(--zb-surface); color: var(--zb-ink-2);
    font-size: var(--zb-t-sm); font-weight: 600; text-decoration: none;
    transition: border-color .16s var(--zb-ease-io);
}
.zb-filter:hover { border-color: var(--zb-brand); }
.zb-filter-n {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 22px; height: 20px; padding: 0 6px;
    border-radius: var(--zb-r-pill);
    background: var(--zb-line-soft); color: var(--zb-ink-3);
    font-size: var(--zb-t-xs); font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.zb-filter.is-on {
    background: var(--zb-brand); border-color: var(--zb-brand); color: #fff;
}
.zb-filter.is-on .zb-filter-n { background: rgba(255,255,255,.22); color: #fff; }

/* ═══ [LEAD 2026-09-05] هدفِ لمسی در ناوبریِ پنل ═══════════════════════
   دستور مالک: «پروژه برای موبایل واقعاً باید مناسب باشد».

   ممیزیِ لمسی روی پنل سوپرادمین با عرض ۳۷۵px: **۱۴ هدفِ زیر ۴۰px**.
   ولی چهارده جا نبود — دو قاعده بود:
     `.sidebar-link`      ۳۷px
     `.zb-navgroup-head`  ۳۴px

   کفِ ۴۴px استانداردِ WCAG 2.5.5 (AAA) و همان چیزی است که
   UI-ELEMENT-SPEC §۰ نوشته. روی دسکتاپ هم ضرری ندارد: سایدبار
   جای عمودی کم نمی‌آورد و ردیف‌های بازتر خوانا‌ترند.

   `min-height` است نه `height` تا آیتم‌های دوخطی نشکنند. */
.sidebar-link,
.zb-navgroup-head {
    min-height: 44px;
}

/* ═══ [LEAD 2026-09-05 · R1] هدف لمسی — قواعد مشترک ═══════════════════
   ممیزیِ ۳۷۵px روی هر چهار نقش. نتیجه همان الگوی همیشگی بود: ده‌ها
   «مورد»، ولی چند **قاعده**. تک‌تکِ نمونه‌ها را درست کردن یعنی دفعهٔ
   بعد دوباره از نو.

   کف: ۴۴px (WCAG 2.5.5 · UI-ELEMENT-SPEC §۰). `min-height` است نه
   `height` تا محتوای دوخطی نشکند، و `inline-flex` تا متن وسط بماند.

   استثنا: `.sr-only` — لینکِ «پرش به محتوا» تا فوکوس نگیرد دیده
   نمی‌شود، پس هدفِ لمسی نیست. */

/* ۱. کنشِ ردیف در جدول‌ها — «جزئیات» · «رسید» · «لغو» · «ثبت نظر» */
.zb-act {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    min-height: 44px; min-width: 44px; padding: 0 var(--zb-s3);
    border-radius: var(--zb-r-sm); border: 1px solid var(--zb-line);
    background: var(--zb-surface); color: var(--zb-ink-2);
    font-size: var(--zb-t-xs); font-weight: 700;
    text-decoration: none; white-space: nowrap;
    transition: border-color .16s var(--zb-ease-io), background-color .16s var(--zb-ease-io);
}
.zb-act:hover { border-color: var(--zb-brand); color: var(--zb-brand); }
.zb-act--brand { background: var(--zb-brand); border-color: var(--zb-brand); color: #fff; }
.zb-act--brand:hover { color: #fff; filter: brightness(1.06); }
.zb-act--err  { background: var(--zb-err-bg); border-color: rgba(211,58,58,.28); color: #8f2020; }
.zb-act--err:hover { color: #8f2020; border-color: var(--zb-err); }
.zb-act--gold { background: var(--zb-gold-soft); border-color: rgba(201,166,107,.4); color: var(--zb-gold-deep); }
.zb-act--gold:hover { color: var(--zb-gold-deep); border-color: var(--zb-gold); }

/* ردیفِ کنش‌ها — روی گوشی می‌پیچد به‌جای اینکه جدول را پهن کند */
.zb-acts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--zb-s2); }

/* ۲. آیکنِ تنها در نوار بالا (زنگ اعلان و مانندش) */
.zb-iconbtn {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px;
    border-radius: var(--zb-r-md); border: 0; background: transparent;
    color: inherit; cursor: pointer;
}
.zb-iconbtn:hover { background: var(--zb-line-soft); }

/* ۳. چیپِ فیلتر از ۴۰ به ۴۴ — زیر کف بود */
.zb-filter { min-height: 44px; }

/* ۴. دکمه‌های مشترکِ سیستم — کفِ ۴۴px.
   `.btn-primary` و خانواده‌اش در `design-system.css` فقط padding داشتند،
   پس ارتفاعِ نهایی به اندازهٔ فونت وابسته بود و روی متن‌های ریز به
   ۳۴–۳۸px می‌رسید. این‌جا کف می‌گذاریم تا آن فایل دست‌نخورده بماند. */
.btn-primary, .btn-secondary, .btn-danger, .btn-ghost {
    min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
}

/* ۵. ورودی‌های فرم — کفِ ۴۴px.
   `.form-input` هم فقط padding داشت؛ روی `text-sm` به ~۳۸px می‌رسید. */
.form-input, .form-select, select.form-input { min-height: 44px; }

/* لحنِ «تأیید» برای کنشِ ردیف — رنگِ معنایی، نه هویتی */
.zb-act--ok { background: var(--zb-ok-bg); border-color: rgba(30,158,90,.3); color: #14663b; }
.zb-act--ok:hover { color: #14663b; border-color: var(--zb-ok); }

/* ۶. کفِ ۴۴px برای الگوهای پرتکرارِ باقی‌مانده — R1
   این‌ها را تک‌تک در قالب‌ها عوض نکردم چون الگو‌اند نه مورد:
     · لینک/دکمهٔ درونِ سلولِ جدول (نام مشتری، «مشاهده»، «رسید»)
     · کارت یا ردیفی که خودش لینک است (میانبرها، آمارِ کلیک‌پذیر)
   چون ردیف‌های جدول از قبل ~۴۴px‌اند، این کف ارتفاعِ جدول را عملاً
   عوض نمی‌کند؛ فقط ناحیهٔ لمس را به تمامِ ارتفاعِ سلول می‌رساند. */
.table-responsive td a,
.table-responsive td button,
a.link-card,
a.glass-card,
a.card,
a.stat-hero {
    min-height: 44px;
}
.table-responsive td a,
.table-responsive td button {
    display: inline-flex; align-items: center;
}
a.link-card, a.glass-card, a.card { display: flex; align-items: center; }

/* ۷. پاک‌سازیِ باقی‌مانده — کنترل‌هایی که با کلاس‌های ابزاری ساخته شده‌اند
   و کلاسِ کامپوننتی ندارند. این یک **موقت** است، نه الگو:

     کدِ تازه باید `.zb-act` یا `.zb-touch` بگیرد.

   دلیلِ وجودش: این شکل‌ها در ده‌ها قالب پخش‌اند و عوض کردنِ تک‌تکشان
   ریسکِ تغییرِ چیدمان دارد بدون اینکه چیزی به کاربر بدهد. کف گذاشتن
   روی خودِ شکل، همان نتیجه را با ریسکِ صفر می‌دهد.

   محدود به پوستهٔ پنل است تا لینک‌های متنیِ صفحات عمومی دست‌نخورده
   بمانند (لینکِ درونِ جمله طبق WCAG 2.5.8 از هدفِ لمسی مستثناست). */
body:has(.dashboard-shell) a[class*="px-3"][class*="py-1.5"],
body:has(.dashboard-shell) button[class*="px-3"][class*="py-1.5"],
body:has(.dashboard-shell) a[class*="px-4"][class*="py-2"],
body:has(.dashboard-shell) button[class*="px-4"][class*="py-2"],
body:has(.dashboard-shell) a[class*="inline-flex"][class*="items-center"],
body:has(.dashboard-shell) button[class*="inline-flex"][class*="items-center"],
body:has(.dashboard-shell) a[class*="block"][class*="text-center"],
body:has(.dashboard-shell) button[class*="w-9"][class*="h-9"],
body:has(.dashboard-shell) a[class*="text-xs"][class*="font-semibold"] {
    min-height: 44px;
}
body:has(.dashboard-shell) button[class*="w-9"][class*="h-9"] { min-width: 44px; }

/* ═══ [K6] انتخابگرِ خدمت در مسیر رزرو — ظاهرِ zh-svc، روی توکن‌های --c-* ═══
   این صفحه بعدازورود است (پوستهٔ --c-*) ولی باید هم‌خانوادهٔ منوی zh-svc
   دیده شود؛ برای همین کامپوننت مستقل در components.css نشسته که روی هر دو
   پوسته کار می‌کند. رفتارِ چندانتخابی (data-service-*, picked[]) دست‌نخورده. */
.zb-svcpick {
    display: flex; align-items: center; gap: var(--zb-s4);
    padding: var(--zb-s3) var(--zb-s4); background: var(--zb-surface);
    border: 1px solid var(--zb-line); border-radius: var(--zb-r-md);
    cursor: pointer; text-decoration: none;
    transition: border-color .2s var(--zb-ease-io), box-shadow .2s var(--zb-ease-io);
}
.zb-svcpick:hover { border-color: var(--c-primary); box-shadow: var(--zb-shadow); }
.zb-svcpick.ring-2 {
    border-color: var(--c-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-primary) 16%, transparent);
}
.zb-svcpick-thumb {
    width: 64px; height: 64px; border-radius: var(--zb-r-md);
    object-fit: cover; flex-shrink: 0;
}
.zb-svcpick-thumb--empty {
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--c-primary) 7%, transparent);
    color: color-mix(in srgb, var(--c-primary) 30%, transparent);
}
/* نقطه‌چینِ رهنما — مثل منوی رستوران: نام را به قیمت وصل می‌کند */
.zb-svcpick-leader {
    flex: 1; min-width: 24px; align-self: flex-end; margin: 0 var(--zb-s2) 5px;
    border-bottom: 2px dotted var(--zb-line);
}
.zb-svcpick-price { font-weight: 800; color: var(--c-primary);
    font-variant-numeric: tabular-nums; white-space: nowrap; }
.zb-svcpick-duration { font-size: var(--zb-t-xs); color: var(--zb-ink-3);
    white-space: nowrap; }
@media (prefers-reduced-motion: reduce) {
    .zb-svcpick, .zb-svcpick * { transition: none !important; }
}
