/* =============================================================================
   هیرا — استایل‌های دست‌نویس (خارج از پروتوتایپ)
   -----------------------------------------------------------------------------
   این فایل پس از vira.css بارگذاری می‌شود. آن فایل خروجی
   scripts/extract_assets.py است و با هر اجرا کاملاً بازنویسی می‌شود، پس هیچ
   استایل دستی نباید آنجا نوشته شود — همه اینجا می‌آیند.
   ============================================================================= */

/* --------------------------------------------- کشیدن و رهاکردن بورد کانبان */

.kanban-column.drag-over {
  outline: 2px dashed var(--primary-600);
  outline-offset: -4px;
  background: var(--primary-50);
}

.deal-card.dragging {
  opacity: 0.45;
  transform: rotate(1.5deg);
}

.deal-card[draggable="true"] {
  cursor: grab;
}

.deal-card[draggable="true"]:active {
  cursor: grabbing;
}

/* ------------------------------------------------ لغزندهٔ شبیه‌ساز پیش‌بینی */

.forecast-slider {
  width: 100%;
  accent-color: var(--primary-600);
  cursor: pointer;
}

/* ------------------------------------------------ چیدمان مرکز تعاملات */

/* ستون گفتگو و ستون پرونده با هم با HTMX عوض می‌شوند، ولی باید فرزند
   مستقیم فلکسِ .inbox-layout بمانند — وگرنه عرض ستون‌ها به‌هم می‌ریزد. */
.inbox-panes {
  display: contents;
}

.conversation-item {
  cursor: pointer;
}

/* گفتگوی دارای پیام خوانده‌نشده — پروتوتایپ کلاس جداگانه‌ای نداشت، پس
   به‌جای افزودن بج سوم به ردیف، خودِ ردیف پررنگ‌تر می‌شود. */
.conversation-item.unread .conv-customer-name { font-weight: 800; }
.conversation-item.unread .conv-last-msg { color: var(--text-main); font-weight: 600; }

.chat-composer-box .composer-input-row {
  margin: 0;
}

/* ------------------------------------------- سربرگ کارت‌های بخش‌بندی‌شده */

/* در پروتوتایپ این دو کلاس استفاده شده بود ولی تعریف CSS نداشت؛ اینجا
   هم‌سبک با .section-card-title تعریف می‌شوند تا کارت‌های تحلیلی، پرونده
   ۳۶۰ درجه و سود و زیان سربرگ یکدستی داشته باشند. */
.command-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.command-section-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-main);
}

/* ------------------------------------------------ ویجت گفتگوی وب‌سایت */

/* صفحهٔ مستقل ویجت داخل iframe سایت مشتری اجرا می‌شود، پس نه سایدبار
   دارد و نه سربرگ؛ فقط یک ستون تمام‌قد. */
.widget-shell {
  display: flex;
  flex-direction: column;
  height: 100vh;
  max-width: 420px;
  margin: 0 auto;
  background: var(--bg-card);
  border-left: 1px solid var(--border-base);
  border-right: 1px solid var(--border-base);
}

.widget-header {
  padding: 14px 16px;
  color: #ffffff;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.widget-header-title { font-size: 14px; font-weight: 800; }
.widget-header-subtitle { font-size: 11.5px; opacity: 0.85; }

.widget-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--bg-app);
}

.widget-thread {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.widget-thread .message-bubble-wrapper { max-width: 88%; }
.widget-thread .message-bubble { font-size: 13px; }
.widget-thread .message-bubble-wrapper.agent .message-bubble { color: #ffffff; }

.message-meta {
  font-size: 10.5px;
  color: var(--text-muted);
  margin-top: 4px;
  padding: 0 4px;
}

.widget-footer {
  padding: 12px;
  border-top: 1px solid var(--border-base);
  background: var(--bg-card);
  flex-shrink: 0;
}

.widget-composer { display: flex; gap: 8px; }
.widget-composer .form-control { flex: 1; }
/* دکمهٔ ارسال سمت راست (ابتدای جهت RTL). با ``order`` انجام می‌شود نه با
   جابه‌جایی در HTML، تا ترتیب Tab همان جعبهٔ پیام بماند. */
.widget-composer button { order: -1; }

/* ============================================================================
   کلاس‌هایی که در قالب‌ها استفاده شده بودند ولی هرگز تعریف نشدند
   ----------------------------------------------------------------------------
   این‌ها در پروتوتایپ وجود نداشتند و در فازهای بعدی ساخته شدند، ولی استایلشان
   نوشته نشده بود؛ پس بی‌صدا با اندازه و وزن پیش‌فرض متن رندر می‌شدند.
   ========================================================================== */

/* عدد بزرگ کارت شاخص. هم‌سنگ .kpi-number پروتوتایپ، ولی در چیدمانی که
   ردیف .kpi-value-row ندارد و مقدار مستقیم زیر عنوان می‌آید. */
.kpi-card-value {
  font-size: 22px;
  font-weight: 800;
  color: var(--text-main);
  letter-spacing: -0.02em;
  line-height: 1.35;
}

/* حالت هشدار کارت شاخص — وقتی عددش نیازمند توجه است (کسری انبار،
   فیش منتظر تایید و مانند آن). */
.kpi-card.warning {
  border-color: var(--warning-500);
  background: var(--warning-50);
}

.kpi-card.featured {
  border-color: var(--primary-600);
  box-shadow: 0 0 20px rgba(79, 70, 229, 0.15);
}

/* کارت پیام/هشدار سراسری: پیام‌های flash، خطاهای فرم، بنر وضعیت.
   پایه‌اش خنثی است و رنگش را از حالت می‌گیرد. */
.ai-insight-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-base);
  border-right: 3px solid var(--border-strong);
  border-radius: 12px;
  padding: 14px 16px;
  color: var(--text-secondary);
  line-height: 1.7;
}

.ai-insight-card.success {
  background: var(--success-50);
  border-color: var(--success-100);
  border-right-color: var(--success-600);
  color: var(--success-600);
}

.ai-insight-card.warning {
  background: var(--warning-50);
  border-color: var(--warning-100);
  border-right-color: var(--warning-600);
  color: var(--warning-600);
}

.ai-insight-card.danger {
  background: var(--danger-50);
  border-color: var(--danger-100);
  border-right-color: var(--danger-600);
  color: var(--danger-600);
}

