/* ===============================================================
   لایه‌ی پروژه.

   style.css همان قالب Mobilekit در PWA/ است، با این تفاوت که رنگ‌های ثابتش
   به توکن تبدیل شده‌اند (tokenize.php این کار را از روی نسخه‌ی خام تکرار می‌کند).
   هر چیزی که مخصوص این پروژه است اینجا می‌آید و چون بعد از قالب بارگذاری
   می‌شود، رویش را می‌گیرد.

   دو کار می‌کند:
     ۱. رنگ‌های ثابت قالب را به توکن وصل می‌کند (مقادیر از جدول setting)
     ۲. روی دسکتاپ برنامه را داخل یک قاب موبایل وسط صفحه نشان می‌دهد
   =============================================================== */


/* ---------------------------------------------------------------
   ۱) پالت
   توکن‌ها را تابع THEME() در <head> چاپ می‌کند.
   اینجا فقط سطح‌های اصلی قالب به آن توکن‌ها وصل می‌شوند.
   --------------------------------------------------------------- */

/* تخصیص عمداً با body.dark-mode-active برابر است، وگرنه قاعده‌ی خود قالب
   (که همان تخصیص را دارد و !important هم دارد) برنده می‌شود. */
body,
body.dark-mode-active {
    background: var(--bg) !important;
    color: var(--fg-muted);
}

/* روی موبایل با زمینه یکی است؛ در حالت دسکتاپ پایین‌تر عوض می‌شود
   تا قاب از پس‌زمینه جدا دیده شود. بدون !important تا قاعده‌ی media بتواند
   رویش را بگیرد. */
html { background: var(--bg); }

/* کپسول باید تمام ارتفاع را پر کند وگرنه زیرش رنگ body لخت دیده می‌شود. */
#appCapsule {
    background: var(--bg);
    min-height: 100vh;
}

/* صفحه‌ی بارگذاری اولیه — قالب رنگ سرمه‌ای و اسپینر آبی خودش را دارد. */
#loader,
body.dark-mode-active #loader {
    background: var(--bg);
}
#loader .spinner-border { color: var(--accent) !important; }

/* نوار دکمه‌ی ثابت پایین فرم‌ها (صفحه‌ی ورود و ۲FA) */
.form-button-group,
body.dark-mode-active .form-button-group {
    background: var(--surface);
    border-top: 1px solid var(--line);
}

/* نوار بالا و پایین */
.appHeader,
body.dark-mode-active .appHeader,
.appBottomMenu,
body.dark-mode-active .appBottomMenu,
.extraHeader,
body.dark-mode-active .extraHeader {
    background: var(--surface);
    border-color: var(--line);
    color: var(--fg);
}

.appHeader .pageTitle,
body.dark-mode-active .appHeader .pageTitle,
.appHeader .left .headerButton,
.appHeader .right .headerButton,
body.dark-mode-active .appHeader .left .headerButton,
body.dark-mode-active .appHeader .right .headerButton {
    color: var(--fg);
}

/* متن‌ها */
h1, h2, h3, h4, h5, h6,
body.dark-mode-active h1, body.dark-mode-active h2, body.dark-mode-active h3,
body.dark-mode-active h4, body.dark-mode-active h5, body.dark-mode-active h6 {
    color: var(--fg);
}

/* سطح‌ها */
.card,
body.dark-mode-active .card,
.listview,
body.dark-mode-active .listview,
.wide-block,
body.dark-mode-active .wide-block,
.section-title {
    background: var(--surface);
    color: var(--fg);
    border-color: var(--line);
}

.section-title { background: transparent; color: var(--fg-muted); }

/* فرم‌ها */
.form-group.boxed .form-control,
body.dark-mode-active .form-group.boxed .form-control,
.form-control,
body.dark-mode-active .form-control {
    background: var(--surface);
    color: var(--fg);
    border-color: var(--line);
}
.form-control:focus { border-color: var(--accent); box-shadow: none; }
.form-control::placeholder { color: var(--fg-muted); }

/* دکمه‌ی اصلی */
.btn-primary,
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
    background: var(--accent) !important;
    border-color: var(--accent) !important;
    color: var(--accent-fg) !important;
}
.btn-outline-primary {
    background: transparent !important;
    border-color: var(--accent) !important;
    color: var(--accent) !important;
}

/* حالت فعال منوی پایین */
.appBottomMenu .item.active i.bi,
.appBottomMenu .item.active strong,
body.dark-mode-active .appBottomMenu .item.active i.bi,
body.dark-mode-active .appBottomMenu .item.active strong {
    color: var(--accent);
}
.appBottomMenu .item i.bi,
.appBottomMenu .item strong,
body.dark-mode-active .appBottomMenu .item i.bi,
body.dark-mode-active .appBottomMenu .item strong {
    color: var(--fg-muted);
}

/* حباب چت */
.message-item .bubble {
    direction: rtl;
    text-align: right;
    background: var(--surface);
    color: var(--fg);
}
/* پیشوند body.dark-mode-active عمدی است: قاعده‌ی خود قالب
   «body.dark-mode-active .message-item .bubble» یک واحد ویژگی بیشتر دارد و
   بدون این پیشوند، متنِ حباب خودی رنگ متن عادی را می‌گیرد — روی رنگ شاخصِ
   روشنِ حالت تیره خوانا نیست. */
.message-item.user .bubble,
body.dark-mode-active .message-item.user .bubble {
    background: var(--accent);
    color: var(--accent-fg);
}

/* امضای سازنده */
.credit-link { font-size: 9pt; color: var(--fg-muted); text-decoration: none; }
.credit-link:hover, .credit-link:focus { color: var(--fg); text-decoration: underline; }


/* ---------------------------------------------------------------
   ۲) حالت دسکتاپ — قاب موبایل وسط صفحه

   قالب برای عرض موبایل ساخته شده و روی مانیتور کشیده و بدریخت می‌شود.
   به‌جای بستن دسترسی دسکتاپ، برنامه داخل یک قاب با عرض موبایل نشان
   داده می‌شود. نوارهای position:fixed هم به همان قاب محدود می‌شوند.
   --------------------------------------------------------------- */


@media (min-width: 768px) {

    /* پس‌زمینه‌ی بیرون قاب — کمی روشن‌تر از خود قاب تا لبه‌هایش دیده شود. */
    html { background: var(--surface-alt); }
    html:not(.dark-mode-active) { background: #E8E8E8; }

    body {
        /* قاب: عرض موبایل، وسط صفحه، با ارتفاع کامل */
        width: var(--frame);
        max-width: 100%;
        min-height: 100vh;
        margin: 0 auto;
        position: relative;
        overflow-x: hidden;
        border-left: 1px solid var(--line);
        border-right: 1px solid var(--line);
        box-shadow: 0 0 40px rgba(0, 0, 0, .18);
    }

    /* عنصرهای fixed نسبت به viewport می‌چسبند، نه به قاب.
       با تبدیل مختصاتشان به همان عرض، داخل قاب می‌مانند.
       هر عنصر position:fixed جدیدی که اضافه شد باید به این فهرست هم بیاید. */
    .appHeader,
    .extraHeader,
    .poll-modal,
    .chat-panel,
    .appBottomMenu,
    .chatFooter,
    .form-button-group,
    .fab-button.bottom-center,
    .notification-box,
    #loader {
        width: var(--frame) !important;
        max-width: 100%;
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%);
    }

    /* آفکانواس و مودال‌ها هم داخل قاب */
    .offcanvas.offcanvas-bottom,
    .action-sheet {
        width: var(--frame) !important;
        max-width: 100%;
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%);
    }

    .modal-dialog {
        max-width: var(--frame);
    }

    /* قاب‌های تمام‌صفحه‌ی مسابقه هم محدود شوند */
    .quiz-frame,
    .quiz-actions,
    .quiz-viewers,
    .touch-disabled {
        max-width: var(--frame);
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%);
    }
    .quiz-frame { width: calc(var(--frame) - 32px); }
    .quiz-actions { width: calc(var(--frame) - 40px); }
    /* کشوی کناری نسبت به viewport می‌چسبد؛ به لبه‌ی قاب منتقلش می‌کنیم.
       بدون این، منو ته صفحه‌ی دسکتاپ باز می‌شد و از برنامه جدا به نظر می‌رسید.
       style.css قالب در حالت راست‌چین start را سمت راست می‌گذارد و end را چپ،
       پس نگاشت اینجا هم همان است. */
    .offcanvas.offcanvas-start {
        right: calc(50% - var(--frame) / 2) !important;
        left: auto !important;
    }
    .offcanvas.offcanvas-end {
        left: calc(50% - var(--frame) / 2) !important;
        right: auto !important;
    }
}


/* ---------------------------------------------------------------
   ۴) اصلاح‌های موضعی
   --------------------------------------------------------------- */

/* توگل‌ها: در تم سیاه‌وسفید، رنگ شاخص سفید است. اگر دستگیره هم سفید بماند
   روی مسیر سفید ناپدید می‌شود. دستگیره را به رنگ متن‌روی‌شاخص می‌بریم. */
.form-check-input:checked ~ .form-check-label:after,
body.dark-mode-active .form-check-input:checked ~ .form-check-label:after,
.form-switch .form-check-input:checked ~ .form-check-label:after,
body.dark-mode-active .form-switch .form-check-input:checked ~ .form-check-label:after {
    background-color: var(--accent) !important;
    border-color: var(--accent) !important;
}
.form-switch .form-check-input:checked ~ .form-check-label:before,
body.dark-mode-active .form-switch .form-check-input:checked ~ .form-check-label:before {
    background: var(--accent-fg) !important;
}
.form-switch .form-check-label:before,
body.dark-mode-active .form-switch .form-check-label:before {
    background: var(--fg-muted);
}
.form-switch .form-check-label:after,
body.dark-mode-active .form-switch .form-check-label:after {
    background-color: var(--surface-alt);
    border-color: var(--line) !important;
}

/* دکمه‌ی تغییر تم روشن/تیره در نوار بالا */
.themeToggle {
    background: none;
    border: 0;
    padding: 0 6px;
    color: var(--fg);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}


/* ===============================================================
   لایه‌ی پروژه

   عمداً آخرین بخش فایل است: اُوِرایدهای تولیدشده‌ی بالا با انتخابگرهایی
   مثل «body.dark-mode-active .form-group.boxed .form-control» ویژگی
   (0,4,1) دارند و هر قاعده‌ی هم‌وزنی که قبل از آنها بیاید را می‌بازانند.
   با آخر بودن، قاعده‌های این بخش در تساوی ویژگی برنده می‌شوند.
   =============================================================== */

/* ---------------------------------------------------------------
   نظرسنجی چت.
   استایلش قبلاً در شیت برندشده بود و با حذف آن از بین رفت، برای همین
   بدون هیچ قاعده‌ای وسط جریان صفحه می‌افتاد و از کادر می‌زد بیرون.
   جاوااسکریپت صفحه به ارتفاعش paddingTop می‌دهد، یعنی انتظار دارد
   چسبیده و روی محتوا باشد — همان کاری که اینجا انجام می‌شود.
   --------------------------------------------------------------- */
.poll-modal {
    position: fixed;
    /* درست زیر appHeader — که روی iPhone نصب‌شده خودش زیر نوار وضعیت است
       (top: safe-area)؛ بدون آن، نظرسنجی روی نیمه‌ی پایین سربرگ می‌افتاد. */
    top: calc(56px + env(safe-area-inset-top));
    left: 0;
    right: 0;
    z-index: 1020;
    padding: 12px 16px 14px;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
}

