﻿/* ==========================================================================
   zadbyan-overrides.css
   --------------------------------------------------------------------------
   تخصيصات المشروع التي لا مقابل لها في الـ template.

   ⚠️ لا تُحرَّر css/styles.css: هو مرآة لـ zadbyan design template/zadbyan/styles.css
   وأي تعديل هناك يُفقد أداةَ docs/tools/design-parity.ps1 معناها. كل تخصيص هنا.

   يُحمَّل بعد styles.css مباشرةً في App.razor.

   أقسامٌ غائبة من الترقيم (2 و4 و10 و11 و14 و15): كانت للإطار القديم، أي
   InnerLayout وشريطَيه الجانبي والعلوي، وحُذفت معه في المرحلة 10 لأن لا عنصر
   حيّاً يطابق محدِّداتها. انظر docs/ADMIN-REDESIGN-PLAN.md.
   ========================================================================== */

/* ==========================================================================
   1) إصلاح أدوات bootstrap المنطقية في RTL
   --------------------------------------------------------------------------
   التطبيق يحمّل نسختَي bootstrap معاً بمنطق RTL متعاكس:

     libs/bootstrap/css/bootstrap.rtl.css   ->  .start-0 { right: 0 !important }
     global.css  (حزمة ABP، نسخة LTR)       ->  .start-0 { left:  0 !important }

   وهما خاصّيتان مختلفتان، فلا تلغي إحداهما الأخرى مهما كان الترتيب: يجتمع
   left و right على العنصر الواحد فيمتدّ من الحافّة إلى الحافّة.

   الأثر المقيس على /StudentDashboard قبل الإصلاح:
     i.bi-search        عرضه 356px مطابقاً لعرض حقل البحث كلّه
     elementFromPoint(وسط الحقل)  -->  I.bi   لا INPUT
   أي أن حقل البحث كان لا يستقبل النقر إطلاقاً. وشارة الصحّ على صورة الطالب
   كانت تظهر في الزاوية المقابلة لما يقصده end-0.

   القاعدة أدناه تُعيد المعنى المنطقي: في RTL تكون start يميناً وend يساراً،
   وتُصفّر الخاصّية المضادّة صراحةً حتى لا يبقى العنصر ممتدّاً.
   ========================================================================== */

[dir="rtl"] .start-0 {
    right: 0 !important;
    left: auto !important;
}

[dir="rtl"] .start-50 {
    right: 50% !important;
    left: auto !important;
}

[dir="rtl"] .start-100 {
    right: 100% !important;
    left: auto !important;
}

[dir="rtl"] .end-0 {
    left: 0 !important;
    right: auto !important;
}

[dir="rtl"] .end-50 {
    left: 50% !important;
    right: auto !important;
}

[dir="rtl"] .end-100 {
    left: 100% !important;
    right: auto !important;
}

/* ==========================================================================
   3) صور بطاقات الدورات
   --------------------------------------------------------------------------
   ImageURL يأتي من قاعدة البيانات، وقد يكون الملف مفقوداً على بيئة بعينها.
   القياس على /StudentDashboard: صورتان من صورتين بـ naturalWidth = 0، أي أن
   المتصفّح يرسم أيقونة «صورة مكسورة» داخل البطاقة.

   خلفية بهوية المنصّة تحت الصورة تعالج الحالتين معاً: تظهر ريثما تُحمَّل
   الصورة، وتبقى مكانها إن لم تصل — فيرى المستخدم مساحة مقصودة لا عطلاً.
   ========================================================================== */

.course-img {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
}