/* ============================================================================
   لایهٔ ریسپانسیو — بهبودهای «قابل استفاده بودن»، نه فقط «نشکستن»
   ----------------------------------------------------------------------------
   پایهٔ ریسپانسیو در vira.css است (خروجی پروتوتایپ) و سرریز افقی ندارد.
   آنچه اینجا می‌آید سه چیزی است که «می‌شد ولی خوب کار نمی‌کرد»:
   ستون شناسه در جدول‌های پهن، اهداف لمسی ریز، و مرکز تعاملات روی موبایل.
   ========================================================================== */

/* ------------------------------------------- ۱) ستون شناسه در جدول‌های پهن */

/* جدول‌های این سامانه روی صفحهٔ باریک داخل ظرفشان افقی اسکرول می‌شوند و
   نمی‌شکنند — ولی وقتی به ستون‌های راست‌تر می‌رسید، ستون اولِ شناسه
   (نام دسترسی، کد کالا، نام مخاطب) از دید بیرون می‌رود و معلوم نیست
   دارید کدام ردیف را می‌خوانید. اینجا آن ستون می‌چسبد.

   inset-inline-start به‌جای right/left نوشته شده تا در RTL و LTR هر دو
   همان «ستون اول» بچسبد. */
@media (max-width: 1100px) {
  .data-table th:first-child,
  .data-table td:first-child {
    position: sticky;
    inset-inline-start: 0;
    z-index: 2;
    background: var(--bg-card);
  }

  .data-table th:first-child {
    z-index: 3;
    background: var(--bg-subtle);
  }

  /* ردیف‌های سربرگ گروه (مثل «مرکز تعاملات مشتریان» در ماتریس دسترسی‌ها)
     تک‌سلولیِ colspan هستند؛ چسباندنشان بی‌معنی است و زمینه‌شان را خراب
     می‌کند. */
  .data-table td[colspan]:first-child {
    position: static;
    background: transparent;
  }

  /* لبهٔ باریک تا مرز ستون چسبیده از بقیه جدا دیده شود. */
  .data-table th:first-child::after,
  .data-table td:first-child::after {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    width: 1px;
    background: var(--border-base);
  }

  /* رنگ ردیفِ زیر ماوس/فعال نباید از زیر ستون چسبیده رد شود. */
  .data-table tr:hover td:first-child {
    background: var(--bg-hover);
  }
}

/* --------------------------------------------------- ۲) اهداف لمسی */

/* فقط روی دستگاه لمسی اعمال می‌شود تا رابط دسکتاپ باد نکند.
   چک‌باکس ۱۳ پیکسلی ماتریس دسترسی‌ها با انگشت عملاً قابل زدن نیست. */
@media (pointer: coarse) {
  .data-table input[type="checkbox"],
  .modal-body input[type="checkbox"],
  .form-group input[type="checkbox"] {
    width: 22px;
    height: 22px;
    accent-color: var(--primary-600);
  }

  /* خودِ خانهٔ جدول ناحیهٔ لمسی را بزرگ می‌کند، بدون بزرگ‌کردن خود چک‌باکس. */
  .data-table td:has(> input[type="checkbox"]) {
    padding: 16px 18px;
  }

  .icon-btn,
  .btn-primary,
  .btn-secondary,
  .tag-badge[onclick],
  .tag-badge[hx-get],
  .tag-badge[hx-post] {
    min-height: 44px;
  }

  .icon-btn {
    min-width: 44px;
  }

  /* دکمه‌های ریز داخل ردیف جدول: ناحیهٔ لمسی بزرگ‌تر ولی ظاهر هم‌اندازه. */
  .data-table .tag-badge {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding-block: 8px;
  }
}

/* --------------------------------------- ۳) مرکز تعاملات روی موبایل */

/* دکمهٔ بازگشت و میان‌بر پرونده فقط در نمای تک‌ستونی معنی دارند؛ روی
   دسکتاپ ستون فهرست و ستون پرونده هر دو دیده می‌شوند. */
.inbox-back-btn,
.inbox-context-shortcut {
  display: none;
}

/* روی صفحهٔ باریک هر سه ستون زیر هم می‌نشستند و صفحه‌ای نزدیک ۱۹۰۰ پیکسل
   می‌ساختند: برای پاسخ‌دادن باید از ۳۵۰ پیکسل فهرست رد می‌شدید و برای
   دیدن پروندهٔ مشتری ۸۰۰ پیکسل دیگر. هیچ پیام‌رسانی این‌طور کار نمی‌کند.

   حالا هر بار یک ستون: تا وقتی گفتگویی انتخاب نشده فقط فهرست، و پس از
   انتخاب فقط رشتهٔ گفتگو با دکمهٔ بازگشت.

   تشخیص «انتخاب‌شده» از data-selected می‌آید که سرور می‌گذارد (یعنی ?c=
   در نشانی بوده، نه انتخاب خودکارِ نخستین گفتگو). :has لازم است چون
   #inbox-panes بعد از ستون فهرست می‌آید. */