:is(.poll-modal, .dash-poll) .poll-question {
    margin: 0 0 10px;
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.7;
    text-align: center;
    color: var(--fg-muted);
}

/* گزینه‌ها از تنظیمات می‌آیند و تعدادشان ثابت نیست، پس به‌جای ستون‌های
   ثابت بوت‌استرپ از flex استفاده می‌شود که ۲ تا ۶ گزینه را جا بدهد. */
:is(.poll-modal, .dash-poll) .poll-options {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

:is(.poll-modal, .dash-poll) .poll-option {
    position: relative;
    flex: 1 1 calc(50% - 8px);
    min-width: 96px;
    height: 40px;
    padding: 0 10px;
    border-radius: 10px;
    font-size: 13px;
    font-weight: 600;
    background: var(--surface-alt);
    border: 1px solid var(--line);
    color: var(--fg);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    transition: transform 120ms ease, background 120ms ease;
}

/* نوار درصد پشت متن می‌نشیند تا سهم هر گزینه در یک نگاه دیده شود. */
:is(.poll-modal, .dash-poll) .poll-bar {
    position: absolute;
    inset-inline-start: 0;
    top: 0;
    bottom: 0;
    width: 0;
    background: var(--accent);
    opacity: .16;
    transition: width 320ms cubic-bezier(.22, .61, .36, 1);
    pointer-events: none;
}

:is(.poll-modal, .dash-poll) .poll-label,
:is(.poll-modal, .dash-poll) .poll-count {
    position: relative;   /* روی نوار */
    white-space: nowrap;
}

:is(.poll-modal, .dash-poll) .poll-count {
    font-size: 10.5px;
    font-weight: 500;
    color: var(--fg-muted);
    font-variant-numeric: tabular-nums;
}

:is(.poll-modal, .dash-poll) .poll-option.is-picked .poll-count { color: var(--accent-fg); }
:is(.poll-modal, .dash-poll) .poll-option.is-picked .poll-bar   { opacity: 0; }

:is(.poll-modal, .dash-poll) .poll-option:active { transform: scale(.96); }

:is(.poll-modal, .dash-poll) .poll-option.is-picked {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-fg);
}

:is(.poll-modal, .dash-poll) .poll-option.is-busy { opacity: .55; pointer-events: none; }


/* ---------------------------------------------------------------
   انیمیشن‌ها

   قواعد به صورت عادی نوشته شده‌اند و فقط زیر prefers-reduced-motion: reduce
   خاموش می‌شوند. حالت برعکس (no-preference) روی مرورگری که این پرسش رسانه‌ای
   را نمی‌شناسد هیچ انیمیشنی نمی‌داد.
   --------------------------------------------------------------- */

/* جهت حرکت. در راست‌چین برعکس چپ‌چین است تا حس «هل دادن» درست بماند. */
:root            { --spa-shift: -12px; }
html[dir="rtl"]  { --spa-shift:  12px; }

/* --- جابه‌جایی بین صفحه‌ها ---
   قبلاً کل #spa-root (با هدر و منوی پایین) تا جواب سرور به شفافیت صفر می‌رفت
   و روی سرور کند، صفحه چند لحظه سفید می‌ماند. حالا هدر و منو سر جایشان
   می‌مانند، فقط محتوا کم‌رنگ و کمی جابه‌جا می‌شود و نوار باریک بالای صفحه
   نشان می‌دهد که صفحه‌ی بعد در راه است.
   ترنسفورم عمداً روی #spa-root نیست: عنصرهای position:fixed داخلش مرجعشان
   عوض می‌شد و می‌پریدند؛ اسلاید فقط روی #appCapsule است. */
#spa-root.spa-leave #appCapsule {
    opacity: .45;
    transform: translateX(var(--spa-shift));
    transition: opacity 140ms ease, transform 140ms ease-in;
    pointer-events: none;
}

#spa-root.spa-leave::before {
    content: ""; position: fixed; z-index: 10000; top: env(safe-area-inset-top); inset-inline-start: 0;
    height: 3px; width: 100%; background: var(--accent); transform-origin: 100% 50%;
    animation: spaBar 1.6s cubic-bezier(.1, .7, .3, 1) forwards;
}
html[dir="ltr"] #spa-root.spa-leave::before { transform-origin: 0 50%; }
@keyframes spaBar { from { transform: scaleX(0); } to { transform: scaleX(.9); } }

#spa-root.spa-enter #appCapsule {
    animation: spaEnter 260ms cubic-bezier(.22, .61, .36, 1);
}

/* صفحه‌ای که دکمه‌ی شناور دارد فقط محو می‌شود — چون آن دکمه position:fixed
   است و با ترنسفورمِ #appCapsule مرجعش عوض می‌شود. */
#spa-root.spa-no-slide.spa-leave #appCapsule,
#spa-root.spa-no-slide.spa-enter #appCapsule {
    transform: none;
    transition: none;
    animation: none;
}

@keyframes spaEnter {
    from { opacity: .45; transform: translateX(calc(var(--spa-shift) * -1.4)); }
    to   { opacity: 1;   transform: none; }
}

/* --- ورود پیام تازه در چت ---
   فقط به پیام‌هایی داده می‌شود که در تازه‌سازی قبلی نبودند، وگرنه هر
   ۷ ثانیه کل گفت‌وگو دوباره انیمیت می‌شد. */
.message-item.msg-enter {
    animation: msgEnter 300ms cubic-bezier(.22, .61, .36, 1);
}

@keyframes msgEnter {
    from { opacity: 0; transform: translateY(10px) scale(.96); }
    to   { opacity: 1; transform: none; }
}

/* --- بازخورد لمس دکمه‌ی ارسال --- */
#send-chat-btn {
    transition: transform 120ms ease;
}

#send-chat-btn:active {
    transform: scale(.86);
}

/* کاربری که در سیستم‌عاملش کاهش حرکت را روشن کرده، هیچ‌کدام را نمی‌بیند. */
@media (prefers-reduced-motion: reduce) {
    #spa-root,
    #spa-root.spa-leave,
    #spa-root.spa-leave #appCapsule,
    #spa-root.spa-enter #appCapsule,
    .message-item.msg-enter,
    #send-chat-btn,
    #send-chat-btn:active {
        transition: none;
        animation: none;
        transform: none;
    }
    #spa-root.spa-leave #appCapsule { opacity: 1; }
    #spa-root.spa-leave::before { animation: none; transform: scaleX(.6); }
}


/* ---------------------------------------------------------------
   صفحه‌های ورود و ثبت‌نام

   بدون کارت و بدون قاب: محتوا وسط صفحه می‌نشیند و دکمه‌ی اصلی پایین
   می‌چسبد — همان الگویی که برنامه‌های موبایل دارند.
   --------------------------------------------------------------- */
.auth-page {
    min-height: 100vh;
    min-height: 100dvh;          /* روی موبایل نوار آدرس را حساب می‌کند */
    display: flex;
    flex-direction: column;
    padding: 24px 24px calc(24px + env(safe-area-inset-bottom));
    box-sizing: border-box;
}

/* بخش وسط: هرچه فضای آزاد هست را می‌گیرد و محتوایش را وسط می‌گذارد. */
.auth-main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    max-width: 340px;
    margin: 0 auto;
}

/* نشان جای لوگو — حرف اول عنوان برنامه. چون پروژه سفیدبرچسب است
   هیچ تصویر ثابتی اینجا نمی‌گذاریم. */
.auth-mark img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.auth-mark {
    overflow: hidden;
    width: 60px;
    height: 60px;
    margin: 0 auto 18px;
    border-radius: 18px;
    background: var(--accent);
    color: var(--accent-fg);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    user-select: none;
}

.auth-title {
    margin: 0 0 5px;
    font-size: 20px;
    font-weight: 700;
    text-align: center;
    color: var(--fg);
}

.auth-sub {
    margin: 0 0 26px;
    font-size: 12.5px;
    text-align: center;
    color: var(--fg-muted);
}

/* هشدارها: فقط ته‌رنگ و لبه، با رنگ از توکن‌های معنایی. */
.auth-page .alert {
    padding: 11px 13px;
    margin-bottom: 18px;
    font-size: 12px;
    line-height: 1.7;
    border-radius: 12px;
    background: var(--surface-alt);
    border: 1px solid var(--line);
    color: var(--fg);
}

.auth-page .alert-success {
    background: color-mix(in srgb, var(--ok) 15%, var(--bg));
    border-color: color-mix(in srgb, var(--ok) 45%, transparent);
}

.auth-page .alert-danger {
    background: color-mix(in srgb, var(--danger) 15%, var(--bg));
    border-color: color-mix(in srgb, var(--danger) 45%, transparent);
}

.auth-page .alert-warning {
    background: color-mix(in srgb, var(--warn) 15%, var(--bg));
    border-color: color-mix(in srgb, var(--warn) 45%, transparent);
}

.auth-page .alert::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-left: 7px;
    vertical-align: middle;
    background: var(--fg-muted);
}

.auth-page .alert-success::before { background: var(--ok); }
.auth-page .alert-danger::before  { background: var(--danger); }
.auth-page .alert-warning::before { background: var(--warn); }

.auth-page .form-group.boxed { margin-bottom: 16px; }

/* قاعده‌ی عمومی قالب «body.dark-mode-active .form-group.boxed .form-control»
   ویژگی (0,4,1) دارد؛ برای همین انتخابگر اینجا هم باید هم‌وزن باشد، وگرنه
   فیلدها پس‌زمینه‌ی پُر می‌گرفتند و شکل کارتی می‌ماندند. */
body .auth-page .form-group.boxed .form-control,
body .auth-page .form-control {
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    height: 46px;
    padding: 0 2px;
    color: var(--fg);
}

body .auth-page .form-group.boxed .form-control:focus,
body .auth-page .form-control:focus {
    border-bottom-color: var(--accent);
    box-shadow: none;
}

/* تکمیل خودکار مرورگر رنگ آبی خودش را تحمیل می‌کند و فیلد از پالت بیرون می‌زند. */
.auth-page .form-control:-webkit-autofill,
.auth-page .form-control:-webkit-autofill:hover,
.auth-page .form-control:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--fg);
    -webkit-box-shadow: 0 0 0 1000px var(--bg) inset;
    caret-color: var(--fg);
}

.auth-page .form-label {
    font-size: 11px;
    color: var(--fg-muted);
    margin-bottom: 4px;
}

/* بخش پایین: دکمه‌ی اصلی و لینک‌ها، چسبیده به کف صفحه. */
.auth-bottom {
    flex: 0 0 auto;
    width: 100%;
    max-width: 340px;
    margin: 24px auto 0;
}

.auth-page .btn-block {
    width: 100%;
    height: 50px;
    border-radius: 14px;
    font-size: 15px;
    font-weight: 700;
}

.auth-alt {
    margin: 0 0 14px;
    font-size: 12.5px;
    text-align: center;
    color: var(--fg-muted);
}

.auth-alt a { font-weight: 700; color: var(--accent); }

.auth-hint {
    margin: 10px 0 0;
    font-size: 10.5px;
    line-height: 1.9;
    text-align: center;
    color: var(--fg-muted);
}

.auth-foot {
    margin-top: 10px;
    text-align: center;
}


/* ---------------------------------------------------------------
   تخته‌ی ایموجی و استیکر پیام‌رسان
   --------------------------------------------------------------- */
.chat-panel {
    position: fixed;
    bottom: 64px;                 /* بالای نوار نوشتن پیام */
    left: 0;
    right: 0;
    z-index: 1030;
    max-height: 46vh;
    overflow-y: auto;
    padding: 12px;
    background: var(--surface);
    border-top: 1px solid var(--line);
    box-shadow: 0 -10px 30px -18px rgba(0, 0, 0, .6);
}