/* ==========================================================================
   5) الـ CSS المعزول ووسوم حزمه
   --------------------------------------------------------------------------
   كل ملفات *.razor.css في التطبيق والوحدات المرجعية تعمل، لكنها كانت لا تصل
   إلى المتصفّح إطلاقاً قبل هذه الموجة: وسما الحزمتين كانا مفقودَين من App.razor
   رغم أن الملفين يُخدَمان بـ 200. أُضيفا الآن:

     TS.ZadByan.Blazor.styles.css          حزمة الـ host
     TS.ZadByan.Blazor.Client.styles.css   حزمة مشروع Client المستقلّة

   وحزمة وحدة Volo.BasicTheme تصل عبر @import داخل حزمة الـ host، فقواعدها
   المعزولة تعمل هي الأخرى.

   ملاحظة: قاعدة .header-backdrop حُذفت من هنا. كانت لعنصر يرسمه MainLayout
   حين تُفتح قائمة، ثم استُبدل ذلك النهج بتفويض على document في
   js/zadbyan-header.js — فالإغلاق بالنقر خارجاً صار بلا عنصر خلفية أصلاً،
   وبقيت القاعدة كوداً ميّتاً لا يطابق شيئاً.
   ========================================================================== */

/* ==========================================================================
   6) قائمة المستخدم ومبدّل اللغة بمظهر الـ template
   --------------------------------------------------------------------------
   التصميم يرسمهما بـ user-menu-trigger و user-dropdown و lang-selector و
   lang-dropdown-menu. والمشروع يبنيهما عبر <NavToolbar /> الذي يركّب مكوّنَي
   ABP: LoginDisplay و LanguageSwitch، وكلاهما يخرج بنية Blazorise BarDropdown.

   القرار: إعادة تنسيق لا استبدال. المكوّنان مكرّران في أربعة ملفات (نسخة
   Server ونسخة WebAssembly لكلٍّ)، ومنطقهما ليس شكلاً: تبديل الثقافة برابط
   Abp/Languages/Switch، وعناصر قائمة المستخدم من StandardMenus.User باحترام
   الصلاحيات، واسم الـ tenant. إعادة كتابتها تعني نسخ ذلك المنطق أربع مرات
   وكسر تسجيل الخروج والصلاحيات مقابل شكلٍ يُنال بالتنسيق وحده.

   البنية المقيسة من الـ DOM الحيّ لا من الافتراض:
     .header-utils
       .nav-item                 <-- language: يحوي span.lang-globe
         a.nav-link.dropdown-toggle
         .dropdown-menu > a.dropdown-item
       .nav-item.dropdown        <-- user menu
         a.nav-link.dropdown-toggle
         .dropdown-menu > a.dropdown-item ... .dropdown-divider ... a.dropdown-item

   القيم منقولة حرفياً من styles.css الخاصّة بالتصميم.
   ========================================================================== */

.header-utils > .nav-item {
    position: relative;
}

/* زرّ قائمة المستخدم — قيم .user-menu-trigger */
.header-utils > .nav-item > .nav-link.dropdown-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px 6px 14px;
    border: none;
    border-radius: 999px;
    background: var(--gray-100);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--gray-900);
    text-decoration: none;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
}

    .header-utils > .nav-item > .nav-link.dropdown-toggle:hover,
    .header-utils > .nav-item > .nav-link.dropdown-toggle:focus {
        background: var(--primary-light);
        color: var(--primary-dark);
    }

/* مبدّل اللغة — قيم .lang-selector. يُميَّز بوجود .lang-globe داخله لأن
   العنصرين يخرجان بنفس الأصناف تماماً */
.header-utils > .nav-item:has(.lang-globe) > .nav-link.dropdown-toggle {
    background: transparent;
    padding: 8px 12px;
    border-radius: var(--radius);
    font-weight: 500;
    color: #1f2d3d;
}

/* اللوحة المنسدلة — قيم .user-dropdown و .lang-dropdown-menu */
.header-utils .dropdown-menu {
    margin-top: 8px;
    padding: 8px 0;
    min-width: 200px;
    background: var(--white);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    border: 1px solid rgba(0, 0, 0, 0.08);
    /* ⚠️ حزام أمان في RTL: القائمة تُثبَّت على جهة، وأي اتّساع يدفعها خارج
       الشاشة على الأجهزة الضيّقة. القياس على 360px يعطيها 200px داخل الحدّ،
       والقيد يمنع تجاوزها إن طال نصّ عنصر مستقبلاً. */
    max-width: calc(100vw - 2rem);
}