@media (max-width: 720px) {
  .inbox-layout:has(#inbox-panes[data-selected]) .inbox-list-col {
    display: none;
  }

  .inbox-layout:not(:has(#inbox-panes[data-selected])) .inbox-panes {
    display: none;
  }

  /* فهرست وقتی تنهاست باید تمام ارتفاع را بگیرد، نه ۳۵۰ پیکسل. */
  .inbox-layout:not(:has(#inbox-panes[data-selected])) .inbox-list-col {
    height: auto;
    min-height: calc(100dvh - 205px);
    border-bottom: 0;
  }

  /* رشتهٔ گفتگو وقتی تنهاست تمام صفحه را می‌گیرد. */
  .inbox-layout:has(#inbox-panes[data-selected]) .inbox-chat-col {
    min-height: calc(100dvh - 205px);
  }

  .inbox-context-shortcut {
    display: inline-flex;
  }

  .inbox-back-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-inline-start: -6px;
    border-radius: 10px;
    color: var(--text-secondary);
    flex: 0 0 auto;
  }

  .inbox-back-btn:hover {
    background: var(--bg-hover);
    color: var(--text-main);
  }

  /* فلش در RTL باید به سمت راست (بازگشت) اشاره کند. */
  .inbox-back-btn svg {
    transform: scaleX(-1);
  }

  /* پروندهٔ ۳۶۰ درجه روی موبایل زیر گفتگو جا نمی‌شود؛ به‌جای فشرده‌کردنش،
     از سربرگ گفتگو به صفحهٔ کامل مخاطب می‌رویم که خودش ریسپانسیو است. */
  .inbox-context-col {
    display: none;
  }
}

/* ============================================================================
   شکستن سطر — فقط جایی که واقعاً لازم است
   ----------------------------------------------------------------------------
   شمارهٔ فاکتور، کد کالا، مبلغ، تاریخ و برچسب وضعیت «یک واحد معنایی» هستند؛
   دو خطی شدنشان هم بدریخت است و هم خواندنشان را سخت می‌کند
   («#INV-1405-» / «۰۳»). در مقابل، نام کالا یا خلاصهٔ اقلام متن آزادِ بلند
   است و شکستنش طبیعی است.

   قاعدهٔ فراگیر `td { white-space: nowrap }` عمداً گذاشته نشده: با آن،
   جدول انبارداری از ۱۱۸۲ به ۱۲۷۹ پیکسل می‌رسید و روی دسکتاپ هم اسکرول
   افقی می‌گرفت. پس فقط چیزهای اتمی nowrap می‌شوند.
   ========================================================================== */

/* برچسب وضعیت هر جای برنامه — «هشدار کسری انبار ⚠️» نباید نصف شود. */
.tag-badge {
  white-space: nowrap;
}

/* برچسب دکمه‌ها — «ثبت ورود/خروج» در ستون عملیات دو خطی می‌شد. */
.btn-primary,
.btn-secondary,
.icon-btn {
  white-space: nowrap;
}

/* شناسه‌های لاتین: شمارهٔ فاکتور و پیش‌فاکتور، کد کالا (SKU)، شبا، موبایل.
   کلاس ltr از قبل روی همین سلول‌ها هست. */
.ltr {
  white-space: nowrap;
}

/* عدد کارت شاخص هرگز نباید بشکند: «۲۵۲ میلیون / تومان» در دو خط، هم
   بدریخت است و هم لحظه‌ای طول می‌کشد تا بفهمید یک عدد است نه دو تا.
   جا هست — عدد به‌خاطر رقابت با نشان کنارش می‌شکست، نه کمبود عرض. */
.kpi-number,
.kpi-card-value {
  white-space: nowrap;
}

/* اگر جا کم آمد، نشان کوچک شود نه عدد. */
.kpi-value-row .kpi-badge {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ستون‌های عددی و کوتاه که در قالب علامت‌گذاری شده‌اند.
   فاصلهٔ کناری‌شان کمتر است: مقدارِ اتمی به هوای دو طرف نیاز ندارد و
   همین چند ده پیکسل باعث می‌شود جدول‌های پرستون بدون شکستن متن، در
   عرض ظرفشان جا شوند. */
.data-table td.num,
.data-table th.num {
  white-space: nowrap;
  padding-inline: 11px;
}

/* استثنا: متن آزادِ بلند باید بشکند، وگرنه جدول بی‌جهت پهن می‌شود. */
.data-table td.wrap {
  white-space: normal;
}

/* ============================================================================
   لینک‌ها بدون خط زیرین
   ----------------------------------------------------------------------------
   در پروتوتایپ تقریباً همهٔ لینک‌ها <button onclick> بودند، پس خط زیرین
   دیده نمی‌شد. در نسخهٔ جنگو به <a href> واقعی تبدیل شدند و خط زیرینِ
   پیش‌فرض مرورگر ظاهر شد. زبان طراحی این سامانه بدون خط زیرین است و
   لینک‌ها با رنگ و حالت hover شناخته می‌شوند.
   ========================================================================== */

a,
a:hover,
a:focus,
a:visited {
  text-decoration: none;
}

/* متن آزادی که می‌تواند بلند شود ولی باید تک‌خطی بماند: یک خط با «…» و
   متن کامل در tooltip. کوتاه‌سازی در جدول به max-width نیاز دارد، وگرنه
   سلول به‌جای بریدن متن، خودش پهن می‌شود. */
.truncate,
.truncate-sm {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.data-table td.truncate,
.data-table td .truncate {
  max-width: 220px;
}

.data-table td.truncate-sm,
.data-table td .truncate-sm {
  max-width: 150px;
}

/* ============================================================================
   تناسب دکمه‌ها — هم‌ارتفاع بودن کنترل‌های یک ردیف
   ----------------------------------------------------------------------------
   دکمه‌ها و قرص‌های کنار هم، padding و محتوای متفاوت داشتند و ارتفاعشان
   نابرابر می‌شد (قرص واگذاری ۳۰ پیکسل در برابر ۳۲ پیکسلِ همسایه‌هایش).
   با باریک شدن صفحه هم متنشان چند خطی می‌شد و ردیف را به هم می‌ریخت.

   راه‌حل «یک ارتفاع ثابت برای همهٔ دکمه‌های برنامه» درست نیست: دکمهٔ داخل
   ردیف جدول باید کوچک‌تر از دکمهٔ سربرگ صفحه باشد. پس به‌جای ارتفاع
   سراسری، هر ردیفِ کنترل با align-items: stretch بچه‌هایش را هم‌قد
   می‌کند — ارتفاع از خودِ ردیف می‌آید، نه از یک عدد ثابت.
   ========================================================================== */

.page-actions-area,
.chat-header-actions,
.modal-footer,
.table-filter-bar > div,
.inbox-list-header .inbox-filters-scroll {
  align-items: stretch;
}

/* بچه‌های کشیده‌شده باید محتوایشان را وسط نگه دارند.

   :where() ویژگی (specificity) این قاعده را صفر می‌کند، پس یک پایهٔ
   بی‌سروصداست: هر کلاسی که display خودش را تعیین کند — مثل
   .inbox-context-shortcut که روی دسکتاپ display:none است — بر آن غلبه
   می‌کند. بدون :where()، این قاعده دکمه‌های عمداً پنهان را آشکار می‌کرد. */
:where(.page-actions-area, .chat-header-actions, .modal-footer)
  > :where(button, a, span, select) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* هیچ کنترلی نباید چند خطی شود؛ متن چندخطی ردیف را بلند و نامتناسب می‌کند.
   (btn-primary / btn-secondary / icon-btn پیش‌تر nowrap شده‌اند.) */
.ai-handoff-pill,
.ai-copilot-btn,
.workspace-btn,
.sub-tab-btn,
.inbox-filter-pill {
  white-space: nowrap;
}

/* در ردیف فلکس، دکمه نباید آن‌قدر فشرده شود که متنش بشکند. */
.page-actions-area > *,
.chat-header-actions > *,
.modal-footer > * {
  flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
   وقتی ردیف می‌شکند، stretch دیگر کافی نیست.

   align-items: stretch فقط بچه‌های *یک خط* را هم‌قد می‌کند. روی صفحهٔ باریک
   که ردیف wrap می‌شود، هر کنترل خطِ خودش را می‌گیرد و به ارتفاع طبیعی‌اش
   برمی‌گردد: در سربرگ تحلیل‌ها، select چهل‌ودو پیکسل، لینک سی‌ونه و دکمه
   سی‌وهشت — همان بی‌تناسبی‌ای که در حالت تک‌خطی حل شده بود.

   پس ارتفاع طبیعیِ خودِ کنترل‌ها یکسان می‌شود، نه فقط کششان. عدد به ردیف
   وابسته است (سربرگ صفحه بلندتر از سربرگ گفتگو)، و چون box-sizing سراسری
   border-box است، padding متفاوتِ هر کلاس در همین ارتفاع جا می‌شود و
   ظاهرشان دست‌نخورده می‌ماند.
   --------------------------------------------------------------------------- */

.page-actions-area { --row-control-h: 38px; }
.modal-footer { --row-control-h: 38px; }
.chat-header-actions { --row-control-h: 32px; }
.table-filter-bar > div { --row-control-h: 36px; }

.page-actions-area > :is(button, a, select, label, span.tag-badge),
.modal-footer > :is(button, a, select, label),
.chat-header-actions > :is(button, a, select, label),
.table-filter-bar > div > :is(button, a, select, label) {
  height: var(--row-control-h);
}

/* ---------------------------------------------------------------------------
   ردیف کنترل‌ها باید بشکند، نه سرریز کند.

   دکمه‌ها flex-shrink: 0 دارند تا متنشان نشکند، ولی خودِ *ظرفِ* آن‌ها
   min-width: 0 دارد و کوچک می‌شود. نتیجه‌اش این بود که دکمه‌ها از ظرف
   بیرون می‌زدند: در سربرگ گفتگو، «تبدیل به تیکت» و «صدور فاکتور» زیر ستون
   پروندهٔ مشتری می‌رفتند و نه دیده می‌شدند نه کلیک‌پذیر بودند (سرریز به
   سمت چپ، چون چیدمان راست‌به‌چپ است). سرریز چیزی را جابه‌جا نمی‌کند، پس
   مرورگر هم هشداری نمی‌دهد؛ فقط کنترل ناپدید می‌شود.

   با flex-wrap هر دو سطح، سرریز اصلاً ممکن نمی‌شود: اول کل ردیف عملیات به
   سطر بعدی می‌رود (چون تصمیمِ wrap با اندازهٔ طبیعی گرفته می‌شود، پیش از
   فشرده‌سازی)، و اگر همان‌جا هم جا نشد، خودِ دکمه‌ها می‌شکنند. ارتفاع‌ها
   با --row-control-h برابر می‌مانند، پس شکستن ردیف بی‌تناسبی نمی‌سازد. */

.chat-thread-header,
.chat-header-actions,
.page-actions-area,
.modal-footer,
.table-filter-bar > div {
  flex-wrap: wrap;
}

/* ============================================================================
   دکمهٔ دستیار هوشمند در سربرگ
   ----------------------------------------------------------------------------
   دو حالت درست دارد و بس: مستطیل تک‌خطی (آیکون + برچسب) روی صفحهٔ پهن، و
   مربع فقط-آیکون روی صفحهٔ باریک. حالت میانیِ «فشرده‌شده و دوخطی» که در
   عمل پیش می‌آمد اصلاً نباید ظاهر شود — با nowrap و flex-shrink: 0 دیگر
   نمی‌تواند؛ نوار جست‌وجو فشردگی را جذب می‌کند.
   ========================================================================== */

.ai-copilot-btn {
  flex-shrink: 0;
  justify-content: center;
}

.ai-copilot-btn > svg {
  flex-shrink: 0;
}

/* در حالت مربعی، آیکون دقیقاً وسط بماند. */
.ai-copilot-btn:not(:has(> span:not([style*="monospace"]))) {
  padding-inline: 0;
}

/* ============================================================================
   صفحهٔ ثبت‌نام
   ----------------------------------------------------------------------------
   دو حالت ثبت‌نام (ساخت سازمان تازه / پیوستن به سازمان موجود) باید در نگاه
   اول از هم جدا باشند، پس رادیوها به شکل دو کارت انتخاب‌شدنی درمی‌آیند.
   ========================================================================== */

.form-error {
  font-size: 11.5px;
  color: var(--danger-600);
  margin-top: 5px;
  line-height: 1.8;
}

.signup-mode-choices {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}

@media (min-width: 420px) {
  .signup-mode-choices { grid-template-columns: 1fr 1fr; }
}

.signup-mode-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 13px;
  border: 1px solid var(--border-base);
  border-radius: 10px;
  background: var(--bg-subtle);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  /* متن دو گزینه هم‌طول نیست؛ بدون این، دو کارت نابرابر می‌شدند. */
  min-height: 44px;
}

.signup-mode-option:hover { border-color: var(--border-strong); }

.signup-mode-option:has(input:checked) {
  border-color: var(--primary-500);
  background: var(--primary-50);
  color: var(--primary-700);
}

/* فیلدهای وابسته به حالت — بدون جاوااسکریپت.

   پوستهٔ ورود/ثبت‌نام (base_bare.html) عمداً Alpine را بار نمی‌کند، و
   صفحهٔ احراز هویت نباید به اجرای اسکریپت وابسته باشد. پس خودِ رادیوی
   انتخاب‌شده با :has تصمیم می‌گیرد کدام فیلد دیده شود. اعتبارسنجی هم
   سمت سرور است، پس پنهان‌بودن یک فیلد راهِ دور زدن قواعد نیست. */
.signup-only-new,
.signup-only-join { display: none; }

form:has(input[name="mode"][value="new"]:checked) .signup-only-new,
form:has(input[name="mode"][value="join"]:checked) .signup-only-join {
  display: block;
}

/* ============================================================================
   شناسه‌های قابل انتخاب
   ----------------------------------------------------------------------------
   پوستهٔ اپ روی body سراسری `user-select: none` دارد (از پروتوتایپ، تا حس
   نرم‌افزار دسکتاپ بدهد نه صفحهٔ وب). ولی چند رشته در این سامانه **داده**‌اند
   نه رابط: شناسه سازمان، شماره فاکتور، شناسه صیادی، نشانی وب‌هوک. کاربر
   باید بتواند انتخاب و کپی‌شان کند — و بدون این، حتی راه پشتیبانِ کپی
   (`document.execCommand`) هم کار نمی‌کند، چون چیزی برای انتخاب نمی‌ماند.
   ========================================================================== */

.selectable {
  user-select: text;
  -webkit-user-select: text;
}

/* ============================================================================
   پنل ادمین هیرا
   ----------------------------------------------------------------------------
   چند ردیف «برچسب ← مقدار» که در پنل فروشنده زیاد تکرار می‌شوند. پروتوتایپ
   چنین الگویی نداشت چون اصلاً پنل فروشنده نداشت، پس اینجا تعریف می‌شود نه
   در vira.css که تولیدشده است.
   ========================================================================== */

.stat-rows {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.stat-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 2px;
  font-size: 12.5px;
  border-bottom: 1px solid var(--border-base);
}

.stat-row:last-child {
  border-bottom: 0;
}

.stat-row .stat-label {
  color: var(--text-secondary);
}

.stat-row .stat-value {
  font-weight: 700;
  color: var(--text-main);
  white-space: nowrap;
}

/* نوار مصرف نسبت به سقف ماهانه. عرض از سرور می‌آید، نه از جاوااسکریپت. */
.quota-bar {
  height: 6px;
  border-radius: 99px;
  background: var(--bg-subtle);
  overflow: hidden;
  min-width: 90px;
}

.quota-bar > span {
  display: block;
  height: 100%;
  border-radius: 99px;
  background: var(--primary-600);
}

.quota-bar.over > span {
  background: var(--danger-600);
}

/* ============================================================================
   وضعیت زندهٔ سرویس‌ها در پای منوی کناری
   ----------------------------------------------------------------------------
   پروتوتایپ اینجا رشتهٔ ثابتِ «کاملاً پایدار (۹۹.۹٪)» داشت که حتی وقتی
   پایگاه داده هم پایین بود همان را می‌گفت. حالا متن از بررسی واقعی می‌آید،
   پس رنگش هم باید فرق کند — وگرنه هشدار در میان همان خاکستریِ همیشگی گم
   می‌شود.
   ========================================================================== */

.system-status-indicator.ok .status-dot {
  background: var(--success-600);
}

.system-status-indicator.warn {
  color: var(--warning-600);
}

.system-status-indicator.warn .status-dot {
  background: var(--warning-600);
}

.system-status-indicator.down {
  color: var(--danger-600);
  background: var(--danger-50);
}

.system-status-indicator.down .status-dot {
  background: var(--danger-600);
}

/* ============================================================================
   مودالِ بلندتر از پنجره باید اسکرول شود، نه اینکه بریده شود
   ----------------------------------------------------------------------------
   `.modal-box` یک فلکس ستونی با `max-height: 88vh` و `overflow: hidden` است و
   `.modal-body` هم `overflow-y: auto` دارد — روی کاغذ درست. ولی تقریباً همهٔ
   مودال‌های این پروژه محتوایشان را در یک `<form>` می‌پیچند تا `{% csrf_token %}`
   و دکمهٔ ارسال در یک فرم باشند. آن `<form>` تنها فرزندِ فلکسِ باکس است و
   خودش `display: block` است، پس:

     .modal-box (flex, max-height, overflow:hidden)
       └─ form (block, بدون محدودیت ارتفاع)   ← زنجیره اینجا پاره می‌شود
            ├─ .modal-header
            ├─ .modal-body (overflow-y: auto ولی هرگز فشرده نمی‌شود)
            └─ .modal-footer

   نتیجه: فرم به ارتفاع طبیعی‌اش رشد می‌کند، باکس مازاد را می‌بُرد، و چون
   `.modal-body` اصلاً کوتاه‌تر از محتوایش نشده هیچ‌چیز برای اسکرول ندارد.
   روی پنجرهٔ کوتاه، دکمهٔ «ذخیره» از دسترس خارج می‌شد — یعنی فرم غیرقابل
   ارسال بود.

   اندازه‌گیری روی مودال «وضعیت اشتراک» با پنجرهٔ ۵۲۰ پیکسلی: باکس ۴۵۶، فرم
   ۶۲۷ — ۱۷۱ پیکسل بریده و دسترسی‌ناپذیر.

   راه‌حل عمداً به‌جای قالب‌ها در CSS است: هر مودال تازه‌ای هم که فرم داشته
   باشد خودبه‌خود درست کار می‌کند و کسی لازم نیست یادش بماند.
   ========================================================================== */

.modal-box > form {
  display: flex;
  flex-direction: column;
  /* بدون این، فلکس‌آیتم زیر ارتفاع محتوایش کوچک نمی‌شود. */
  min-height: 0;
  max-height: 100%;
}

.modal-box .modal-body {
  /* بدنه همان چیزی است که باید جا بدهد و اسکرول شود؛ سربرگ و پاورقی نه. */
  flex: 1 1 auto;
  min-height: 0;
}

.modal-box .modal-header,
.modal-box .modal-footer {
  flex: 0 0 auto;
}

/* ============================================================================
   پوستهٔ پنل ادمین هیرا
   ----------------------------------------------------------------------------
   عمداً از پوستهٔ پنل مشتری جداست. آن یکی گزینشگر فضای کاری، جست‌وجوی
   سراسری و کشوی دستیار دارد — چیزهایی که برای کارمند هیرا نه معنا دارند و
   نه باید داشته باشند (او عضو هیچ سازمانی نیست). ظاهر هم عمداً فرق دارد تا
   کسی یک لحظه هم شک نکند در کدام نقش نشسته است.
   ========================================================================== */

.platform-shell {
  display: flex;
  height: 100vh;
  overflow: hidden;
  background: var(--bg-app);
}

.platform-sidebar {
  width: 248px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 20px 16px;
  background: var(--bg-surface);
  border-inline-start: 1px solid var(--border-base);
  /* نوار رنگی، تنها نشانهٔ همیشه‌درصحنه‌ای که «اینجا سمت فروشنده است». */
  box-shadow: inset 4px 0 0 0 var(--ai-600);
}

.platform-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.platform-brand-mark {
  width: 38px;
  height: 38px;
  border-radius: 11px;
  background: var(--ai-600);
  color: #fff;
  font-weight: 800;
  font-size: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.platform-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.5;
  min-width: 0;
}

.platform-brand-text strong { font-size: 14px; color: var(--text-main); }
.platform-brand-text span { font-size: 11px; color: var(--text-muted); }

.platform-nav {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.platform-nav-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 13px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  transition: background 0.15s, color 0.15s;
}

.platform-nav-item:hover {
  background: var(--bg-hover);
  color: var(--text-main);
}

.platform-nav-item.active {
  background: var(--ai-50);
  color: var(--ai-600);
  font-weight: 800;
}

.platform-nav-count {
  font-size: 11px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 99px;
  background: var(--bg-subtle);
  color: var(--text-muted);
}

.platform-nav-item.active .platform-nav-count {
  background: var(--ai-600);
  color: #fff;
}

.platform-sidebar-foot {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--border-base);
}

.platform-user {
  display: flex;
  flex-direction: column;
  line-height: 1.6;
}

.platform-user-name { font-size: 12.5px; font-weight: 700; color: var(--text-main); }
.platform-user-role { font-size: 11px; color: var(--ai-600); font-weight: 700; }

.platform-main {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  padding: 24px 28px 48px;
}

/* روی نمایشگر باریک، منو بالای صفحه می‌نشیند تا محتوا له نشود. */
@media (max-width: 900px) {
  .platform-shell { flex-direction: column; height: auto; min-height: 100vh; }
  .platform-sidebar {
    width: auto;
    box-shadow: inset 0 4px 0 0 var(--ai-600);
    border-inline-start: 0;
    border-bottom: 1px solid var(--border-base);
  }
  .platform-nav { flex-direction: row; flex-wrap: wrap; overflow: visible; }
  .platform-main { padding: 18px 16px 40px; }
}

/* --------------------------------------------------- صفحهٔ ورود ادمین هیرا */

.platform-login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.platform-login-card {
  width: 100%;
  max-width: 420px;
  background: var(--bg-card);
  border: 1px solid var(--border-strong);
  border-top: 4px solid var(--ai-600);
  border-radius: 16px;
  padding: 30px 28px;
  box-shadow: var(--shadow-xl);
}

/* ------------------------------------------------------------ کارت پلن‌ها */

.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(272px, 1fr));
  gap: 16px;
}