.chat-panel-grid {
    display: grid;
    gap: 6px;
}

.emoji-grid   { grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); }
.sticker-grid { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 8px; }

.emoji-item {
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 9px;
    background: transparent;
    /* فونت متن فارسی برنامه ایموجی ندارد و مربع خالی نشان می‌داد؛
       اینجا صراحتاً فونت ایموجی سیستم خواسته می‌شود. */
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji",
                 "Segoe UI Symbol", "Android Emoji", sans-serif;
    font-size: 23px;
    line-height: 1;
    cursor: pointer;
    transition: background 120ms ease, transform 120ms ease;
}

.emoji-item:hover  { background: var(--surface-alt); }
.emoji-item:active { transform: scale(.88); }

.sticker-item {
    padding: 4px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface-alt);
    aspect-ratio: 1 / 1;
    cursor: pointer;
    transition: transform 120ms ease;
}

.sticker-item:active { transform: scale(.92); }

.sticker-item img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* پیامی که خودش فقط یک نشانی تصویر است، به‌جای متن نشان داده می‌شود. */
.message-item .bubble img.sticker-in-chat {
    display: block;
    width: 128px;
    max-width: 100%;
    height: auto;
    border-radius: var(--radius);
}

/* حبابی که فقط یک استیکر دارد، حباب نیست: قاب رنگی دورش استیکر را
   شبیه دکمه نشان می‌داد. پیشوند body لازم است تا از قاعده‌ی خود قالب
   جلو بزند. */
body .message-item .bubble:has(> img.sticker-in-chat),
body.dark-mode-active .message-item .bubble:has(> img.sticker-in-chat) {
    background: none;
    padding: 0;
    box-shadow: none;
}

/* ---------------------------------------------------------------
   مدیریت گزینه‌های نظرسنجی و استیکرها در صفحه‌ی تنظیمات
   --------------------------------------------------------------- */
/* ردیف گزینه خودش یک form-group boxed است تا فیلدش دقیقاً مثل بقیه‌ی
   صفحه‌های تنظیمات دیده شود؛ دکمه‌ی حذف کنارش می‌نشیند. */
.option-row {
    display: flex;
    align-items: flex-end;
    gap: 6px;
}

.option-row .input-wrapper { flex: 1 1 auto; }

.option-remove {
    flex: 0 0 34px;
    height: 42px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--fg-muted);
    font-size: 13px;
    cursor: pointer;
}

.option-remove:hover { background: var(--surface-alt); color: var(--danger); }

/* با دو گزینه، حذف معنا ندارد و دکمه‌اش خاموش می‌شود. */
#poll-option-list.at-minimum .option-remove { opacity: .3; pointer-events: none; }
#add-option { margin-top: 4px; }
#add-option:disabled { opacity: .4; }

.sticker-manager {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 10px;
}

.sticker-card {
    position: relative;
    aspect-ratio: 1 / 1;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface-alt);
    overflow: hidden;
}

.sticker-card img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 6px;
    display: block;
}

.sticker-del {
    position: absolute;
    top: 5px;
    left: 5px;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: 12px;
    cursor: pointer;
}

/* خانه‌ی «افزودن» هم‌اندازه‌ی بقیه است تا شبکه یکدست بماند. */
.sticker-add {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    aspect-ratio: 1 / 1;
    border: 1px dashed var(--line);
    border-radius: 14px;
    color: var(--fg-muted);
    font-size: 11px;
    cursor: pointer;
    transition: border-color 120ms ease, color 120ms ease;
}

.sticker-add:hover { border-color: var(--accent); color: var(--accent); }
.sticker-add i { font-size: 17px; }

.sticker-empty {
    margin: 12px 0 0;
    font-size: 12px;
    color: var(--fg-muted);
}

/* ---------------------------------------------------------------
   نوار نوشتن پیام

   دکمه‌های ایموجی و استیکر با کلاس btn-secondary قالب، مربع‌های خاکستریِ
   بی‌ربط به پالت می‌شدند. اینجا هم‌شکل و هم‌اندازه‌ی دکمه‌ی ارسال می‌شوند.
   --------------------------------------------------------------- */
.chatFooter .chat-tool {
    flex: 0 0 38px;
    width: 38px;
    height: 38px;
    padding: 0;
    border-radius: 50%;
    background: var(--surface-alt);
    border: 1px solid var(--line);
    color: var(--fg-muted);
    font-size: 17px;
    line-height: 1;
    transition: color 120ms ease, transform 120ms ease, border-color 120ms ease;
}

.chatFooter .chat-tool:hover {
    color: var(--accent);
    border-color: var(--accent);
}

.chatFooter .chat-tool:active { transform: scale(.9); }

/* دکمه‌ی باز، حالت فعال بگیرد تا معلوم باشد کدام تخته باز است. */
.chatFooter .chat-tool.is-open {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-fg);
}

.chatFooter #send-chat-btn {
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
}

/* فاصله‌ی یکدست بین دکمه‌ها و کادر متن */
.chatFooter form {
    display: flex;
    align-items: center;
    gap: 7px;
}

.chatFooter .form-group.boxed {
    flex: 1 1 auto;
    margin-bottom: 0;
}

/* ---------------------------------------------------------------
   پخش زنده
   --------------------------------------------------------------- */
.stream-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;      /* به‌جای ترفند padding-top */
    background: #000;
}

.stream-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.stream-bad,
.stream-empty {
    margin: 0;
    padding: 18px;
    font-size: 12.5px;
    line-height: 1.9;
    text-align: center;
    color: var(--fg-muted);
}

/* شبکه‌ی انتخاب کانال وقتی بیش از یکی تعریف شده. */
.stream-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 12px;
}

.stream-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    color: var(--fg);
    text-decoration: none;
}

.stream-tile-art {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 1 / 1;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: var(--surface-alt);
    overflow: hidden;
    transition: border-color 120ms ease, transform 120ms ease;
}

.stream-tile:active .stream-tile-art { transform: scale(.95); }
.stream-tile:hover  .stream-tile-art { border-color: var(--accent); }

.stream-tile-art img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 8px;
}

.stream-tile-art i { font-size: 26px; color: var(--fg-muted); }

.stream-tile span {
    font-size: 11.5px;
    text-align: center;
    line-height: 1.5;
}

/* نوار کانال‌های دیگر، زیر پخش جاری. */
.stream-strip {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    padding: 0 16px 4px;
    -webkit-overflow-scrolling: touch;
}

.stream-chip {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    width: 70px;
    color: var(--fg);
    text-decoration: none;
    font-size: 10.5px;
    text-align: center;
}

.stream-chip img,
.stream-chip i {
    width: 54px;
    height: 54px;
    border-radius: 14px;
    border: 1px solid var(--line);
    background: var(--surface-alt);
    object-fit: contain;
    padding: 6px;
}

.stream-chip i {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    color: var(--fg-muted);
}

/* دکمه‌های ردیف کانال در صفحه‌ی مدیریت. */
.stream-actions { display: flex; gap: 4px; }

.stream-btn {
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: var(--fg-muted);
    font-size: 13px;
    cursor: pointer;
}

.stream-btn:hover { background: var(--surface-alt); color: var(--accent); }
.stream-btn-danger:hover { color: var(--danger); }

/* ---------------------------------------------------------------
   مودال‌ها

   قالب برای dialogbox فقط عرض را محدود می‌کند، نه ارتفاع را؛ پس مودالی
   که محتوایش بلند بود تا کف صفحه کش می‌آمد و عملاً تمام‌صفحه می‌شد.
   اینجا ارتفاع سقف می‌گیرد و فقط بدنه اسکرول می‌شود، تا سربرگ و دکمه‌ها
   همیشه دیده شوند.

   modalbox و stories عمداً تمام‌صفحه‌اند و دست نمی‌خورند.
   --------------------------------------------------------------- */
.modal.dialogbox .modal-dialog,
.modal.action-sheet .modal-dialog {
    max-width: 340px;
    margin: auto;                 /* وسط افقی و عمودی */
}

.modal.dialogbox .modal-dialog {
    display: flex;
    align-items: center;
    min-height: calc(100% - 32px);
}