.header-utils .dropdown-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 20px;
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--gray-900);
    text-decoration: none;
    text-align: right;
    transition: background 0.15s, color 0.15s;
}

    .header-utils .dropdown-item:hover,
    .header-utils .dropdown-item:focus {
        background: var(--primary-light);
        color: var(--primary-dark);
    }

    /* تسجيل الخروج آخر عنصر دائماً — قيم .user-dropdown-logout */
    .header-utils .dropdown-item:last-child {
        color: #dc2626;
        font-weight: 600;
    }

.header-utils .dropdown-divider {
    height: 1px;
    margin: 8px 0;
    border: 0;
    background: var(--gray-300);
    opacity: 1;
}

/* ==========================================================================
   7) هياكل التحميل
   --------------------------------------------------------------------------
   تشغل مكان المحتوى قبل وصوله. لا وجود لها في الـ template لأنه صفحات ثابتة
   بلا جلب، فهي تخصيص مشروع خالص.

   القياس الذي استدعاها: فجوة 1020ms بلا محتوى عند كل تنقّل إلى لوحة الطالب،
   وفيها تُعرض رسالة «لا توجد دورات» لطالب مسجَّل في دورتين.

   ⭐ الأبعاد مقصودة لتطابق المحتوى النهائي — صورة البطاقة 200px مثل
   .course-img — فلا يقفز التخطيط عند الاستبدال ولا يرتفع CLS.
   ========================================================================== */

/* ⭐ الوميض بـ transform على عنصر زائف لا بـ background-position على العنصر:
   تحريك background-position يُجبر المتصفّح على إعادة الطلاء كل إطار، وهذه
   الصفحة يُقاس على خيطها الرئيسي إسقاطُ إطارات أصلاً — فـ transform يجري على
   الـ compositor بلا طلاء. */
.skel {
    position: relative;
    display: block;
    overflow: hidden;
    border-radius: 8px;
    background: var(--gray-100);
}

    .skel::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.75), transparent);
        transform: translateX(-100%);
        animation: skel-shimmer 1.4s ease-in-out infinite;
        will-change: transform;
    }

@keyframes skel-shimmer {
    100% {
        transform: translateX(100%);
    }
}

/* يحترم تفضيل تقليل الحركة — الوميض المستمرّ مزعج لبعض المستخدمين */
@media (prefers-reduced-motion: reduce) {
    .skel {
        animation: none;
    }
}

.skel-line {
    height: 12px;
    margin-bottom: 8px;
}

.skel-h-lg {
    height: 18px;
}

.skel-h-sm {
    height: 6px;
}

.skel-w-70 {
    width: 70%;
}

.skel-w-40 {
    width: 40%;
}

.skel-w-30 {
    width: 30%;
}

/* يطابق ارتفاع .course-img تماماً */
.skel-card-img {
    height: 200px;
    border-radius: 0;
}

.skel-pill {
    width: 64px;
    height: 22px;
    border-radius: 999px;
}

.skel-btn {
    height: 38px;
    border-radius: 12px;
}

.skel-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    flex: 0 0 auto;
}

/* ==========================================================================
   8) صورة بطاقة الدورة على الجوال
   --------------------------------------------------------------------------
   تحت 576px تُقصَّر صورة البطاقة إلى 132px بدل 200px: الغرض تمييز البطاقة لا
   عرض الصورة، فيصل المستخدم إلى الدورات بتمريرٍ أقلّ.

   كان هذا القسم يضغط أيضاً أرقام لوحة الطالب القديمة وقوائم فلترتها
   (.student-stats و.student-filters). حُذفت قواعدهما في المرحلة 10: لا عنصر
   يحمل الصنفين بعد نقل اللوحة إلى Zui. وبقيت الصورة لأن .course-img حيّة في
   صفحة SectionSemesters العامّة.
   ========================================================================== */

@media (max-width: 575.98px) {
    .course-img {
        height: 132px !important;
    }
}