.plan-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  background: var(--bg-card);
  border: 1px solid var(--border-base);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}

.plan-card.featured {
  border-color: var(--ai-600);
  box-shadow: 0 0 0 1px var(--ai-600), var(--shadow-sm);
}

/* پلن بایگانی هنوز مشتری دارد، پس پنهان نمی‌شود — فقط عقب می‌نشیند. */
.plan-card.archived {
  opacity: 0.62;
  background: var(--bg-subtle);
}

.plan-price {
  font-size: 21px;
  font-weight: 800;
  color: var(--text-main);
  letter-spacing: -0.3px;
}

/* ---------------------------------------------------- نمودار و نوار بودجه */

.usage-chart svg {
  width: 100%;
  height: 160px;
  display: block;
}

.usage-chart-axis {
  display: flex;
  gap: 3px;
  font-size: 9.5px;
  color: var(--text-muted);
  margin-top: 4px;
}

.usage-chart-axis span {
  text-align: center;
  flex-shrink: 0;
}

.usage-chart-peak {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 8px;
}

.usage-chart-empty {
  padding: 46px 16px;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-muted);
}

.budget-bar {
  height: 12px;
  border-radius: 99px;
  background: var(--bg-subtle);
  overflow: hidden;
}

.budget-bar > span {
  display: block;
  height: 100%;
  border-radius: 99px;
  background: var(--success-600);
}