.modal.dialogbox .modal-content {
    width: 100%;
    max-height: calc(100vh - 48px);
    max-height: calc(100dvh - 48px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

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

.modal.dialogbox .modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* فرم داخل مودال همان شکل بقیه‌ی صفحه‌ها را داشته باشد. */
.modal.dialogbox .modal-body .form-group.boxed:last-of-type { margin-bottom: 6px; }

/* ---------------------------------------------------------------
   دکمه‌های هدر

   قاعده‌ی .headerButton قالب برای <a> نوشته شده و پس‌زمینه/حاشیه را ریست
   نمی‌کند. هر <button> با همان کلاس، جعبه‌ی خاکستری پیش‌فرض مرورگر را
   نگه می‌داشت. (دکمه‌های تازه‌سازی و تغییر تم و افزودن همه <button>اند،
   چون کارشان ناوبری نیست.)
   --------------------------------------------------------------- */
button.headerButton {
    background: transparent;
    border: 0;
    padding: 10px;
    font: inherit;
    color: inherit;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}

button.headerButton:focus { outline: none; }

/* ---------------------------------------------------------------
   دکمه‌های داخل مودال

   قاعده‌های قالب برای dialogbox رنگ‌های سرمه‌ای ثابت دارند
   (#0F1C2F برای دکمه، #1B283B برای جداکننده) و ویژگی‌شان خیلی بالاست
   (هفت کلاس تو در تو). برای همین دکمه‌ی «انصراف» آبی می‌شد و «بستن» در
   پس‌زمینه گم. انتخابگرها اینجا هم‌وزن نوشته شده‌اند تا پالت برنده شود.
   حالت hover/focus قالب !important دارد، پس اینجا هم لازم است.
   --------------------------------------------------------------- */
body .dialogbox .modal-dialog .modal-content .btn-inline,
body .dialogbox .modal-dialog .modal-content .modal-footer {
    background: var(--line);
    border-top: 1px solid var(--line);
}

body .dialogbox .modal-dialog .modal-content .btn-inline .btn,
body .dialogbox .modal-dialog .modal-content .modal-footer .btn {
    background: var(--surface);
    color: var(--fg);
    border: 0 !important;
    min-height: 52px;
    font-size: 14px;
    font-weight: 600;
}

body .dialogbox .modal-dialog .modal-content .btn-inline .btn:hover,
body .dialogbox .modal-dialog .modal-content .btn-inline .btn:focus,
body .dialogbox .modal-dialog .modal-content .btn-inline .btn:active,
body .dialogbox .modal-dialog .modal-content .btn-inline .btn.active,
body .dialogbox .modal-dialog .modal-content .modal-footer .btn:hover,
body .dialogbox .modal-dialog .modal-content .modal-footer .btn:focus,
body .dialogbox .modal-dialog .modal-content .modal-footer .btn:active {
    background: var(--surface-alt) !important;
    color: var(--fg) !important;
}

/* قاعده‌ی تیره‌ی قالب رنگ متن را #8195a6 می‌کند و یک واحد ویژگی بیشتر
   دارد (body.dark-mode-active به‌جای body)، پس اینجا هم هم‌وزن می‌شود. */
body.dark-mode-active .dialogbox .modal-dialog .modal-content .btn-inline .btn,
body.dark-mode-active .dialogbox .modal-dialog .modal-content .modal-footer .btn,
body.dark-mode-active .dialogbox .modal-dialog .modal-content .btn-list .btn {
    background: var(--surface);
    color: var(--fg);
}

body.dark-mode-active .dialogbox .modal-dialog .modal-content .btn-inline {
    background: var(--line);
}

/* دکمه‌ی تأیید (آخرین دکمه) پررنگ‌تر باشد تا کنش اصلی معلوم شود. */
body .dialogbox .modal-dialog .modal-content .btn-inline .btn[type="submit"],
body.dark-mode-active .dialogbox .modal-dialog .modal-content .btn-inline .btn[type="submit"] {
    color: var(--accent);
}

body .dialogbox .modal-dialog .modal-content .btn-list .btn {
    background: var(--surface);
    color: var(--fg);
    border-bottom-color: var(--line) !important;
}

body .dialogbox .modal-dialog .modal-content .btn-list .btn:hover,
body .dialogbox .modal-dialog .modal-content .btn-list .btn:focus,
body .dialogbox .modal-dialog .modal-content .btn-list .btn:active {
    background: var(--surface-alt) !important;
}

body .dialogbox .modal-dialog .modal-content .modal-title { color: var(--fg); }
body .dialogbox .modal-dialog .modal-content .modal-body  { color: var(--fg); }

/* فوتر تک‌دکمه‌ای هم مثل btn-inline تمام‌عرض شود. */
body .dialogbox .modal-dialog .modal-content .modal-footer {
    padding: 0;
    display: block;
}

body .dialogbox .modal-dialog .modal-content .modal-footer .btn {
    width: 100%;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg) !important;
}

/* ---------------------------------------------------------------
   ۱۰) گردی گوشه‌ها

   قالب همه‌جا 6px ثابت گذاشته بود، برای همین هر پالتی هم که انتخاب می‌شد
   شکل برنامه یکی بود. اینجا سطح‌های اصلی به --radius وصل می‌شوند تا هر
   پالت بتواند حس متفاوتی بدهد: تیز، ملایم یا کاملاً گرد.
   فقط سطح‌هایی که کاربر واقعاً می‌بیند در این فهرست‌اند؛ گردی‌های ۱۰۰٪
   (آواتارها) و نوارها عمداً دست‌نخورده‌اند.
   --------------------------------------------------------------- */

.btn,
body.dark-mode-active .btn,
.form-control,
body.dark-mode-active .form-control,
.custom-select,
.form-group.boxed .form-control,
body.dark-mode-active .form-group.boxed .form-control {
    border-radius: var(--radius) !important;
}

/* کارت‌ها و بلوک‌های محتوا */
.card,
.chat-panel,
.poll-opt,
.sticker-card,
.sticker-add,
.stream-tile-art,
.stream-chip,
.stream-frame,
.alert {
    border-radius: var(--radius) !important;
}

/* تصویرهایی که قالب گردشان کرده بود */
.imaged.radius   { border-radius: var(--radius-sm) !important; }

/* حباب چت کمی گردتر از بقیه است — این شکل استاندارد پیام‌رسان‌هاست. */
.message-item .bubble,
body.dark-mode-active .message-item .bubble {
    border-radius: var(--radius-lg) !important;
}

/* مودال و فوتر تمام‌عرضش باید یک عدد داشته باشند وگرنه گوشه‌ی پایین می‌شکند. */
.dialogbox .modal-dialog .modal-content,
body.dark-mode-active .dialogbox .modal-dialog .modal-content {
    border-radius: var(--radius-lg) !important;
}


/* اکشن‌شیت از پایین بالا می‌آید، پس فقط دو گوشه‌ی بالایش گرد است. */
.action-sheet .modal-content,
body.dark-mode-active .action-sheet .modal-content {
    border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important;
}

/* ---------------------------------------------------------------
   ۱۱) صفحه‌ی قالب و رنگ

   کارت‌های پالت عمداً هر دو نیمه (روشن و تیره) را نشان می‌دهند، چون
   انتخاب فقط برای حالت فعلی نیست و کاربر باید هر دو را با هم ببیند.
   --------------------------------------------------------------- */

.preset-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 12px;
}

.preset-card {
    background: none;
    border: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    font-family: inherit;
}

.preset-swatch {
    display: flex;
    width: 100%;
    height: 62px;
    overflow: hidden;
    border: 2px solid var(--line);
    transition: border-color .15s, transform .15s;
}

.preset-card:active .preset-swatch { transform: scale(.95); }
.preset-card.is-on .preset-swatch  { border-color: var(--accent); }

.preset-half {
    flex: 1;
    padding: 8px 7px;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 5px;
}

.preset-dot {
    width: 16px;
    height: 16px;
    border-radius: 100%;
    display: block;
}

/* دو خط نازک، نمایندهٔ متن اصلی و خطوط جداکننده. */
.preset-line {
    height: 3px;
    border-radius: 3px;
    display: block;
    opacity: .85;
}
.preset-line:nth-of-type(2) { width: 80%; }
.preset-line:nth-of-type(3) { width: 55%; }

.preset-name {
    font-size: 11px;
    color: var(--fg);
}
.preset-card.is-on .preset-name {
    color: var(--accent);
    font-weight: 700;
}

.theme-hint {
    margin: 12px 0 0;
    font-size: 11px;
    line-height: 1.8;
    color: var(--fg-muted);
}

/* --- نمونه‌ی زنده --- */

.theme-demo {
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--bg);
}

.theme-demo-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    color: var(--fg);
    font-size: 13px;
    font-weight: 700;
}
.theme-demo-bar i { color: var(--accent); font-weight: 400; }

.theme-demo-body { padding: 12px 14px 14px; }

.theme-demo-in,
.theme-demo-out {
    max-width: 78%;
    padding: 8px 12px;
    border-radius: var(--radius-lg);
    font-size: 12px;
    margin-bottom: 8px;
}

.theme-demo-in {
    background: var(--surface-alt);
    color: var(--fg);
    margin-left: auto;
}

.theme-demo-out {
    background: var(--accent);
    color: var(--accent-fg);
    margin-right: auto;
}

.theme-demo-muted {
    font-size: 11px;
    color: var(--fg-muted);
    margin: 0 0 12px;
}

/* --- رنگ دستی --- */

.theme-subhead {
    font-size: 12px;
    color: var(--fg-muted);
    margin: 20px 0 8px;
    font-weight: 700;
}

.theme-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--line);
    margin: 0;
    cursor: pointer;
}
.theme-row:last-child { border-bottom: 0; }

/* کادر رنگ مرورگر لبه و زمینه‌ی خودش را دارد؛ برداشته می‌شود تا فقط
   خودِ رنگ دیده شود. */
.theme-swatch {
    flex: none;
    width: 40px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: none;
    cursor: pointer;
}
.theme-swatch::-webkit-color-swatch-wrapper { padding: 2px; }
.theme-swatch::-webkit-color-swatch { border: 0; border-radius: calc(var(--radius-sm) - 1px); }
.theme-swatch::-moz-color-swatch { border: 0; border-radius: calc(var(--radius-sm) - 1px); }

.theme-row-label { flex: 1; font-size: 13px; color: var(--fg); }
/* فونت فارسی رقم‌های لاتین را به فارسی نگاشت می‌کند و کد رنگ «#F۴F۵FB»
   درمی‌آید. فونت تک‌فاصله این نگاشت را ندارد. */
.theme-row-hex {
    font-size: 11px;
    color: var(--fg-muted);
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
}

/* --- لغزنده --- */

.form-range {
    width: 100%;
    height: 24px;
    background: none;
    padding: 0;
    -webkit-appearance: none;
    appearance: none;
}
.form-range::-webkit-slider-runnable-track {
    height: 4px;
    border-radius: 4px;
    background: var(--line);
}
.form-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    margin-top: -8px;
    border-radius: 100%;
    background: var(--accent);
    border: 0;
}
.form-range::-moz-range-track {
    height: 4px;
    border-radius: 4px;
    background: var(--line);
}
.form-range::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border-radius: 100%;
    background: var(--accent);
    border: 0;
}

/* ---------------------------------------------------------------
   ۱۲) نشان ثانویه

   رنگ ثانویه‌ی قالب به --fg-muted نگاشت شده. وقتی همان رنگ پس‌زمینه‌ی یک
   نشان می‌شود، متن رویش دیگر نباید رنگ متن عادی باشد — خاکستری روی خاکستری
   می‌شد (۲٫۳ در حالت تیره). متنِ «روی رنگ» در هر دو حالت درست است: در روشن
   سفید و در تیره تقریباً مشکی.
   --------------------------------------------------------------- */

.badge.bg-secondary,
.badge-secondary,
a.badge-secondary,
.icon-box.bg-secondary,
body.dark-mode-active .badge.bg-secondary,
body.dark-mode-active .badge-secondary,
body.dark-mode-active a.badge-secondary,
body.dark-mode-active .icon-box.bg-secondary {
    color: var(--accent-fg) !important;
}

/* ---------------------------------------------------------------
   ۱۳) انیمیشن‌های بیشتر

   همه با transform و opacity کار می‌کنند — تنها دو خاصیتی که مرورگر بدون
   چیدمان دوباره‌ی صفحه انیمیت می‌کند. انیمیت کردن width/height/top روی گوشی
   پرش می‌دهد.

   هر چیزی که اینجا اضافه شود باید به بلوک prefers-reduced-motion انتهای
   همین بخش هم برود.
   --------------------------------------------------------------- */

/* --- ورود ردیف‌های فهرست ---
   تأخیر پلکانی فقط برای ده ردیف اول: بعد از آن کاربر اسکرول کرده و
   دیگر اول فهرست را نمی‌بیند، ولی تأخیرِ بلند باعث می‌شد ردیف‌های پایین
   دیر ظاهر شوند. */
#appCapsule .listview > li {
    animation: rowIn 320ms cubic-bezier(.22, .61, .36, 1) backwards;
}
#appCapsule .listview > li:nth-child(1) { animation-delay: 0ms; }
#appCapsule .listview > li:nth-child(2) { animation-delay: 25ms; }
#appCapsule .listview > li:nth-child(3) { animation-delay: 50ms; }
#appCapsule .listview > li:nth-child(4) { animation-delay: 75ms; }
#appCapsule .listview > li:nth-child(5) { animation-delay: 100ms; }
#appCapsule .listview > li:nth-child(6) { animation-delay: 125ms; }
#appCapsule .listview > li:nth-child(7) { animation-delay: 150ms; }
#appCapsule .listview > li:nth-child(8) { animation-delay: 175ms; }
#appCapsule .listview > li:nth-child(n+9) { animation-delay: 200ms; }

@keyframes rowIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}

/* --- ورود بخش‌ها --- */
#appCapsule > .section,
#appCapsule > .section-title {
    animation: sectionIn 360ms cubic-bezier(.22, .61, .36, 1) backwards;
}
#appCapsule > *:nth-child(2) { animation-delay: 40ms; }
#appCapsule > *:nth-child(3) { animation-delay: 80ms; }
#appCapsule > *:nth-child(n+4) { animation-delay: 120ms; }

/* بخشی که دکمه‌ی شناور دارد انیمیت نمی‌شود: transform یک والد، عنصر
   position:fixed داخلش را از صفحه‌نمایش جدا می‌کند و دکمه تا پایان انیمیشن
   ته صفحه می‌افتاد. */
#appCapsule > .section:has(.fab-button) { animation: none; }

@keyframes sectionIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}

/* --- بازخورد لمس ---
   هر چیزی که کاربر روی آن انگشت می‌گذارد باید کمی فرو برود. */
.btn,
.appBottomMenu .item,
.listview > li > .item,
.listview > li > a,
.preset-card,
.stream-tile,
.icon-pick,
.stream-btn {
    transition: transform 120ms ease, background-color 160ms ease, color 160ms ease;
}