/* ==========================================================================
   9) ارتفاع الـ header المحجوز
   --------------------------------------------------------------------------
   styles.css يحجز 72px ثابتة، والـ header ثابت الموضع فوقها. لكن ارتفاعه
   يتغيّر: عدد روابط التنقّل يختلف بحسب حالة الدخول فتلتفّ على العروض المتوسّطة.

   القياس على 1009px: الـ header 104px والحجز 72px، فبقي 32px من المحتوى خلفه
   ولم يستقبل النقر — elementFromPoint عند أعلى المحتوى أعطى NAV.nav.

   js/zadbyan-header.js يقيس الارتفاع الفعلي ويكتبه في --zb-header-h ويُبقيه
   مطابقاً بـ ResizeObserver. والقيمة الاحتياطية 72px هي قيمة التصميم، فلو
   تعطّل الـ JS عاد السلوك إلى ما كان لا إلى ما هو أسوأ.
   ========================================================================== */

body {
    padding-top: var(--zb-header-h, 72px) !important;
}

/* ==========================================================================
   12) الترويسة في الصفحة الرئيسية — فصل بصري عند التمرير
   --------------------------------------------------------------------------
   الترويسة ثابتة وخلفيّتها بيضاء كخلفية الأقسام تحتها، فحين يمرّر المستخدم
   تمرّ البطاقات تحتها بلا حدّ فتبدو ملتصقة بها ويضيع إحساس الطبقات.
   الصنف is-scrolled يضعه zadbyan-header.js عند scrollY > 8.
   ========================================================================== */

.header {
    transition: box-shadow 0.2s ease, background-color 0.2s ease;
}

    .header.is-scrolled {
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.07);
    }

/* الرابط الحالي في الترويسة: التصميم يرسم خطاً تحته عبر ::after في styles.css،
   ويبقى اللون. هنا نزيد الوزن وحده فيُقرأ التمييز حتى على الشاشات الصغيرة
   حيث تنقلب القائمة عمودية فيختفي أثر الخطّ. */
.nav a.nav-link-active span,
.nav .nav-dropdown-trigger.nav-link-active span {
    font-weight: 700;
}

/* ==========================================================================
   13) أزرار btn-outline-* — إعادة الحدّ الذي يمحوه القالب
   --------------------------------------------------------------------------
   styles.css يعطي كل .btn قاعدة `border: none` (سطر 1164)، وأسبقيّتها تفوق
   قواعد bootstrap لأنها تأتي بعدها. ونمط btn-outline-* كلّه قائم على الحدّ:
   خلفيّته شفّافة ولونه هو لون الحدّ. فبلا حدّ يصير الزرّ نصّاً ملوّناً عائماً
   لا يبدو زرّاً إطلاقاً.

   القياس على زرّ «تغيير كلمة المرور» في /Profile:
       background-color = rgba(0, 0, 0, 0)
       border           = 0px none rgb(25, 135, 84)   <-- ممحوّ

   والقاعدة عامّة لا خاصّة بتلك الصفحة: كل زرّ btn-outline-* في المنصّة يقع
   في العطل نفسه. ولون الحدّ لا يُذكر هنا — bootstrap يحسبه من المتغيّر
   --bs-btn-border-color بحسب اللون المطلوب، والممحوّ هو العرض والنمط وحدهما.
   ========================================================================== */

.btn[class*="btn-outline-"] {
    border-width: 1px !important;
    border-style: solid !important;
}

/* ==========================================================================
   16) ترويسة الصفحة الرئيسية العامة — مساحة النقر والوضوح
   --------------------------------------------------------------------------
   القياس على 1440: ارتفاع كل رابط في القائمة 26px. وهو ارتفاع النصّ نفسه بلا
   حشو رأسي، فمنطقة النقر تساوي الحروف. الإرشاد المتعارف عليه 40px على الأقل
   للفأرة و44px للإصبع، والفارق محسوس: المستخدم يخطئ الرابط فيضغط الفراغ.

   الحشو رأسي فقط عن قصد: الزيادة الأفقية تدفع القائمة فتلتفّ على العروض
   المتوسّطة — قيس أن الروابط الستّة تشغل 624px من 1200px متاحة.
   ========================================================================== */