.budget-bar.warn > span { background: var(--warning-600); }
.budget-bar.over > span { background: var(--danger-600); }

/* ------------------------------------------------------------ کارت پروژه */

.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
  gap: 16px;
}

.project-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px;
  background: var(--bg-card);
  border: 1px solid var(--border-base);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}

/* پروژهٔ فعال باید در یک نگاه از بقیه جدا باشد — کار در پروژهٔ اشتباه،
   خطایی است که تا مدت‌ها معلوم نمی‌شود. */
.project-card.active {
  border-color: var(--primary-600);
  box-shadow: 0 0 0 1px var(--primary-600), var(--shadow-sm);
}

/* ==========================================================================
   ویجت: تفاوت ربات و آدم
   --------------------------------------------------------------------------
   کسی که فکر می‌کند با ربات حرف می‌زند، جور دیگری می‌نویسد تا کسی که
   می‌داند پشت خط آدم نشسته است. پس این تفاوت باید در یک نگاه دیده شود،
   نه با خواندن ریزنوشتهٔ زیر حباب.
   ========================================================================== */

.widget-thread .message-bubble.from-human {
  border-inline-start: 3px solid var(--success-600);
}

.widget-system-note {
  align-self: center;
  max-width: 90%;
  margin: 6px 0;
  padding: 9px 13px;
  border-radius: 10px;
  background: var(--bg-subtle);
  border: 1px dashed var(--border-strong);
  font-size: 11.5px;
  line-height: 1.9;
  color: var(--text-secondary);
  text-align: center;
}