.btn:active,
.listview > li > .item:active,
.listview > li > a:active,
.stream-btn:active { transform: scale(.97); }

.appBottomMenu .item:active .col { transform: scale(.9); }
.appBottomMenu .item .col { transition: transform 140ms ease; }

/* --- ردیف فعال نوار پایین ---
   آیکون کمی بالا می‌آید تا بدون خواندن متن هم معلوم باشد کجایی. */
.appBottomMenu .item i {
    transition: transform 220ms cubic-bezier(.34, 1.56, .64, 1);
}
.appBottomMenu .item.active i {
    transform: translateY(-2px) scale(1.12);
}

/* --- کشوی کناری ---
   ردیف‌ها پشت سر هم می‌آیند؛ بدون این، کشو یکجا ظاهر می‌شود و سنگین
   به نظر می‌رسد. */
.offcanvas.show .listview > li {
    animation: sideIn 300ms cubic-bezier(.22, .61, .36, 1) backwards;
}
.offcanvas.show .listview > li:nth-child(1) { animation-delay: 40ms; }
.offcanvas.show .listview > li:nth-child(2) { animation-delay: 70ms; }
.offcanvas.show .listview > li:nth-child(3) { animation-delay: 100ms; }
.offcanvas.show .listview > li:nth-child(4) { animation-delay: 130ms; }
.offcanvas.show .listview > li:nth-child(5) { animation-delay: 160ms; }
.offcanvas.show .listview > li:nth-child(6) { animation-delay: 190ms; }
.offcanvas.show .listview > li:nth-child(n+7) { animation-delay: 220ms; }

.offcanvas.show .profileBox {
    animation: sideIn 320ms cubic-bezier(.22, .61, .36, 1) backwards;
}

@keyframes sideIn {
    from { opacity: 0; transform: translateX(24px); }
    to   { opacity: 1; transform: none; }
}
html[dir="ltr"] .offcanvas.show .listview > li,
html[dir="ltr"] .offcanvas.show .profileBox {
    animation-name: sideInLtr;
}
@keyframes sideInLtr {
    from { opacity: 0; transform: translateX(-24px); }
    to   { opacity: 1; transform: none; }
}

/* --- مودال --- */
.modal.fade .modal-dialog {
    transition: transform 260ms cubic-bezier(.22, .61, .36, 1), opacity 200ms ease;
    transform: scale(.94) translateY(10px);
    opacity: 0;
}
.modal.show .modal-dialog {
    transform: none;
    opacity: 1;
}

/* --- ورود تصویرها ---
   عکسی که دیر می‌رسد به‌جای پریدن، محو می‌شود. */
.imaged,
.card-img-top {
    animation: imgIn 400ms ease backwards;
}
@keyframes imgIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* --- تغییر پالت --- *
   وقتی رنگ‌ها عوض می‌شوند، پرش ناگهانی بد است. فقط روی سطح‌های بزرگ. */
body,
#appCapsule,
.appHeader,
.appBottomMenu,
.wide-block,
.card {
    transition: background-color 220ms ease, color 220ms ease, border-color 220ms ease;
}

/* --- نوار درصد نظرسنجی --- */
:is(.poll-modal, .dash-poll) .poll-bar {
    transition: width 420ms cubic-bezier(.22, .61, .36, 1);
}

@media (prefers-reduced-motion: reduce) {

    /* فقط حرکت خاموش می‌شود، نه ترنسفورم.
       نسخه‌ی قبلی همین بلوک روی .appHeader و .appBottomMenu هم
       «transform: none !important» می‌گذاشت. آن دو نوار position:fixed هستند و
       با left:50% + translateX(-50%) وسط قاب دسکتاپ می‌نشینند — یعنی ترنسفورمشان
       چیدمان است، نه انیمیشن. نتیجه این بود که برای هرکس که در سیستم‌عاملش
       کاهش حرکت روشن بود، هر دو نوار نصف عرض قاب به کنار می‌پریدند.
       پس اینجا فقط animation و transition برداشته می‌شوند. */
    #appCapsule .listview > li,
    #appCapsule > .section,
    #appCapsule > .section-title,
    .offcanvas.show .listview > li,
    .offcanvas.show .profileBox,
    .imaged,
    .card-img-top,
    .modal.fade .modal-dialog,
    .modal.show .modal-dialog,
    .appBottomMenu .item i,
    .appBottomMenu .item .col,
    .btn,
    .listview > li > .item,
    .listview > li > a,
    .preset-card,
    .stream-tile,
    .icon-pick,
    .stream-btn,
    .poll-modal .poll-bar,
    body,
    #appCapsule,
    .appHeader,
    .appBottomMenu,
    .wide-block,
    .card {
        animation: none !important;
        transition: none !important;
    }

    /* ترنسفورم فقط جایی صفر می‌شود که خودش حرکتِ تزئینی بوده:
       بازخورد لمس و بالا آمدن آیکون ردیف فعال. */
    .btn:active,
    .listview > li > .item:active,
    .listview > li > a:active,
    .stream-btn:active,
    .preset-card:active .preset-swatch,
    .stream-tile:active .stream-tile-art,
    .appBottomMenu .item:active .col,
    .appBottomMenu .item.active i,
    .poll-modal .poll-option:active,
    #send-chat-btn:active {
        transform: none !important;
    }
}
/* ---------------------------------------------------------------
   ۱۴) کشوی کناری

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

.offcanvas {
    background: var(--surface);
    color: var(--fg);
}

.offcanvas .profileBox,
body.dark-mode-active .offcanvas .profileBox {
    background: var(--accent);
    color: var(--accent-fg);
}
.offcanvas .profileBox strong,
.offcanvas .profileBox .text-muted,
.offcanvas .profileBox .close-sidebar-button {
    color: var(--accent-fg) !important;
}
.offcanvas .profileBox .text-muted { opacity: .75; }

.sidebar-avatar {
    width: 40px;
    height: 40px;
    border-radius: var(--radius);
    background: var(--accent-fg);
    color: var(--accent);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 17px;
}

.offcanvas .listview .icon-box,
body.dark-mode-active .offcanvas .listview .icon-box {
    background: var(--surface-alt) !important;
    color: var(--fg-muted);
    border-radius: var(--radius-sm);
}

.offcanvas .listview .item.is-here .icon-box {
    background: var(--accent) !important;
    color: var(--accent-fg);
}
.offcanvas .listview .item.is-here .in { color: var(--accent); font-weight: 700; }

.offcanvas .listview .item,
body.dark-mode-active .offcanvas .listview .item { color: var(--fg); }


/* ---------------------------------------------------------------
   ۱۵) انتخاب آیکون (صفحه‌ی منو)
   --------------------------------------------------------------- */

.icon-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
    gap: 6px;
    max-height: 168px;
    overflow-y: auto;
    padding: 4px 2px;
}

.icon-pick {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--fg-muted);
    font-size: 18px;
    cursor: pointer;
    padding: 0;
}

.icon-pick.is-on {
    border-color: var(--accent);
    background: var(--accent);
    color: var(--accent-fg);
}

.nav-off { opacity: .5; text-decoration: line-through; }


/* ---------------------------------------------------------------
   ۱۶) اعلان همگانی
   --------------------------------------------------------------- */

.notify-stat {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    background: var(--surface-alt);
    border-radius: var(--radius);
}
.notify-stat b     { font-size: 26px; color: var(--fg); display: block; line-height: 1.2; }
.notify-stat span  { font-size: 12px; color: var(--fg-muted); }
.notify-stat i     { font-size: 28px; color: var(--accent); }


/* ---------------------------------------------------------------
   ۱۷) ردیف آیکون در تنظیمات کلی
   --------------------------------------------------------------- */

.icon-row {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 12px 0;
    border-bottom: 1px solid var(--line);
}
.icon-row:last-of-type { border-bottom: 0; }

.icon-row-art {
    flex: none;
    width: 56px;
    height: 56px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: var(--surface-alt);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.icon-row-art img, .icon-row-art video { width: 100%; height: 100%; object-fit: cover; }
.icon-row-art i   { font-size: 22px; color: var(--fg-muted); }

.icon-row-in { flex: 1; min-width: 0; }

/* ورودی فایل در قالب استایل ندارد و خام دیده می‌شود. */
input[type="file"].form-control,
body.dark-mode-active input[type="file"].form-control {
    padding: 8px 10px;
    height: auto;
    background: var(--surface-alt);
    border: 1px solid var(--line);
    color: var(--fg-muted);
    font-size: 12px;
}


/* ---------------------------------------------------------------
   ۱۸) تب‌های صفحه‌ی کاربران
   --------------------------------------------------------------- */

.nav-tabs.style1 .nav-link,
body.dark-mode-active .nav-tabs.style1 .nav-link {
    color: var(--fg-muted);
    border-bottom: 2px solid transparent;
    background: none;
}

.nav-tabs.style1 .nav-link.active,
body.dark-mode-active .nav-tabs.style1 .nav-link.active {
    color: var(--accent);
    border-bottom-color: var(--accent);
    background: none;
}

.nav-tabs.style1 .nav-link .badge { margin-inline-start: 4px; }

/* توضیح وضعیت اعلان زیر فهرست کشو. وقتی سوییچ خاموش و غیرفعال است، بدون
   این جمله معلوم نیست چرا کار نمی‌کند. */
.push-note {
    margin: 4px 16px 0;
    font-size: 11px;
    line-height: 1.8;
    color: var(--fg-muted);
}
.push-note:empty { display: none; }

/* کادر پروفایل کشو.
   قالب آن را position:fixed با left:0 گذاشته و جایش را با margin-top روی
   بدنه باز کرده. آن ترفند فقط وقتی می‌خواند که کشو چسبیده به لبه‌ی
   صفحه‌نمایش باشد؛ داخل قاب وسط‌چینِ دسکتاپ، کادر از کشو کنده می‌شد و
   می‌پرید گوشه‌ی صفحه. اینجا به جریان عادی برمی‌گردد و بالای کشو می‌چسبد. */
#sidebarPanel .profileBox,
body.dark-mode-active #sidebarPanel .profileBox {
    position: sticky;
    top: 0;
    left: auto;
    right: auto;
    width: 100%;
}
#sidebarPanel .profileBox::before { display: none; }
#sidebarPanel .offcanvas-body { margin-top: 0; }

/* عنوان بخش.
   قالب این عنوان را داخل .section می‌گذارد که ۱۶ پیکسل پدینگ افقی دارد.
   وقتی مستقیم زیر #appCapsule بنشیند آن پدینگ را ندارد و عنوان به لبه‌ی
   صفحه می‌چسبد، در حالی که محتوای زیرش ۱۶ پیکسل تورفته است. */
.section-title {
    padding-left: 16px;
    padding-right: 16px;
}

/* .section (بدون full) خودش ۱۶ پیکسل پدینگ دارد؛ عنوان داخلش نباید دوباره بگیرد. */
.section:not(.full) > .section-title {
    padding-left: 0;
    padding-right: 0;
}

/* ---------------------------------------------------------------
   ۱۹) فاصله از نوار پایین

   قالب .fab-button.bottom-center را ۱۶ پیکسل از کف می‌گذارد، در حالی که
   نوار پایین ۵۶ پیکسل ارتفاع دارد — دکمه دقیقاً پشت نوار می‌افتاد.
   --------------------------------------------------------------- */

.fab-button.bottom-center,
.fab-button.bottom-right,
.fab-button.bottom-left {
    bottom: calc(56px + 16px);
    margin-bottom: env(safe-area-inset-bottom);
}