.header .nav > a,
.header .nav .nav-link-dropdown {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding-block: 0.5rem;
    border-radius: 8px;
    transition: color 0.15s;
}

/* حالة المرور: كانت بلا أثر بصري إطلاقاً فلا يعرف المستخدم أن العنصر قابل
   للنقر قبل أن يضغطه */
.header .nav > a:hover,
.header .nav .nav-dropdown-trigger:hover {
    color: var(--primary, #198754);
}

/* مبدّل اللغة وقائمة المستخدم: أزرار دائرية متساوية بدل نصوص عائمة */
.header .header-utils .nav-link.dropdown-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 40px;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    transition: background 0.15s;
}

    .header .header-utils .nav-link.dropdown-toggle:hover {
        background: #f1f5f3;
    }

/* المنسدلة: حوافّ ألين وظلّ أوضح فتُقرأ طبقةً فوق الصفحة */
.header .header-utils .dropdown-menu {
    border: 1px solid #e8eeeb;
    border-radius: 12px;
    box-shadow: 0 10px 30px -8px rgba(16, 58, 44, 0.18);
    padding: 0.35rem;
}

    .header .header-utils .dropdown-menu .dropdown-item {
        border-radius: 8px;
        padding: 0.5rem 0.75rem;
        min-height: 40px;
        display: flex;
        align-items: center;
    }

@media (max-width: 991.98px) {
    /* القائمة تنقلب عمودية على الجوال — العناصر تحتاج مساحة إصبع */
    .header .nav > a,
    .header .nav .nav-link-dropdown {
        min-height: 44px;
        width: 100%;
    }
}

/* ==========================================================================
   17) الصندوق الأسود حول عنوان الصفحة — حلقة تركيز لا حدّ
   --------------------------------------------------------------------------
   ظهر إطار أسود يحيط بعنوان «الحصص المباشرة» بعرض الصفحة. القياس:

       activeElement            = H1.lc-display lc-display-l
       tabindex                 = "-1"
       outline                  = rgb(16,16,16) auto 0.8px
       matches(':focus-visible') = true

   فليس حدّاً في التصميم بل حلقة تركيز يرسمها المتصفّح. سببها نمط إتاحة سليم:
   الصفحة تنقل التركيز إلى عنوانها بعد الانتقال ليعلنه قارئ الشاشة، فتضع
   tabindex="-1" وتنادي focus().

   والعنصر ذو tabindex="-1" لا يُبلَغ بمفتاح Tab إطلاقاً — يُركَّز برمجياً أو
   بالنقر وحدهما. فحلقةُ التركيز عليه لا تفيد مستخدم لوحة المفاتيح شيئاً
   وتشوّه الصفحة لغيره. إخفاؤها هنا لا يُنقص إتاحةً: الإعلان الصوتي يبقى.

   ⚠️ النطاق محصور بـ tabindex="-1" عن قصد: حلقة التركيز على الأزرار والحقول
   والروابط ضرورية ولا تُمسّ.
   ========================================================================== */

[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
    box-shadow: none;
}


/* ===== بدائل الصور الغائبة =====
   عام لا scoped: الكلاس يُضاف من zadbyan-home.js على أكثر من صفحة، والـ scoped
   CSS لا يطابق إلا العناصر المكتوبة في الملف الذي عُرّف فيه.
   الحالتان اللتان يغطّيهما:
     1. ImageURL فارغة، فكان المسار يُركَّب على كل حال فينتج مجلّد لا ملف.
     2. ImageURL غير فارغة والملفّ مفقود على القرص — 404 وإطارٌ فارغ. */
.home-media-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 200px;
    background: #f2f4f6;
    color: #9aa4ae;
    font-size: 2.5rem;
}

.home-avatar-placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #f2f4f6;
    color: #127452;
    font-weight: 700;
    font-size: 1.4rem;
}