.widget-support-state {
  align-self: center;
  margin: 8px 0 2px;
  font-size: 11.5px;
  color: var(--success-600);
  font-weight: 700;
}

.widget-support-call {
  margin: 10px 0 2px;
  text-align: center;
}

.widget-support-call button {
  padding: 8px 14px;
  border-radius: 99px;
  border: 1px solid var(--border-strong);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: 11.5px;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.widget-support-call button:hover {
  background: var(--success-50);
  border-color: var(--success-600);
  color: var(--success-600);
}

/* ==========================================================================
   صندوق پیام: گروه‌بندی پروژه و وضعیت زندهٔ گفتگو
   ========================================================================== */

.mailbox-alert {
  margin-top: 8px;
  padding: 7px 11px;
  border-radius: 8px;
  background: var(--warning-50);
  color: var(--warning-600);
  font-size: 11.5px;
  font-weight: 700;
}

.mailbox-group-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 14px;
  background: var(--bg-subtle);
  border-block: 1px solid var(--border-base);
  font-size: 11.5px;
}

.mailbox-group-name {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 800;
  color: var(--text-main);
  min-width: 0;
}

.mailbox-group-current {
  font-size: 9.5px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 99px;
  background: var(--primary-600);
  color: #fff;
}

.mailbox-group-count { color: var(--text-muted); white-space: nowrap; }