/* ---------------------------------------------------------------
   ۲۰) ردیف‌های مدیریت پیام
   --------------------------------------------------------------- */

.comment-block .item .comment-header .title,
body.dark-mode-active .comment-block .item .comment-header .title {
    color: var(--fg);
    font-size: 13px;
    margin: 0;
}

.comment-block .item .comment-header .time,
body.dark-mode-active .comment-block .item .comment-header .time {
    color: var(--fg-muted);
    font-size: 11px;
}

.comment-block .item .text,
body.dark-mode-active .comment-block .item .text { color: var(--fg); }

.comment-block .item {
    background: var(--surface-alt);
    border-radius: var(--radius);
    padding: 10px 12px;
    margin-bottom: 10px;
}

.comment-footer.stream-actions { justify-content: flex-start; }

/* دکمه‌ی تأیید همان شکل بقیه را دارد، فقط رنگش معنایی است. */
.stream-btn-ok        { color: var(--ok); }
.stream-btn-ok:hover,
.stream-btn-ok:focus  { background: color-mix(in srgb, var(--ok) 15%, transparent); }


/* ---------------------------------------------------------------
   ۲۱) استوری
   --------------------------------------------------------------- */

/* نام و دکمه‌ی بستن روی تصویر تیره ناپیدا می‌شدند. یک سایه‌ی ملایم از بالا
   خوانا نگهشان می‌دارد بدون اینکه تصویر را بپوشاند. */
.modal.stories .modal-header {
    background: linear-gradient(to bottom, rgba(0, 0, 0, .55), transparent);
    position: relative;
    z-index: 3;
}
.modal.stories .modal-header h4,
.modal.stories .modal-header .close-stories,
body.dark-mode-active .modal.stories .modal-header h4,
body.dark-mode-active .modal.stories .modal-header .close-stories {
    color: #FFF;
    text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}
.modal.stories .modal-header .close-stories { font-size: 24px; }

.modal.stories .story-bar {
    position: absolute;
    top: 8px;
    left: 12px;
    right: 12px;
    height: 3px;
    border-radius: 3px;
    background: rgba(255, 255, 255, .35);
    overflow: hidden;
    z-index: 4;
}
.modal.stories .story-bar span {
    display: block;
    width: 0;
    height: 100%;
    background: #FFF;
}

/* حلقه‌ی استوریِ دیده‌شده کمرنگ می‌شود — همان قراردادی که همه می‌شناسند. */
.story-block .splide__slide a .imaged {
    border: 2px solid var(--accent);
    padding: 2px;
    transition: border-color .2s, opacity .2s;
}
.story-block .splide__slide a.story-seen .imaged {
    border-color: var(--line);
    opacity: .65;
}


/* ---------------------------------------------------------------
   ۲۲) نوار پیشنهاد (اعلان و نصب)
   --------------------------------------------------------------- */

.prompt-sheet { position: fixed; inset: 0; z-index: 13000; }
.prompt-dim { position: absolute; inset: 0; background: rgba(0, 0, 0, .45); opacity: 0; transition: opacity .3s ease; }
.prompt-card {
    position: absolute; left: 50%; bottom: 0;
    width: min(var(--frame, 480px), 100%);
    transform: translate(-50%, 100%);
    transition: transform .35s cubic-bezier(.22, .61, .36, 1);
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 10px 20px calc(20px + env(safe-area-inset-bottom));
    background: var(--surface);
    border-radius: 24px 24px 0 0;
    box-shadow: 0 -8px 30px rgba(0, 0, 0, .18);
    text-align: center;
}
.prompt-sheet.is-on .prompt-dim { opacity: 1; }
.prompt-sheet.is-on .prompt-card { transform: translate(-50%, 0); }
.prompt-grab { width: 40px; height: 5px; border-radius: 3px; background: var(--line); margin-bottom: 12px; }
.prompt-icon { width: 76px; height: 76px; border-radius: 18px; object-fit: cover; box-shadow: 0 4px 14px rgba(0, 0, 0, .15); }
.prompt-name { font-size: 18px; font-weight: 800; color: var(--fg); margin-top: 8px; }
.prompt-text { font-size: 14px; line-height: 1.9; color: var(--fg-muted); margin-bottom: 12px; }
.prompt-text i { color: var(--accent); font-size: 16px; }
.prompt-card .btn { margin: 0; }
.prompt-close, body.dark-mode-active .prompt-close { background: var(--surface-alt); color: var(--fg); border: 0; }
/* ---------------------------------------------------------------
   ۲۳) توست

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

   قاعده روی خود .toast-box است، پس همه‌ی توست‌های پروژه — بدون استثنا —
   همین شکل را می‌گیرند.
   --------------------------------------------------------------- */

.toast-box,
body.dark-mode-active .toast-box {
    top: auto !important;
    bottom: calc(56px + 32px);
    /* وسط‌چین با left/right صفر و margin خودکار، نه left:50%.
       عرضِ خودکارِ یک عنصر fixed با left:50% فقط تا لبه‌ی راست جا دارد —
       یعنی نصف صفحه — و پیام بلند در ستونی ۱۸۸ پیکسلی می‌شکست. */
    left: 0 !important;
    right: 0 !important;
    width: fit-content !important;
    max-width: min(var(--frame, 480px) - 48px, calc(100% - 48px));
    min-height: 0;
    margin: 0 auto env(safe-area-inset-bottom) auto;

    padding: 10px 18px;
    border-radius: 999px;
    background: rgba(28, 28, 30, .94);
    color: #FFF;
    font-size: 12px;
    line-height: 1.7;
    text-align: center;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .28);

    opacity: 0;
    transform: translateY(12px);
    transition: opacity .22s ease, transform .22s ease;
    pointer-events: none;   /* نباید جلوی کلیک روی چیزی که زیرش است را بگیرد */
}

.toast-box.show,
body.dark-mode-active .toast-box.show {
    opacity: 1;
    transform: none;
}

/* صفحه‌هایی که دکمه‌ی شناور وسطِ پایین دارند (مدیریت پیام‌ها): توست بالای دکمه
   می‌نشیند، نه رویش. وقتی دکمه پنهان است، جای معمولی‌اش را دارد. */
body:has(.fab-button.bottom-center:not([style*="none"])) .toast-box {
    bottom: calc(56px + 16px + 56px + 16px);
}

/* body.rtl-mode عمداً در فهرست است: قاعده‌ی راست‌چینِ قالب ۲۰ پیکسل padding-left
   می‌گذارد و یک واحد ویژگی بیشتر دارد — همان فاصله‌ی بعد از آخرین کلمه. */
.toast-box .in,
body.rtl-mode .toast-box .in,
body.dark-mode-active .toast-box .in {
    display: block;
    padding: 0;
}

.toast-box .text,
body.dark-mode-active .toast-box .text {
    color: #FFF;
    font-size: 12px;
}

/* توست اندروید دکمه ندارد؛ خودش می‌رود. */
.toast-box .close-button,
.toast-box .btn {
    display: none !important;
}

/* نسخه‌ی سیستم پایین صفحه‌ی مدیریت */
.admin-version {
    text-align: center;
    font-size: 11px;
    color: var(--fg-muted);
    padding: 16px 0 8px;
    font-family: ui-monospace, Consolas, monospace;
}

/* Safari روی iPhone هر فیلدی که نوشته‌اش کمتر از ۱۶ پیکسل باشد را هنگام تایپ
   بزرگ‌نمایی می‌کند و صفحه بعدش همان‌طور بزرگ می‌ماند. روی صفحه‌های لمسی
   نوشته‌ی فیلدها ۱۶ پیکسل می‌شود؛ این به‌جای maximum-scale است که بزرگ‌نمایی
   با دو انگشت را برای همه می‌بست. */
@media (hover: none) and (pointer: coarse) {
    input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=color]),
    textarea, select, .form-control, .form-select {
        font-size: 16px !important;
    }
}

/* ثبت‌نام در صفحه‌ی ورود یک دکمه‌ی کامل است، نه یک پیوند کوچک؛ تازه‌واردها
   باید ببینند که اول ثبت‌نام لازم است. */
.auth-register {
    margin: 0 0 14px;
    font-weight: 800;
    font-size: 15px;
    border-width: 2px;
}
.auth-page .auth-alt { margin-bottom: 8px; }

/* تنظیمات داشبورد: تصویر اسلاید پهن است، نه مربع؛ عنوان و تعداد هر بخش کنار هم. */
.listview .item img.image.dash-thumb { width: 72px !important; min-width: 72px !important; height: 40px !important; object-fit: cover; border-radius: 8px !important; }
.dash-row { display: grid; grid-template-columns: 1fr 88px; gap: 10px; align-items: end; }

/* سربرگ هر اسلایدر در تنظیمات داشبورد: نام و شکل و سرعت، و دکمه‌هایش کنارش. */
.section-title.dash-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.section-title.dash-head small { display: block; font-size: 11px; font-weight: 400; color: var(--fg-muted); margin-top: 2px; }
/* اسلایدر کارتی داشبورد: گوشه‌ی گرد و سایه‌ی نرم، با فاصله از لبه‌ها. */
.dash-box .splide__slide img { border-radius: var(--radius, 14px); box-shadow: 0 6px 18px rgba(0, 0, 0, .12); aspect-ratio: 2 / 1; object-fit: cover; }
/* نقطه‌های صفحه‌ی اسلایدر کارتی، زیر کارت‌ها. */
.dash-box .splide__pagination {
    position: relative; inset: auto; transform: none; width: auto;
    display: flex; justify-content: center; margin: 10px 0 0; padding: 0;
}
.dash-box .splide__pagination button { background: var(--line); width: 7px; height: 7px; margin: 0 3px; }
.dash-box .splide__pagination button.is-active { background: var(--accent); transform: scale(1.3); }

/* مسابقه‌ی خاموش: نشان ساعت‌شنی با رنگ خنثی. */
.quiz-result-mark--off { background: var(--surface-alt); color: var(--fg-muted); font-size: 34px; }

/* تنظیمات مسابقه: هر سوال با پاسخ درستش زیرش؛ در مودال، دکمه‌ی پاسخ درست کنار هر گزینه. */
.quiz-q-list li { align-items: flex-start; gap: 8px; }
.quiz-q { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quiz-q b { font-weight: 600; line-height: 1.6; }
.quiz-q small { color: var(--ok); font-size: 12px; }
.quiz-opt-row { display: flex; align-items: center; gap: 10px; }
.quiz-opt-row input[type=radio] { width: 20px; height: 20px; flex: none; accent-color: var(--ok); }

/* کلمات محدود: فهرست به‌صورت برچسب با دکمه‌ی حذف؛ نتیجه‌ی آزمایش زیر فرم. */
.wf-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.wf-actions .btn { flex: 1; }
.wf-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.wf-chip {
    display: inline-flex; align-items: center; gap: 2px; padding: 3px 4px 3px 10px;
    border-radius: 999px; background: var(--surface-alt); font-size: 13px;
}
.wf-chip[hidden] { display: none; }
.wf-chip button { border: 0; background: none; color: var(--fg-muted); padding: 0 4px; line-height: 1; font-size: 16px; }
.wf-chip button:hover { color: var(--danger); }
.wf-result { margin-top: 10px; padding: 10px 12px; border-radius: var(--radius, 12px); font-size: 14px; }
.wf-result.ok  { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }
.wf-result.bad { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger); }
.wf-masked { margin-top: 6px; color: var(--fg); direction: rtl; }

/* لوگوی سربرگ صفحه‌ی اصلی، به‌جای نام برنامه. */
.appHeader .pageTitle .header-logo { height: 34px; width: auto; max-width: 60vw; object-fit: contain; display: block; margin: 0 auto; }
.dash-logo-art img { object-fit: contain !important; }

/* اخبار: نشان «جدیدترین» بالای فهرست و برچسب «تازه» برای خبرهای ۶ ساعت اخیر. */
.news-head {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    margin: 4px 16px 12px; font-size: 12px; color: var(--fg-muted);
}
.news-newest {
    display: inline-flex; align-items: center; gap: 4px; padding: 4px 12px; border-radius: 999px;
    background: var(--accent); color: var(--accent-fg); font-weight: 700;
}
.news-fresh {
    display: inline-block; margin-inline-start: 6px; padding: 0 8px; border-radius: 999px;
    background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger);
    font-size: 11px; font-weight: 700; line-height: 18px;
}

/* ---------- بازی‌ها (/games) ----------
   کارت برای هر مسابقه؛ دیدارهای دوطرفه مثل تابلوی امتیاز. رنگ مدال‌ها جزو
   معنای خودشان است، نه تم؛ بقیه از توکن‌های تم. */
#appCapsule { --gold: #d4a017; --silver: #9aa3ad; --bronze: #b0703a; }
.gm-head { position: sticky; top: calc(56px + env(safe-area-inset-top)); z-index: 5; background: var(--bg); padding: 10px 12px 8px; }
.gm-tabs, body.dark-mode-active .gm-tabs { background: var(--surface-alt); border-radius: var(--radius); }
.gm-tabs .nav-item .nav-link { font-size: 13px; padding: 6px 2px; white-space: nowrap; border-radius: calc(var(--radius) - 2px); }
.gm-tabs .nav-item .nav-link.active,
body.dark-mode-active .gm-tabs .nav-item .nav-link.active { background: var(--accent); color: var(--accent-fg); font-weight: 700; }
.gm-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--danger); margin-inline-end: 4px; animation: gm-blink 1.4s infinite; }
.gm-tabs .nav-link.active .gm-dot { background: currentColor; }
@keyframes gm-blink { 50% { opacity: .25; } }

.gm-bar { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.gm-days { flex: 1; min-width: 0; display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; }
.gm-days::-webkit-scrollbar { display: none; }
.gm-days button { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; min-width: 54px; padding: 4px 8px; line-height: 1.35;
    border: 0; border-radius: var(--radius); background: var(--surface); color: var(--fg); font: inherit; }
.gm-days button small { font-size: 10px; color: var(--fg-muted); }
.gm-days button b { font-size: 12px; font-weight: 700; }
.gm-days button.active { background: var(--accent); color: var(--accent-fg); }
.gm-days button.active small { color: inherit; opacity: .85; }
.gm-scope { flex: 0 0 auto; display: flex; padding: 3px; margin-inline-start: auto; border-radius: var(--radius); background: var(--surface); }
.gm-scope button { display: flex; align-items: center; gap: 4px; border: 0; background: none; color: var(--fg-muted); font: inherit; font-size: 12px; padding: 6px 10px; border-radius: calc(var(--radius) - 2px); }
.gm-scope button img { width: 16px; height: 11px; object-fit: cover; border-radius: 2px; }
.gm-scope button.active { background: var(--surface-alt); color: var(--fg); font-weight: 700; }

.gm-body { padding: 4px 12px 16px; }
.gm-title { font-size: 13px; font-weight: 700; color: var(--fg-muted); margin: 16px 4px 8px; }
.gm-card { background: var(--surface); border-radius: var(--radius-lg, 12px); padding: 12px; margin-bottom: 10px; box-shadow: 0 1px 3px rgba(0, 0, 0, .06); }
.gm-card.gm-flush { padding: 0; overflow: hidden; }
.gm-card.is-live { box-shadow: inset 0 0 0 1.5px var(--danger); }
.gm-skel { height: 96px; background: linear-gradient(90deg, var(--surface) 30%, var(--surface-alt) 50%, var(--surface) 70%); background-size: 300% 100%; animation: gm-shine 1.2s infinite linear; }
@keyframes gm-shine { from { background-position: 100% 0; } to { background-position: 0 0; } }

.gm-card-h { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--fg-muted); }
.gm-card-h > span:not([class]) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm-picto { width: 26px; height: 26px; flex: 0 0 auto; border-radius: 7px; background: #fff; padding: 2px; object-fit: contain; }
.gm-name { font-size: 15px; font-weight: 700; color: var(--fg); margin: 10px 0 2px; line-height: 1.6; }
.gm-card-f { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line); font-size: 12px; color: var(--fg-muted); }
.gm-card-f > span:not([class]) { flex: 1; min-width: 0; }
.gm-card-f b { flex: 0 0 auto; font-size: 12px; }
.gm-card-f b.good { color: var(--ok); } .gm-card-f b.bad { color: var(--danger); }
.gm-clock { font-size: 15px; font-weight: 800; color: var(--fg); }