.mailbox-group-empty {
  padding: 14px;
  font-size: 11.5px;
  color: var(--text-muted);
  text-align: center;
}

.conv-vitals {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-base);
}

.conv-vitals-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
  font-size: 12.5px;
  font-weight: 800;
  color: var(--text-main);
}

.conv-vitals-controls {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.conv-vitals-controls .form-label { margin-top: 6px; }

/* ============================================================================
   بخش «چت‌بات‌های من» — فهرست، ویرایشگر و عناصر تازهٔ خودِ ویجت
   ========================================================================= */

.chatbot-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--border-base);
  border-radius: 14px;
  background: var(--bg-card);
  text-decoration: none;
  color: inherit;
  transition: border-color .15s, transform .15s;
}

.chatbot-card:hover {
  border-color: var(--primary-600);
  transform: translateY(-2px);
}

.chatbot-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.chatbot-swatch {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chatbot-card-name {
  font-size: 13.5px;
  font-weight: 800;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chatbot-card-title {
  font-size: 11.5px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chatbot-card-head .tag-badge { margin-inline-start: auto; }

.chatbot-card-stats {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border-radius: 10px;
}

.chatbot-stat-number {
  font-size: 16px;
  font-weight: 800;
  color: var(--text-main);
  margin-inline-end: 4px;
}

.chatbot-stat-label {
  font-size: 11px;
  color: var(--text-muted);
}

.chatbot-card-foot {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.8;
}

/* ------------------------------------------------------------- ویرایشگر */

.chatbot-editor {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

.chatbot-preview-col {
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* ستون پیش‌نمایش هنگام پیمایش فرمِ بلند در جای خودش می‌ماند. */
  position: sticky;
  top: 16px;
}

@media (max-width: 1080px) {
  .chatbot-editor { grid-template-columns: minmax(0, 1fr); }
  .chatbot-preview-col { position: static; }
}

.chatbot-section-title {
  font-size: 12px;
  font-weight: 800;
  color: var(--text-muted);
  letter-spacing: .2px;
  margin: 18px 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border-base);
}

.chatbot-section-title:first-of-type { margin-top: 6px; }

.chatbot-field-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

@media (max-width: 520px) {
  .chatbot-field-pair { grid-template-columns: 1fr; }
}

.chatbot-toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  background: var(--bg-subtle);
  border-radius: 10px;
  margin-bottom: 12px;
}

.chatbot-toggle-row.plain {
  padding: 6px 0;
  background: none;
  margin-bottom: 4px;
}

.chatbot-toggle-row label {
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}

.chatbot-toggle-row.plain label { font-weight: 600; }

/* ------------------------------------------------- عناصر تازهٔ خود ویجت */

.widget-quick-replies {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0;
}

.widget-quick-reply {
  padding: 6px 11px;
  font-size: 11.5px;
  font-weight: 600;
  font-family: inherit;
  color: var(--primary-700);
  background: var(--primary-50);
  border: 1px solid var(--primary-600);
  border-radius: 999px;
  cursor: pointer;
}

.widget-quick-reply:hover {
  color: #fff;
  background: var(--primary-600);
}

.widget-note {
  font-size: 10.5px;
  color: var(--text-muted);
  margin-top: 7px;
  text-align: center;
  line-height: 1.8;
}

.widget-branding {
  font-size: 10px;
  color: var(--text-muted);
  text-align: center;
  margin-top: 6px;
  opacity: .75;
}

/* ============================================================================
   بخش «راه‌های انتشار»
   ========================================================================= */

.publish-bot-picker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
}

.publish-bot-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  margin-inline-end: 4px;
}

.publish-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
}

.publish-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  border: 1px solid var(--border-base);
  border-radius: 14px;
  background: var(--bg-card);
}

/* کانال نساخته عمداً کم‌رنگ است و هیچ دکمه‌ای ندارد؛ کارتی که مثل
   کارت آماده به‌نظر برسد، وعده‌ای می‌دهد که پشتش چیزی نیست. */
.publish-card.planned {
  background: var(--bg-subtle);
  border-style: dashed;
}

.publish-card.planned .publish-icon { opacity: .55; }

.publish-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.publish-icon {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.publish-card-title {
  font-size: 13.5px;
  font-weight: 800;
  color: var(--text-main);
}

.publish-card-note {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.7;
}

.publish-card-desc {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.9;
  margin: 0;
}

.publish-card textarea,
.publish-card input { width: 100%; }

.publish-action { align-self: flex-start; }

.publish-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* --------------------------------------------- کانال‌های پیام‌رسان */

.publish-steps {
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.9;
}

.publish-steps-name {
  font-weight: 800;
  color: var(--text-main);
  margin-top: 8px;
}

.publish-steps ol {
  margin: 4px 0 0;
  padding-inline-start: 18px;
}

.messenger-status {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 13px 15px;
  border-radius: 12px;
  margin-bottom: 16px;
  font-size: 12.5px;
  background: var(--bg-subtle);
  color: var(--text-main);
  border: 1px solid var(--border-base);
}

.messenger-status-dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  margin-top: 5px;
  border-radius: 50%;
  background: var(--text-muted);
}

.messenger-status.connected { background: var(--success-50); border-color: var(--success-600); }
.messenger-status.connected .messenger-status-dot { background: var(--success-600); }
.messenger-status.error { background: var(--danger-50); border-color: var(--danger-600); }
.messenger-status.error .messenger-status-dot { background: var(--danger-600); }
.messenger-status.waiting_key .messenger-status-dot,
.messenger-status.ready .messenger-status-dot { background: var(--warning-600); }

.messenger-status-note {
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.8;
  margin-top: 3px;
}

.messenger-steps {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 2;
  margin: 10px 0 0;
  padding-inline-start: 18px;
}

.messenger-caveat {
  margin-top: 12px;
  padding: 10px 12px;
  font-size: 11.5px;
  line-height: 1.9;
  color: var(--warning-600);
  background: var(--warning-50);
  border-radius: 10px;
}

/* نشانگر «در حال نوشتن» ویجت — سه نقطهٔ آرام. */
.widget-typing {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: 10px 14px;
  margin: 4px 0;
  width: fit-content;
  background: var(--bg-subtle);
  border-radius: 14px;
}