.gm-tag { flex: 0 0 auto; font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 20px; color: #fff; background: var(--fg-muted); }
.gm-tag.live { background: var(--danger); animation: gm-blink 1.4s infinite; }
.gm-tag.gold { background: var(--gold); } .gm-tag.silver { background: var(--silver); } .gm-tag.bronze { background: var(--bronze); }
.gm-tag.medal { background: none; color: var(--gold); padding: 0; }

.gm-board { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px; margin-top: 12px; }
.gm-team { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; text-align: center; font-size: 13px; color: var(--fg); }
.gm-team span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm-team .gm-flag { width: 34px; height: 23px; }
.gm-team.win span { font-weight: 800; }
.gm-team.us span { color: var(--accent); }
.gm-score { display: flex; align-items: center; gap: 6px; font-size: 24px; font-weight: 800; color: var(--fg); }
.gm-score i { font-style: normal; color: var(--fg-muted); font-size: 18px; }
.gm-score span { font-size: 16px; padding: 4px 10px; border-radius: var(--radius); background: var(--surface-alt); }
.gm-score.live b { color: var(--danger); }
.gm-flag { width: 22px; height: 15px; object-fit: cover; border-radius: 3px; box-shadow: 0 0 0 1px var(--line); flex: 0 0 auto; }
.gm-splits { display: flex; justify-content: center; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.gm-splits span { font-size: 11px; padding: 1px 7px; border-radius: 6px; background: var(--surface-alt); color: var(--fg-muted); }

.gm-empty { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 56px 16px; color: var(--fg-muted); text-align: center; }
.gm-empty > i { font-size: 36px; opacity: .6; }

.gm-table, body.dark-mode-active .gm-table { margin: 0; font-size: 13px; color: var(--fg); }
.gm-table th, .gm-table td { text-align: center; vertical-align: middle; padding: 9px 4px; border-color: var(--line); background: none; color: inherit; }
.gm-table th, body.dark-mode-active .gm-table thead th { font-size: 11px; color: var(--fg-muted); font-weight: 600; border-top: 0; }
.gm-table td:first-child { color: var(--fg-muted); width: 28px; }
.gm-table .c { text-align: start; white-space: nowrap; }
.gm-table .gm-flag { margin-inline-end: 8px; vertical-align: -3px; }
.gm-table tr.us td { background: var(--surface-alt); font-weight: 700; color: var(--accent); }
.gm-m { display: inline-block; width: 12px; height: 12px; border-radius: 50%; vertical-align: middle; }
.gm-m.gold { background: var(--gold); } .gm-m.silver { background: var(--silver); } .gm-m.bronze { background: var(--bronze); }

.gm-tally { border-radius: var(--radius-lg, 12px); padding: 14px; margin-top: 6px; background: var(--accent); color: var(--accent-fg); }
.gm-tally-h { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.gm-tally-h span { margin-inline-start: auto; font-size: 12px; font-weight: 700; padding: 2px 10px; border-radius: 20px; background: rgba(255, 255, 255, .22); }
.gm-tally-n { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 12px; }
.gm-tally-n > div { display: flex; flex-direction: column; align-items: center; padding: 8px 0 6px; border-radius: var(--radius); background: rgba(255, 255, 255, .14); }
.gm-tally-n i { width: 10px; height: 10px; border-radius: 50%; }
.gm-tally-n .gold i { background: var(--gold); } .gm-tally-n .silver i { background: var(--silver); } .gm-tally-n .bronze i { background: var(--bronze); }
.gm-tally-n b { font-size: 22px; line-height: 1.3; }
.gm-tally-n small { font-size: 11px; opacity: .85; }
.gm-tally-n .all { padding-top: 12px; }

.gm-winners { list-style: none; margin: 0; padding: 0; }
.gm-winners li { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-top: 1px solid var(--line); }
.gm-winners li:first-child { border-top: 0; }
.gm-winners li > div { display: flex; flex-direction: column; min-width: 0; }
.gm-winners b { font-size: 14px; color: var(--fg); }
.gm-winners small { font-size: 11px; color: var(--fg-muted); }

/* کارت بازی‌ها در داشبورد: همان کارت مدال و کارت مسابقه‌ی صفحه‌ی بازی‌ها. */
.dash-games { padding: 0 16px; }
.dash-games .gm-tally { display: block; text-decoration: none; margin: 0; }
.dash-games .gm-next { margin-top: 10px; }
.dash-games .gm-next .gm-card { display: block; color: inherit; text-decoration: none; }
.dash-gm-links { display: flex; gap: 6px; margin-top: 4px; }
.dash-gm-links .btn { flex: 1; padding-inline: 4px; }

/* کارت خبر داشبورد: عنوان و لید روی تصویر (از مدیریت اخبار). */
.news-card { position: relative; display: block; border-radius: var(--radius-lg, 12px); overflow: hidden; color: #fff; }
.news-card img { display: block; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 0 !important; }
.news-card-in { position: absolute; inset: auto 0 0 0; padding: 40px 14px 12px; background: linear-gradient(to top, rgba(0, 0, 0, .85), rgba(0, 0, 0, .5) 60%, transparent); }
.news-card-in h3 { margin: 0; color: #fff; font-size: 15px; font-weight: 800; line-height: 1.6; }
.news-card-in p { margin: 3px 0 0; color: rgba(255, 255, 255, .85); font-size: 12px; line-height: 1.7; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.news-full h2 { font-size: 18px; font-weight: 800; line-height: 1.7; color: var(--fg); }
.news-full .lead { font-size: 14px; color: var(--fg-muted); font-weight: 600; }
.news-thumb { object-fit: cover; }
.news-preview { display: block; width: 100%; max-height: 160px; object-fit: cover; border-radius: var(--radius); margin: 4px 0 8px; }
.gm-splits span { display: inline-flex; gap: 3px; } .gm-splits span i { font-style: normal; }

/* نظرسنجی در داشبورد: دکمه‌ها همان دکمه‌های نظرسنجی پیام‌رسان‌اند. */
.dash-poll-h { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; color: var(--accent); }
.dash-poll .poll-question { margin: 6px 0 12px; font-size: 15px; font-weight: 700; line-height: 1.7; color: var(--fg); }
.dash-poll .poll-options { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-poll .poll-option.is-busy { opacity: .6; }

/* ---------- پخش زنده (/live) ----------
   پخش‌کننده تمام‌عرض زیر سربرگ، کارت کانال در حال پخش، و فهرست کانال‌ها. */
.live-player { position: relative; width: 100%; aspect-ratio: 16 / 9; background: #000; }
.live-player iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.live-bad { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 32px; opacity: .6; }
.live-now { display: flex; align-items: center; gap: 12px; margin: 12px; padding: 12px; border-radius: var(--radius-lg, 12px); background: var(--surface); box-shadow: 0 1px 3px rgba(0, 0, 0, .06); }
.live-now-in { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.live-now-in b { font-size: 16px; color: var(--fg); }
.live-logo { width: 46px; height: 46px; flex: 0 0 auto; border-radius: 12px; object-fit: contain; background: var(--surface-alt); padding: 4px; }
.live-logo.is-empty { display: flex; align-items: center; justify-content: center; color: var(--fg-muted); font-size: 20px; }
.live-badge { display: inline-flex; align-items: center; gap: 5px; align-self: flex-start; font-size: 11px; font-weight: 700; color: var(--danger); }
.live-badge i { width: 7px; height: 7px; border-radius: 50%; background: var(--danger); animation: gm-blink 1.4s infinite; }
.live-title { font-size: 13px; font-weight: 700; color: var(--fg-muted); margin: 18px 16px 8px; }
.live-list { margin: 0 12px 16px; border-radius: var(--radius-lg, 12px); background: var(--surface); overflow: hidden; }
.live-ch { display: flex; align-items: center; gap: 12px; padding: 10px 12px; color: var(--fg); text-decoration: none; border-top: 1px solid var(--line); }
.live-ch:first-child { border-top: 0; }
.live-ch span { flex: 1; font-size: 14px; font-weight: 600; }
.live-ch .live-logo { width: 38px; height: 38px; border-radius: 10px; }
.live-ch.is-on { background: var(--surface-alt); }
.live-ch.is-on span, .live-ch.is-on > i { color: var(--accent); }
.live-ch > i { font-size: 20px; }
.live-ch:active { background: var(--surface-alt); }

/* اسامی فارسی ورزشکاران (/games-names) */
.gn-filter { display: flex; gap: 6px; }
.gn-filter button { border: 1px solid var(--line); background: var(--surface); color: var(--fg-muted); border-radius: 20px; padding: 5px 12px; font: inherit; font-size: 12px; }
.gn-filter button.active { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.gn-row { display: flex; flex-direction: column; align-items: stretch !important; gap: 4px; padding-top: 8px !important; padding-bottom: 8px !important; }
.gn-row > span { font-size: 11px; color: var(--fg-muted); text-align: left; }
.gn-row .form-control { font-size: 16px; height: 40px; }
.gn-row.is-missing .form-control { border-color: var(--danger); }
.gn-save { position: sticky; bottom: calc(56px + env(safe-area-inset-bottom)); padding: 12px 16px; background: var(--bg); }

/* ---------------------------------------------------------------
   مودال‌ها به شکل برگه‌ی پایین صفحه
   dialogbox (همه‌ی فرم‌ها و پرسش‌ها) از پایین بالا می‌آید، گوشه‌های بالا گرد و
   دستگیره‌ی کوچک بالای آن. قالب dialogbox را وسط صفحه با scale باز می‌کرد و
   transformش !important دارد، پس اینجا هم لازم است. modalbox (تمام‌صفحه)
   از قبل از پایین می‌آمد؛ فقط حرکتش نرم‌تر شد.
   --------------------------------------------------------------- */
body .modal.dialogbox .modal-dialog {
    position: fixed; top: auto; bottom: 0; left: 50%; right: auto;
    width: min(var(--frame, 480px), 100%); max-width: none;
    min-height: 0; margin: 0; display: block; overflow: visible;
    transform: translate(-50%, 100%) !important;
    transition: transform .35s cubic-bezier(.22, .61, .36, 1) !important;
}
body .modal.dialogbox.show .modal-dialog { transform: translate(-50%, 0) !important; }
body .modal.dialogbox .modal-content {
    border-radius: 24px 24px 0 0 !important;
    max-height: calc(100dvh - 40px - env(safe-area-inset-top));
    padding-top: 14px;
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -8px 30px rgba(0, 0, 0, .18);
}
body .modal.dialogbox .modal-content::before {
    content: ""; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
    width: 40px; height: 5px; border-radius: 3px; background: var(--line);
}
body .modal.dialogbox .modal-header .modal-title { font-size: 16px; font-weight: 800; }
body .dialogbox .modal-dialog .modal-content .btn-inline .btn,
body .dialogbox .modal-dialog .modal-content .modal-footer .btn { min-height: 56px; font-size: 15px; }
.modalbox .modal-dialog { transition: transform .4s cubic-bezier(.22, .61, .36, 1) !important; }
.offcanvas.offcanvas-bottom, .action-sheet { border-radius: 24px 24px 0 0; overflow: hidden; }
.offcanvas.offcanvas-bottom { transition: transform .35s cubic-bezier(.22, .61, .36, 1); }/* بوت‌استرپ بعد از پایان محو شدن مودال (۰.۱۵ ثانیه) پنهانش می‌کند؛ هم‌اندازه‌ی لغزش می‌شود تا برگه تا پایین برود. */
.modal.dialogbox.fade { transition: opacity .35s linear; }

/* قالب محتوای مودال را ۳۰۰ پیکسل و ۵۶۰ ارتفاع می‌بست؛ برگه تمام‌عرض است. */
body .modal.dialogbox .modal-dialog .modal-content { max-width: none; width: 100%; }

/* ویرایشگر متن خبر */
.rte { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.rte-bar { display: flex; flex-wrap: wrap; gap: 2px; padding: 4px; border-bottom: 1px solid var(--line); background: var(--surface-alt); }
.rte-bar button { width: 36px; height: 34px; border: 0; border-radius: 8px; background: none; color: var(--fg); font-size: 17px; display: flex; align-items: center; justify-content: center; }
.rte-bar button:active { background: var(--line); }
.rte-area { min-height: 160px; max-height: 40vh; overflow-y: auto; padding: 10px 12px; font-size: 16px; line-height: 1.9; color: var(--fg); outline: none; }
.rte-area h3 { font-size: 17px; font-weight: 800; margin: 6px 0; }
.rte-area ul, .rte-area ol { padding-inline-start: 22px; }
/* انتخاب فایل (spa.js، filePickers): دکمه‌ی خام مرورگر پنهان، input نامرئی روی دکمه. */
.file-pick {
    position: relative; display: flex; align-items: center; gap: 10px;
    min-height: 48px; padding: 6px 8px 6px 14px; margin: 0;
    border: 1.5px dashed var(--line); border-radius: var(--radius);
    background: var(--surface); color: var(--fg-muted); cursor: pointer;
    transition: border-color .15s ease, background .15s ease;
}
.file-pick input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.file-pick > i { font-size: 20px; color: var(--accent); }
.file-pick > span { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: ltr; text-align: right; }
.file-pick > b { flex: 0 0 auto; font-size: 13px; font-weight: 700; padding: 7px 14px; border-radius: calc(var(--radius) - 4px); background: var(--accent); color: var(--accent-fg); }
.file-pick:active, .file-pick:hover { border-color: var(--accent); }
.file-pick.has-file { border-style: solid; border-color: var(--accent); color: var(--fg); }

/* لینک‌های کارتی داشبورد: قاعده‌ی a:hover قالب رنگ متن را accent می‌کرد و
   روی کارت مدال (که خودش accent است) نوشته‌ها ناپدید می‌شدند. */
.dash-games .gm-tally:hover, .dash-games .gm-tally:focus, .dash-games .gm-tally:active { color: var(--accent-fg); }
.dash-games .gm-next .gm-card:hover, .dash-games .gm-next .gm-card:focus { color: var(--fg); }
.news-card:hover, .news-card:focus { color: #fff; }

/* تب‌های صفحه‌ی بازی‌ها: انتخاب‌شده کم‌رنگ از رنگ اصلی، نه یک قرص تیره. رنگ
   پررنگ فقط برای روز انتخاب‌شده می‌ماند تا دو انتخاب با هم رقابت نکنند. */
.nav-tabs.capsuled.gm-tabs, body.dark-mode-active .nav-tabs.capsuled.gm-tabs { background: var(--surface); border: 1px solid var(--line); padding: 3px; }
.nav-tabs.capsuled.gm-tabs .nav-item .nav-link { margin: 0 !important; height: 34px; color: var(--fg-muted); font-weight: 600; }
.nav-tabs.capsuled.gm-tabs .nav-item .nav-link.active,
body.dark-mode-active .nav-tabs.capsuled.gm-tabs .nav-item .nav-link.active {
    background: color-mix(in srgb, var(--accent) 14%, var(--surface));
    color: var(--accent); font-weight: 800; box-shadow: none;
}
.nav-tabs.capsuled.gm-tabs .nav-link.active .gm-dot { background: var(--danger); }
.gm-scope { border: 1px solid var(--line); }
.gm-scope button.active { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent); }
.gm-days button { border: 1px solid var(--line); }
.gm-days button.active { border-color: var(--accent); }.file-pick input[type="file"], body.dark-mode-active .file-pick input[type="file"].form-control { height: 100%; padding: 0; border: 0; }

/* کیبورد داخلی (vkb.js) — بالای مودال‌ها (z-index آن‌ها ۱۲۰۰۰ است). */
.vkb {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 14000;
    display: flex; flex-direction: column; gap: 6px;
    padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
    background: var(--surface-alt); border-top: 1px solid var(--line);
    box-shadow: 0 -6px 20px rgba(0, 0, 0, .08);
    user-select: none; -webkit-user-select: none; touch-action: manipulation;
}
.vkb[hidden] { display: none; }
.vkb-row { display: flex; gap: 4px; justify-content: center; }
.vkb-key {
    flex: 1 1 0; min-width: 0; max-width: 64px; height: 46px; padding: 0;
    border: 0; border-radius: 9px; background: var(--surface); color: var(--fg);
    font: inherit; font-size: 19px; line-height: 1;
    box-shadow: 0 1px 0 var(--line);
    display: flex; align-items: center; justify-content: center;
}
.vkb-key.is-down { background: var(--line); transform: scale(.94); }
.vkb-back, .vkb-num, .vkb-abc, .vkb-lang, .vkb-zwnj, .vkb-shift { flex-grow: 1.4; max-width: 96px; font-size: 13px; color: var(--fg-muted); }
.vkb-shift.is-on { background: var(--accent); color: var(--accent-fg); }
.vkb-space { flex-grow: 4; max-width: none; font-size: 13px; color: var(--fg-muted); }
.vkb-enter { flex-grow: 1.4; max-width: 96px; background: var(--accent); color: var(--accent-fg); }
.vkb-back i, .vkb-enter i, .vkb-shift i { font-size: 20px; }
@media (min-width: 768px) { .vkb { width: var(--frame) !important; max-width: 100%; left: 50% !important; right: auto !important; --vkb-x: -50%; } }
/* باز و بسته: کیبورد از پایین بالا می‌آید و نوار پیام و برگه‌ی مودال هم‌زمان با آن جابه‌جا می‌شوند. */
.vkb { transform: translate(var(--vkb-x, 0), 100%); transition: transform .26s cubic-bezier(.22, .61, .36, 1); }
.vkb.is-open { transform: translate(var(--vkb-x, 0), 0); }
.chatFooter { transition: bottom .26s cubic-bezier(.22, .61, .36, 1); }
body .modal.dialogbox .modal-dialog { transition: transform .35s cubic-bezier(.22, .61, .36, 1), bottom .26s cubic-bezier(.22, .61, .36, 1) !important; }
@media (prefers-reduced-motion: reduce) { .vkb, .chatFooter { transition: none; } }/* وقتی کیبورد باز است فاصله‌ی امن پایین iPhone را خود کیبورد دارد؛ نوار پیام و
   برگه‌ی مودال که رویش نشسته‌اند نباید دوباره همان فاصله را بگذارند. */
body.vkb-open .chatFooter { padding-bottom: 0; }
body.vkb-open .modal.dialogbox .modal-content { padding-bottom: 0 !important; }