.widget-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-muted);
  animation: vira-typing 1.2s infinite ease-in-out;
}

.widget-typing span:nth-child(2) { animation-delay: .18s; }
.widget-typing span:nth-child(3) { animation-delay: .36s; }

@keyframes vira-typing {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

@media (prefers-reduced-motion: reduce) {
  .widget-typing span { animation: none; opacity: .6; }
}

/* ============================================================================
   ارتفاع صفحه روی گوشی
   ----------------------------------------------------------------------------
   پوستهٔ اپ روی ``height: 100vh`` با ``overflow: hidden`` بسته شده است. روی
   دسکتاپ درست است، روی گوشی نه: مرورگرهای موبایل ``100vh`` را برابر
   بلندترین حالت ویوپورت می‌گیرند — یعنی وقتی نوار آدرس **پنهان** است.
   تا وقتی نوار آدرس دیده می‌شود، ناحیهٔ واقعی کوتاه‌تر است و همان مقدار
   از پایین صفحه بیرون می‌ماند. چون بدنه اسکرول نمی‌کند، آن قسمت
   دست‌نیافتنی می‌شود — روی صندوق پیام اندازه‌گیری شد: ۶۰ پیکسل، درست
   همان‌جایی که نوار ناوبری پایین می‌نشیند.

   ``dvh`` همان ویوپورت است ولی پویا: با باز و بسته‌شدن نوار آدرس
   به‌روز می‌شود. اعلان‌های ``vh`` در ``vira.css`` دست نمی‌خورند و
   به‌عنوان پشتیبان برای مرورگرهای قدیمی می‌مانند؛ این بلوک فقط رویشان
   می‌نشیند.

   ``vira.css`` تولیدشده است و ویرایش نمی‌شود؛ به همین دلیل اینجاست.
   ========================================================================= */

@supports (height: 100dvh) {
  html,
  body,
  #app,
  .app-container,
  .main-wrapper,
  .widget-shell,
  .platform-shell {
    height: 100dvh;
  }

  /* ستون کناری فقط روی دسکتاپ تمام‌قد است. روی گوشی همین عنصر نوار ۶۶
     پیکسلی پایین صفحه است (vira.css، بلوک 720px) و چون این فایل بعد از
     آن بار می‌شود، ارتفاع بی‌شرط اینجا نوار را تا بالای صفحه کش می‌داد
     و روی همهٔ محتوا می‌نشست. نگهبان: apps/core/tests/test_mobile_css.py */
  @media (min-width: 721px) {
    .sidebar {
      height: 100dvh;
    }
  }

  .platform-login-wrap,
  .auth-wrap {
    min-height: 100dvh;
  }

  .inbox-layout {
    height: calc(100dvh - 70px);
  }

  /* روی گوشی نوار منوی ۶۶ پیکسلی پایین هم از ارتفاع کم می‌شود؛ وگرنه
     ته صندوق پیام — دکمهٔ ارسال — زیر نوار می‌افتد و فقط با اسکرول
     دیده می‌شود. */
  @media (max-width: 720px) {
    .inbox-layout {
      height: calc(100dvh - 70px - 66px);
    }
  }
}

/* ----------------------------------------------------------------------------
   ستون گفتگو روی گوشی: جعبهٔ نگارش نباید از پایین بیرون بزند.

   ``.chat-messages-area`` روی ``min-height`` ثابت (۳۶۰px) قفل شده بود و
   ``.chat-thread-header`` روی ۶۵px. روی صفحهٔ بلند مشکلی نداشت، ولی روی
   گوشی جمع اجزا از خودِ ستون بیشتر می‌شد و چون ستون ``overflow: visible``
   بود، جعبهٔ نگارش پایین‌تر از لبهٔ صفحه می‌افتاد — اندازه‌گیری‌شده:
   ۶۹۶px محتوا در ستون ۶۸۲px.

   ناحیهٔ پیام‌ها خودش ``overflow-y: auto`` دارد، پس اجازهٔ کوچک‌شدن به آن
   هیچ محتوایی را از دست نمی‌دهد؛ فقط بیشتر اسکرول می‌خورد. همان الگوی
   «حلقهٔ ارتفاع فلکس» که در مودال‌ها هم بود.
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .inbox-chat-col { overflow: hidden; min-height: 0; }

  .chat-messages-area {
    flex: 1 1 0;
    min-height: 0;
  }

  .chat-thread-header { flex: 0 0 auto; min-height: 0; }
  .chat-composer-box { flex: 0 0 auto; }
}

/* ------------------------------------------------------ قواعد نگهبان */

.guardrail-list {
  margin: 8px 0 0;
  padding-inline-start: 18px;
  font-size: 12px;
  line-height: 2;
  color: var(--text-main);
}

.guardrail-preview {
  margin: 0;
  padding: 12px;
  max-height: 320px;
  overflow: auto;
  background: var(--bg-subtle);
  border-radius: 10px;
  font-size: 11px;
  line-height: 1.9;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text-muted);
  font-family: inherit;
}

/* ------------------------------------------- گروه‌بندی پایگاه دانش */

.kb-group-row td {
  background: var(--bg-subtle);
  padding: 10px 14px;
}

.kb-group-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.kb-group-name {
  font-size: 13px;
  font-weight: 800;
  color: var(--text-main);
}

.kb-group-meta {
  font-size: 11px;
  color: var(--text-muted);
}

.kb-group-actions {
  margin-inline-start: auto;
  display: flex;
  gap: 6px;
  align-items: center;
}

.kb-group-desc {
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.8;
  margin-top: 4px;
}

.kb-empty-group {
  padding: 18px 14px !important;
  font-size: 12px;
  color: var(--text-muted);
  text-align: center;
}

.kb-locator {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 3px;
}

.kb-tags {
  font-size: 10.5px;
  color: var(--primary-700);
  margin-top: 3px;
}

/* --------------------------------------------------- صفحه‌های خطا */

.error-page {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 32px 20px;
  gap: 4px;
}

.error-code {
  font-size: 58px;
  font-weight: 800;
  color: var(--primary-600);
  line-height: 1.2;
}

.error-title {
  font-size: 19px;
  font-weight: 800;
  color: var(--text-main);
  margin: 0 0 8px;
}

.error-text {
  font-size: 13.5px;
  line-height: 2;
  color: var(--text-muted);
  max-width: 420px;
  margin: 0 0 22px;
}
