﻿/* ─── CSS Variables ─────────────────────────────────────────────────────────── */
:root {
    --primary:       #2563eb;
    --primary-dark:  #1d4ed8;
    --primary-light: rgba(37,99,235,0.08);
    --success:       #10b981;
    --warning:       #f59e0b;
    --danger:        #ef4444;
    --info:          #06b6d4;

    --bg-app:        #f0f4f8;
    --bg-panel:      #ffffff;

    --text-primary:  #111827;
    --text-secondary:#374151;
    --text-muted:    #6b7280;

    --border-color:  #e5e7eb;

    --radius-sm:     8px;
    --radius-md:     12px;
    --radius-lg:     16px;

    /* Tinted toward the canvas hue rather than neutral black alpha — a grey shadow on a
       cool ground is what makes a light interface look washed out. */
    --shadow-sm:     0 1px 2px rgba(15,23,42,0.05), 0 1px 3px rgba(15,23,42,0.04);
    --shadow-md:     0 2px 4px rgba(15,23,42,0.05), 0 8px 20px -12px rgba(15,23,42,0.28);
    --shadow-lg:     0 4px 8px rgba(15,23,42,0.05), 0 16px 32px -18px rgba(15,23,42,0.32);
    --shadow-xl:     0 8px 16px rgba(15,23,42,0.06), 0 32px 64px -28px rgba(15,23,42,0.38);

    --sidebar-width: 260px;
    --header-height: 72px;
}

/* ─── Reset ────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Force light rendering of native controls (select dropdowns, etc.) so option
   text stays visible even when the OS / browser is in dark mode. */
html { font-size: 15px; color-scheme: light; }
body {
    /* Each platform's own UI face, in order — see the note in _Layout: the previous
       stack named a font that is never loaded, so every phone picked a different
       fallback for Arabic. */
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Arabic',
                 'Segoe UI', 'Segoe UI Variable Text', Roboto,
                 'Noto Sans Arabic', 'Noto Naskh Arabic', 'Helvetica Neue',
                 Tahoma, Arial, sans-serif;
    background: var(--bg-app);
    color: var(--text-primary);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;   /* off-canvas drawer must not create a horizontal scrollbar */
}

/* ─── App Layout ────────────────────────────────────────────────────────────── */
/* 100dvh, not 100vh — on iOS the address bar makes 100vh taller than the screen and
   the whole page jumps when it retracts. */
/* Both units, in this order: a browser that does not know `dvh` DROPS that line and
   keeps the `vh` above it. Declaring only `dvh` would leave such a browser with no
   minimum height at all. */
.app-wrapper { display: flex; min-height: 100vh; min-height: 100dvh; }

/* ─── Sidebar ───────────────────────────────────────────────────────────────── */
.sidebar {
    width: var(--sidebar-width);
    background: #1e293b;
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0; left: 0; bottom: 0;
    overflow-y: auto;
    z-index: 100;
    border-right: 1px solid rgba(255,255,255,0.05);
}

.brand-section {
    padding: 24px 20px 20px;
    display: flex;
    align-items: center;
    gap: 12px;
    border-bottom: 1px solid rgba(255,255,255,0.07);
}
.brand-logo {
    width: 42px; height: 42px;
    background: var(--primary);
    border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.2rem; color: white; flex-shrink: 0;
}
.brand-name {
    font-size: 0.95rem; font-weight: 700; color: white; line-height: 1.3;
}
.brand-name span {
    display: block; font-size: 0.75rem; color: rgba(255,255,255,0.5); font-weight: 400; margin-top: 2px;
}

.nav-menu { list-style: none; padding: 12px 10px; flex: 1; }
.nav-item { margin-bottom: 2px; }
.nav-item a {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    color: rgba(255,255,255,0.65);
    text-decoration: none;
    font-size: 0.88rem; font-weight: 500;
    transition: background 0.15s, color 0.15s;
}
.nav-item a { position: relative; }
.nav-item a:hover { background: rgba(255,255,255,0.07); color: white; }
/* "You are here" said once, quietly: a tinted fill and a solid accent bar on the leading
   edge. A full blue block competes with the primary buttons on the page for the one
   accent the system allows. */
.nav-item.active a {
    background: rgba(37,99,235,0.22);
    color: #fff; font-weight: 700;
}
.nav-item.active a::before {
    content: ""; position: absolute; inset-block: 6px; inset-inline-start: -12px;
    width: 3px; border-radius: 0 3px 3px 0; background: #60a5fa;
}
.nav-item.active a i { color: #93c5fd; }
.nav-item a i { width: 16px; text-align: center; font-size: 0.9rem; }

.sidebar-footer {
    padding: 16px 12px;
    border-top: 1px solid rgba(255,255,255,0.07);
}
.user-profile {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 8px; margin-bottom: 8px;
}
.profile-avatar {
    width: 36px; height: 36px;
    background: var(--primary);
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 0.8rem; font-weight: 800; color: white; flex-shrink: 0;
}
.profile-info { overflow: hidden; }
.profile-name { display: block; font-size: 0.85rem; font-weight: 600; color: white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.profile-role { display: block; font-size: 0.75rem; color: rgba(255,255,255,0.5); }
.btn-logout {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 9px 12px;
    background: rgba(239,68,68,0.1); border: none;
    color: #f87171; border-radius: var(--radius-sm);
    font-size: 0.85rem; font-weight: 600; cursor: pointer;
    transition: background 0.15s;
}
.btn-logout:hover { background: rgba(239,68,68,0.2); }

/* ─── Main Content ──────────────────────────────────────────────────────────── */
.main-content {
    margin-left: var(--sidebar-width);
    flex: 1;
    min-width: 0;          /* allow content to shrink instead of overflowing */
    max-width: 100%;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.page-header {
    background: var(--bg-panel);
    border-bottom: 1px solid var(--border-color);
    padding: 0 32px;
    height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: sticky; top: 0;
    z-index: 50;
    gap: 16px;
}
.page-title h1 { font-size: 1.1rem; font-weight: 700; color: var(--text-primary); }
.page-title p  { font-size: 0.8rem; color: var(--text-muted); margin-top: 2px; }

.content-body { padding: 28px 32px; flex: 1; }

/* ─── Mobile menu toggle (hidden on desktop) ──────────────────────────────────── */
.menu-toggle {
    display: none;
    background: none; border: none; cursor: pointer;
    font-size: 1.4rem; color: var(--text-primary);
    padding: 6px 8px; line-height: 1; flex-shrink: 0;
}
.sidebar-overlay {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 90;
    opacity: 0; visibility: hidden;
    transition: opacity 0.25s ease, visibility 0.25s ease;
}
.sidebar-overlay.show { opacity: 1; visibility: visible; }

/* ─── Responsive: phones, tablets & narrow/half-screen windows ─────────────────── */
@media (max-width: 1024px) {
    .menu-toggle { display: inline-flex; align-items: center; }

    /* Content takes the full width — no room reserved for the sidebar. */
    .main-content { margin-left: 0 !important; margin-right: 0 !important; }

    /* Sidebar slides in as an overlay drawer instead of taking layout space. */
    .sidebar {
        width: 82%; max-width: 300px;
        transform: translateX(-100%);
        transition: transform 0.25s ease;
        box-shadow: 0 0 40px rgba(0,0,0,0.45);
    }
    html[dir="rtl"] .sidebar { transform: translateX(100%); }
    .sidebar.open { transform: translateX(0) !important; }

    .page-header { padding: 0 16px; height: auto; min-height: var(--header-height); }
    .page-title h1 { font-size: 1rem; }
    .content-body { padding: 18px 14px; }
    .panel { padding: 18px; }

    /* Two-column layouts stack on narrow/half-screen widths. */
    .dashboard-grid { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
    .metrics-grid { grid-template-columns: 1fr 1fr; }
    .page-title p { display: none; }
}

/* ─── Mobile robustness ───────────────────────────────────────────────────────
   Two things break phone layouts: (1) inline multi-column grids that a media
   query can't reach, and (2) long unbreakable text (emails/codes/URLs) that
   forces the page wider — which makes mobile Safari zoom out and then NONE of the
   responsive breakpoints match, so every screen renders as squeezed desktop.
   These rules stack all multi-column grids and force long text to wrap. */
@media (max-width: 700px) {
    /* Any inline 2-/3-column grid collapses to ONE column. `!important` beats the
       element's own inline grid-template-columns. */
    [style*="grid-template-columns:1fr 1fr"],
    [style*="grid-template-columns: 1fr 1fr"],
    [style*="grid-template-columns:repeat(2"],
    [style*="grid-template-columns: repeat(2"],
    [style*="grid-template-columns:repeat(3"],
    [style*="grid-template-columns: repeat(3"] {
        grid-template-columns: 1fr !important;
    }

    /* Wide data TABLES scroll sideways inside their own box instead of squeezing
       or breaking text character-by-character. Keeping each cell on ONE line makes
       the table hold its natural width, so the horizontal scroll kicks in. */
    .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
    .custom-table th, .custom-table td { white-space: nowrap; }

    /* The page itself never scrolls sideways on a phone. */
    body { max-width: 100%; overflow-x: clip; }

    /* Explanatory notes/badges that live INSIDE a data-table cell: the nowrap rule
       above would stretch a full sentence across the screen, so these wrap — but they
       keep a real minimum width so a narrow column can never squeeze them into one
       letter per line (the table itself scrolls sideways, as designed). */
    .nca-cellnote {
        white-space: normal !important;
        min-width: 230px; width: max-content; max-width: 82vw;
    }
}

/* ─── Phone: the anatomy of a panel ───────────────────────────────────────────
   `.panel` builds 46 of the 47 screens and `.panel-title` appears 69 times, so this is
   the one place that reaches every page. Phone-only: the desktop never sees these rules. */
@media (max-width: 700px) {
    /* 1. the title announces its section instead of running into it */
    .panel-header {
        flex-wrap: wrap; row-gap: 8px;
        padding-bottom: 11px; margin-bottom: 13px;
        border-bottom: 1px solid var(--border-color);
    }
    .panel-title { font-size: 1rem; line-height: 1.5; }

    /* 2. the line that FOLLOWS a section title is guidance, not content — it steps back
          and takes the leading Arabic needs on a narrow column */
    .panel > .panel-header + p,
    .panel > h2 + p, .panel > h3 + p, .panel > h4 + p {
        font-size: 0.82rem; color: var(--text-muted);
        line-height: 1.9; margin-bottom: 14px;
    }

    /* 3. an item is an OBJECT, not a gap between rules.
          The idiom below ("a row opened by a top border") is how repeated records are
          written across these screens; on a phone it becomes a block with its own ground
          and corners, so a list of records reads as separate records. */
    .panel [style*="border-top:1px solid var(--border-color)"] {
        border-top: 0 !important;
        background: var(--bg-app);
        border: 1px solid var(--border-color);
        border-radius: 14px;
        padding: 12px !important;
        margin-bottom: 10px;
    }
    /* the item's own buttons: under the text, sharing a line, big enough to hit —
       and never painted over anything */
    .panel [style*="border-top:1px solid var(--border-color)"] > .btn {
        flex: 1 1 auto; min-height: 42px; min-width: 130px;
        border-radius: 11px; font-weight: 700;
    }
    /* 4. an action belongs to the item above it — full width says so on a phone */
    .panel [style*="border-top:1px solid var(--border-color)"] > form:only-of-type,
    .panel [style*="border-top:1px solid var(--border-color)"] > form:only-of-type .btn {
        width: 100%;
    }
}

/* ─── Phone: a data table is read as CARDS ────────────────────────────────────
   A six-column table on a 390px screen is unreadable however it scrolls. On a phone
   every row becomes its own card and every value carries its column name (filled in
   from the table head at runtime), so nothing is guessed and nothing is cut off.
   A table that must stay a real grid opts out with class="nca-nocards". */
@media (max-width: 700px) {
    /* حتى يحوّلها السكريبت لكروت، الجدول يبقى غير مرئي — بدل ما يومض بشكله
       المكتبي القديم لحظة في كل تنقل. العلامة nca-js يضعها سطر في <head> قبل أول
       رسم، ويزيلها السكريبت لو تعطّل — فتعطُّله يعيد الوميض القديم ولا يخفي شيئًا. */
    html.nca-js table.custom-table:not(.nca-cards):not(.nca-nocards) { visibility: hidden; }
    table.custom-table.nca-cards { display: block; }
    table.custom-table.nca-cards thead { display: none; }
    table.custom-table.nca-cards tbody,
    table.custom-table.nca-cards tr,
    table.custom-table.nca-cards td { display: block; width: 100%; }
    table.custom-table.nca-cards tr {
        border: 1px solid var(--border-color); border-radius: 16px;
        margin: 0 0 12px; padding: 6px 14px; background: var(--bg-panel);
        box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 10px 24px -18px rgba(15, 23, 42, .40);
    }
    table.custom-table.nca-cards tbody tr:hover { background: var(--bg-panel); }
    table.custom-table.nca-cards td {
        white-space: normal !important; overflow-wrap: anywhere;
        border: none !important;
        /* a hairline separates; a dashed rule decorates */
        border-bottom: 1px solid var(--border-color) !important;
        padding: 10px 0; display: flex; gap: 12px; align-items: flex-start;
    }
    table.custom-table.nca-cards tr td:last-child { border-bottom: none !important; }
    table.custom-table.nca-cards td::before {
        content: attr(data-label);
        /* the label names the value — it must never compete with it */
        flex: 0 0 auto; width: 78px; padding-top: 3px;
        font-size: 0.7rem; font-weight: 700; color: var(--text-muted);
        opacity: .85; line-height: 1.55;
    }
    table.custom-table.nca-cards td:not([data-label])::before { content: none; }
    /* The value gets its OWN box and the whole rest of the row — without it the content
       was squeezed into a sliver and long words broke one letter per line. */
    table.custom-table.nca-cards td > .nca-cardval {
        flex: 1 1 auto; min-width: 0; max-width: 100%;
        display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px;
    }
    table.custom-table.nca-cards td > .nca-cardval > * { max-width: 100%; }
    /* The first line of a card is what the card IS — the doctor's name, the moment, the
       room. Reading it as one more grey row is what made these look like a list of
       identical lines instead of a stack of distinct things. */
    table.custom-table.nca-cards tr td:first-child > .nca-cardval {
        font-size: 0.95rem; font-weight: 800; line-height: 1.55;
        color: var(--text-primary);
    }
    /* the headline sits ABOVE the hairline that opens the card's detail — one clear
       break between "what this row is" and "what is known about it" */
    table.custom-table.nca-cards tr td:first-child { padding-bottom: 11px; }

    /* ── the card says its state before you read it ────────────────────────────
       A coloured edge down the leading side, taken from the badge the row already
       renders. Twenty requests separate into approved / rejected / waiting at a
       glance instead of being read one by one. No markup added — :has() reads the
       badge that is already there, and a row without one keeps the neutral edge. */
    table.custom-table.nca-cards tr {
        /* thick enough to be the card's state at a glance. NO overflow:hidden — the
           accent is a border and needs no clipping, and clipping is what cut «مراجعة
           واستعادة» off mid-word at the card's edge. */
        border-inline-start: 5px solid var(--border-color);
    }
    /* A column that had nothing to say for this row. As a table cell its blank was
       invisible; as a card it became a labelled line promising a fact that isn't
       there. The script marks it — CSS :empty is defeated by one space. */
    table.custom-table.nca-cards td.nca-cardempty { display: none; }

    /* ── slot facts inside a card ───────────────────────────────────────────────
       In a table these are chips: they sit under a course code in a dense column
       and must not stretch it. In a card the same content has the whole width, and
       squeezing it into a 250px sliver beside a label is what made a two-word chip
       wrap into three lines. Same wording, a shape that fits the space. */
    table.custom-table.nca-cards td:has(.nca-slot-when),
    table.custom-table.nca-cards td:has(.nca-slot-merged) {
        flex-direction: column; gap: 7px;
    }
    table.custom-table.nca-cards td:has(.nca-slot-when)::before,
    table.custom-table.nca-cards td:has(.nca-slot-merged)::before {
        width: auto; flex: 0 0 auto; padding-top: 0;
    }
    table.custom-table.nca-cards td:has(.nca-slot-when) > .nca-cardval,
    table.custom-table.nca-cards td:has(.nca-slot-merged) > .nca-cardval {
        flex-direction: column; align-items: stretch; gap: 6px; width: 100%;
    }
    table.custom-table.nca-cards .nca-slot-when,
    table.custom-table.nca-cards .nca-slot-merged {
        display: flex; flex-wrap: wrap; align-items: baseline;
        width: 100%; margin: 0; gap: 2px 8px;
        padding: 8px 12px; border-radius: 10px;
        font-size: 0.77rem; line-height: 1.55;
    }

    table.custom-table.nca-cards tr:has(.badge-success) { border-inline-start-color: var(--success); }
    table.custom-table.nca-cards tr:has(.badge-danger)  { border-inline-start-color: var(--danger); }
    table.custom-table.nca-cards tr:has(.badge-warning) { border-inline-start-color: var(--warning); }
    table.custom-table.nca-cards tr:has(.badge-info)    { border-inline-start-color: var(--info); }

    /* The status belongs at the top of the card with its headline, not buried in
       whatever row it happened to fall into. */
    table.custom-table.nca-cards tr td:first-child > .nca-cardval {
        display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
    }
    table.custom-table.nca-cards tr td:first-child > .nca-cardval .badge {
        flex: 0 0 auto; align-self: flex-start;
    }

    /* An action row reads as the card's footer: separated from the detail above it,
       and the buttons sized to be hit rather than aimed at. */
    table.custom-table.nca-cards tr td:last-child:has(.btn) {
        border-top: 1px solid var(--border-color) !important;
        padding-top: 11px; margin-top: 2px;
    }
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval { gap: 8px; }
    /* ── THE ACTION CELL ──────────────────────────────────────────────────
       An action cell holds GROUPS, not buttons: a form with its own row of buttons,
       then a div with more. Each group gets its own line; the buttons inside a group
       share that line and wrap when they run out of room. Nothing is forced into a
       width its contents cannot honour — which is what made them overlap. */
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval {
        display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch;
    }
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval > * {
        flex: 1 1 100%; min-width: 0;
    }
    /* a group's own inner row */
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval form > div,
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval > div {
        display: flex; flex-wrap: wrap; gap: 8px;
    }
    /* every button in the cell: hittable, allowed to grow, never squeezed below a size
       its own words fit in */
    table.custom-table.nca-cards tr td:last-child:has(.btn) .btn {
        flex: 1 1 auto; min-width: 118px;
        min-height: 44px; border-radius: 12px;
        font-size: .84rem; font-weight: 700;
        padding-inline: 12px; white-space: nowrap;
    }
    /* An icon-only button stays a square and never stretches across the row.
       Tagged by the card script, NOT selected with :has(> i:only-child): text nodes
       are not children in CSS, so that selector also matched every icon+text button
       and clamped it to 46px — which is what painted the buttons over each other. */
    table.custom-table.nca-cards tr td:last-child:has(.btn) .btn.nca-icon-btn {
        flex: 0 0 auto; min-width: 46px; width: 46px; padding-inline: 0;
    }
    /* the single action of a card fills it — there is nothing else it could apply to */
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval > .btn:only-child,
    table.custom-table.nca-cards tr td:last-child:has(.btn) > .nca-cardval > form:only-child .btn:only-child {
        width: 100%;
    }
    table.custom-table.nca-cards tr td:last-child:has(.btn) .btn-secondary {
        background: var(--primary-light);
        border-color: color-mix(in srgb, var(--primary) 22%, transparent);
        color: var(--primary);
    }

    /* THE FILTER ROW. On a phone a date field and a button cannot share 390px without
       one of them being too small to use — the field needs its width to show a date and
       the button needs to be hit. So the field takes the line and the button takes the
       next one, full width, where it reads as the thing that runs the filter. */
    .panel form:has(input[type="date"]) {
        display: flex !important; flex-direction: column;
        /* !important الاتنين: الفورمات دي شايلة inline align-items:center — من غيرها
           كل حاجة بتتوسّط عمودياً وتبان مرمية، وقاعدة العرض متتنفذش */
        align-items: stretch !important;
        gap: 12px !important;
        /* margin-inline-start:auto زقّة ديسكتوب لآخر الصف — على الموبايل بترمي
           البلوك كله على الشمال (تصنيفات الأداء: خانات الإكسل والزرار الأخضر) */
        margin-inline-start: 0 !important;
        width: 100%;
    }
    .panel form:has(input[type="date"]) > .form-group {
        margin-bottom: 0; min-width: 0 !important; width: 100%;
    }
    /* الخانات نفسها كانت بعرض inline ثابت (150px) فتفضل قصيرة ومش متحاذية */
    .panel form:has(input[type="date"]) input[type="date"] {
        width: 100% !important; min-width: 0;
    }
    .panel form:has(input[type="date"]) > label {
        width: 100%; text-align: start; font-weight: 700; margin-bottom: -6px;
    }
    .panel form:has(input[type="date"]) > .btn {
        width: 100%; min-height: 46px; border-radius: 12px; font-weight: 700;
    }
    /* نفس زقّة الديسكتوب في فلتر «كل الحالات» (تعليقات المحاضرات) — على الموبايل
       الفورم بياخد عرضه كاملاً فيبدأ من اليمين زي كل حاجة. (الفورم ده أعلى الصفحة
       مباشرة، ليس داخل panel) */
    form[style*="margin-inline-start:auto"]:has(select) {
        margin-inline-start: 0 !important; width: 100%;
    }
    form[style*="margin-inline-start:auto"]:has(select) select { width: 100%; }

    /* ── صف تبويبات الفلترة (تعليقات المحاضرات وأمثاله) ─────────────────────
       أربع أزرار بأعراض مختلفة تلتف سطرين مكسّرين. على الموبايل تصبح شبكة ٢×٢
       متساوية — كل زر بعرض نصف الشاشة وارتفاع يُضغط بالإبهام — والفلتر المنسدل
       يأخذ سطرًا كاملًا تحتها. */
    .content-body > div[style*="flex-wrap:wrap"]:has(> a.btn):has(> form select) {
        display: grid !important;
        grid-template-columns: 1fr 1fr;
        gap: 8px !important;
    }
    .content-body > div[style*="flex-wrap:wrap"]:has(> a.btn):has(> form select) > a.btn {
        width: 100%; min-height: 46px; justify-content: center;
    }
    .content-body > div[style*="flex-wrap:wrap"]:has(> a.btn):has(> form select) > form {
        grid-column: 1 / -1;
    }
    /* a chip is a chip: it wraps as a whole word, never letter by letter */
    table.custom-table.nca-cards .badge { white-space: nowrap; }
    /* a cell full of buttons becomes a tidy wrapped row of full-height targets */
    table.custom-table.nca-cards td .nca-cardval > form,
    table.custom-table.nca-cards td .nca-cardval > a.btn,
    table.custom-table.nca-cards td .nca-cardval > button { flex: 0 0 auto; }
    table.custom-table.nca-cards td .btn { padding: 8px 14px; font-size: 0.82rem; }
    table.custom-table.nca-cards .nca-cellnote { min-width: 0; max-width: 100%; }
    table.custom-table.nca-cards input.form-control,
    table.custom-table.nca-cards select.form-control { width: 100%; min-width: 0; }
}

/* ─── Phone: "pick from a list" opens as a bottom sheet ───────────────────────
   A floating dropdown next to the field is a desktop idea: on a phone it lands on
   top of the text, and iOS drops its own Paste/AutoFill bar over it. The sheet is
   unmistakable — full width, big rows, dimmed background — and needs no keyboard. */
.nca-menu-backdrop {
    position: fixed; inset: 0; z-index: 1390;
    background: rgba(15,23,42,0.45); backdrop-filter: blur(2px);
}
/* Room combobox — shared by the requests screen and the course builder. It lived in
   one page's <style>, so the second screen to use it rendered an unstyled, invisible
   list. A component used by more than one screen belongs in the stylesheet. */
.nca-room-menu {
    position: fixed; z-index: 1000;
    background: var(--bg-primary, #fff); border: 1px solid var(--border-color);
    border-radius: 8px; box-shadow: 0 8px 20px rgba(0,0,0,0.14);
    max-height: 180px; overflow: auto; margin-top: 3px;
}
.nca-room-opt { padding: 7px 10px; cursor: pointer; font-size: 0.8rem; font-weight: 600; }
.nca-room-opt:hover { background: rgba(59,130,246,0.12); }

.nca-menu-sheet {
    position: fixed !important;
    inset-inline: 0 !important; left: 0 !important; right: 0 !important;
    top: auto !important; bottom: 0 !important;
    width: auto !important; max-width: none !important;
    max-height: 62vh !important; overflow-y: auto;
    z-index: 1400;
    border-radius: 18px 18px 0 0 !important;
    box-shadow: 0 -14px 40px rgba(15,23,42,0.32) !important;
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
.nca-menu-sheet > * {
    padding: 14px 18px !important;
    font-size: 0.95rem !important;
    border-bottom: 1px solid var(--border-color);
}
.nca-menu-sheet > *:last-child { border-bottom: none; }
.nca-menu-sheet .nca-sheet-cap {
    position: sticky; top: 0; z-index: 2;
    background: var(--bg-panel, #fff); font-weight: 800; font-size: 0.85rem !important;
    color: var(--text-muted); display: flex; align-items: center; justify-content: space-between;
}

/* ─── Panel ─────────────────────────────────────────────────────────────────── */
.panel {
    background: var(--bg-panel);
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
    padding: 24px;
}
.panel-header {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 20px; gap: 12px;
}
.panel-title { font-size: 1rem; font-weight: 700; color: var(--text-primary); }

/* ─── Metrics Grid ──────────────────────────────────────────────────────────── */
.metrics-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
}
.metric-card {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 20px;
    display: flex; align-items: center; gap: 16px;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 0.15s, transform 0.15s;
}
.metric-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.metric-icon {
    width: 48px; height: 48px; border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.25rem; flex-shrink: 0;
}
.metric-info { display: flex; flex-direction: column; }
.metric-value { font-size: 1.6rem; font-weight: 800; color: var(--text-primary); line-height: 1.1; }
.metric-label { font-size: 0.78rem; color: var(--text-muted); font-weight: 500; margin-top: 4px; }

/* ─── Phone: the tile stacks ──────────────────────────────────────────────────
   Side by side on a 390px screen the figure gets a third of the tile and the label
   wraps under it at a ragged length. Stacked, the figure owns the full width and the
   eye lands on it instead of hunting past an icon. (Pattern taken from the Stitch
   generation of this screen; see DESIGN.md.) */
@media (max-width: 700px) {
    .metrics-grid { grid-template-columns: 1fr 1fr; gap: 12px; }
    .metric-card {
        flex-direction: column; align-items: stretch; justify-content: space-between;
        gap: 14px; padding: 14px; border-radius: 16px; min-height: 118px;
    }
    /* the icon is a marker, not a headline — it steps back into its own chip */
    .metric-icon { width: 38px; height: 38px; font-size: 1.02rem; border-radius: 11px; }
    .metric-info { gap: 2px; }
    /* label first, figure last and largest: the tile reads top-to-bottom in one move */
    .metric-info { display: flex; flex-direction: column-reverse; }
    .metric-label { margin-top: 0; margin-bottom: 4px; font-size: .76rem; font-weight: 600; }
    .metric-value { font-size: 1.75rem; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
    /* a hover lift on a touch screen is a state nobody can leave */
    .metric-card:hover { transform: none; box-shadow: var(--shadow-sm); }

    /* ── A TILE THAT NEEDS SOMETHING LOOKS LIKE IT ─────────────────────────
       Every tile already renders its icon in its own semantic tint. :has() lifts
       that colour to the whole tile, so the one asking for attention is found by
       looking rather than by reading — which is the only reason a dashboard exists.
       A tile with a neutral icon is untouched. */
    .metric-card:has(.metric-icon[style*="245,158,11"]) {              /* warning */
        background: rgba(245, 158, 11, 0.055);
        border-color: rgba(245, 158, 11, 0.34);
    }
    .metric-card:has(.metric-icon[style*="245,158,11"]) .metric-value { color: var(--warning); }

    .metric-card:has(.metric-icon[style*="239,68,68"]) {               /* danger */
        background: rgba(239, 68, 68, 0.05);
        border-color: rgba(239, 68, 68, 0.32);
    }
    .metric-card:has(.metric-icon[style*="239,68,68"]) .metric-value { color: var(--danger); }

    /* ── the quick actions are one row you sweep, not a block that wraps ──
       Five buttons wrapping into three ragged lines is the single untidiest thing
       on this screen at 390px. */
    /* ONLY a row where EVERY child is a button is a toolbar. One non-button child —
       a text block, a form — and the row is content: it must keep wrapping. (The
       broad version of this selector was catching the trash-bin items and painting
       their buttons over their text.) */
    .panel > div[style*="display:flex"][style*="flex-wrap:wrap"]:has(> .btn):not(:has(> :not(.btn))) {
        flex-wrap: nowrap !important;
        overflow-x: auto; overscroll-behavior-x: contain;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        gap: 9px !important;
        padding-bottom: 2px;
        /* the row bleeds to the screen edges so it reads as "there is more that way" */
        margin-inline: -14px; padding-inline: 14px;
    }
    .panel > div[style*="display:flex"][style*="flex-wrap:wrap"]:has(> .btn):not(:has(> :not(.btn)))::-webkit-scrollbar { display: none; }
    .panel > div[style*="display:flex"][style*="flex-wrap:wrap"]:has(> .btn):not(:has(> :not(.btn))) > .btn {
        flex: 0 0 auto; border-radius: 999px; padding-inline: 16px;
    }
}

/* ─── Dashboard Grid ─────────────────────────────────────────────────────────── */
.dashboard-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}

/* ─── Table ─────────────────────────────────────────────────────────────────── */
.table-responsive { overflow-x: auto; }
.custom-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.custom-table th {
    padding: 11px 14px; background: var(--bg-app);
    font-size: 0.76rem; font-weight: 700;
    /* NO letter-spacing and NO uppercase here. Arabic is a cursive script: its letters
       join, and letter-spacing forces gaps that BREAK those joins — every header in the
       system was rendering as disconnected letters. `uppercase` does nothing to Arabic
       either; it was only ever styling the few Latin words that share these headers. */
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-color);
    white-space: nowrap;
}
.custom-table td {
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-secondary);
    vertical-align: middle;
}
/* The first cell is WHAT THE ROW IS — the lecturer, the course, the moment. Giving it the
   ink colour and a little more weight lets the eye find its way down a long table without
   stripes or rules doing the shouting. */
.custom-table tbody td:first-child { color: var(--text-primary); font-weight: 600; }
.custom-table tbody tr:last-child td { border-bottom: none; }
.custom-table tbody tr { transition: background-color .12s ease; }
.custom-table tbody tr:hover { background: var(--bg-app); }

/* ─── Badges ────────────────────────────────────────────────────────────────── */
.badge {
    display: inline-flex; align-items: center; gap: 5px;
    /* Arabic descenders (ج ح خ ع غ م ي) were clipping against a 3px box. */
    padding: 4px 11px; border-radius: 20px; line-height: 1.6;
    font-size: 0.75rem; font-weight: 700; white-space: nowrap;
}
.badge-success   { background: rgba(16,185,129,0.1);  color: var(--success); }
.badge-warning   { background: rgba(245,158,11,0.12); color: var(--warning); }
.badge-danger    { background: rgba(239,68,68,0.1);   color: var(--danger); }
.badge-info      { background: rgba(6,182,212,0.1);   color: var(--info); }
.badge-secondary { background: rgba(107,114,128,0.1); color: var(--text-muted); }

/* ─── Keyboard focus ────────────────────────────────────────────────────────────
   One visible ring for the whole application. It was only ever defined on the header,
   so on every other screen a keyboard user could not see where they were. */
:is(a, button, [role="button"], input, select, textarea, summary):focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}
.sidebar :is(a, button):focus-visible { outline-color: #93c5fd; }

/* ─── Buttons ───────────────────────────────────────────────────────────────── */
.btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 6px; padding: 9px 20px;
    border-radius: var(--radius-sm);
    font-size: 0.88rem; font-weight: 600; cursor: pointer;
    border: 1px solid transparent;
    text-decoration: none; transition: all 0.15s;
    white-space: nowrap;
}
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-primary { background: var(--primary); color: white; border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-dark); }
.btn-secondary { background: var(--bg-app); color: var(--text-secondary); border-color: var(--border-color); }
.btn-secondary:hover { background: var(--border-color); }
.btn-danger { background: rgba(239,68,68,0.1); color: var(--danger); border-color: rgba(239,68,68,0.2); }
.btn-danger:hover { background: var(--danger); color: white; }
.btn-success { background: var(--success); color: white; border-color: var(--success); }
.btn-success:hover { background: #059669; }

/* ─── Forms ─────────────────────────────────────────────────────────────────── */
.form-group { margin-bottom: 18px; }
.form-label { display: block; font-size: 0.82rem; font-weight: 700; color: var(--text-secondary); margin-bottom: 6px; }
.form-control {
    width: 100%; padding: 9px 13px;
    border: 1px solid var(--border-color); border-radius: var(--radius-sm);
    font-size: 0.9rem; color: var(--text-primary); background: var(--bg-panel);
    transition: border-color 0.15s, box-shadow 0.15s;
    font-family: inherit;
}
.form-control:focus {
    outline: none; border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37,99,235,0.12);
}
.form-control::placeholder { color: var(--text-muted); }
/* Keep <select> option lists readable in every browser/OS theme (incl. RTL/dark). */
select.form-control { color: var(--text-primary); background-color: var(--bg-panel); color-scheme: light; }
.form-control option,
.form-control optgroup { color: #111827; background-color: #ffffff; }

/* ─── Timer ─────────────────────────────────────────────────────────────────── */
.timer-container { text-align: center; padding: 28px 0; }
.timer-digits {
    font-size: 3.5rem; font-weight: 800; font-variant-numeric: tabular-nums;
    color: var(--primary); letter-spacing: 2px; line-height: 1;
    font-family: 'Courier New', monospace;
}
.timer-label { font-size: 0.82rem; color: var(--text-muted); margin-top: 8px; font-weight: 600; }

/* ─── Course Cards ──────────────────────────────────────────────────────────── */
.course-card {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 20px;
    transition: all 0.2s;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
}
.course-card:hover {
    box-shadow: var(--shadow-lg);
    transform: translateY(-3px);
    border-color: var(--primary);
}
.course-card-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 12px; }
/* a course code is Latin and numeric — uppercase belongs, tabular figures keep a
   column of codes aligned */
.course-code { font-size: 0.75rem; font-weight: 800; text-transform: uppercase;
    font-variant-numeric: tabular-nums;
    color: var(--primary); background: var(--primary-light); padding: 4px 10px; border-radius: 20px; }
.qr-icon { font-size: 1.4rem; color: var(--text-muted); }
.course-card:hover .qr-icon { color: var(--primary); }
.course-name { font-size: 0.95rem; font-weight: 700; color: var(--text-primary); line-height: 1.4; margin-bottom: 4px; }
.scan-cta {
    margin-top: 16px; padding: 9px 14px;
    background: var(--primary); color: white;
    border-radius: var(--radius-sm);
    font-size: 0.83rem; font-weight: 700;
    text-align: center; display: flex; align-items: center; justify-content: center;
    transition: background 0.15s;
}
.course-card:hover .scan-cta { background: var(--primary-dark); }

/* ─── Code ───────────────────────────────────────────────────────────────────── */
code {
    font-family: 'Courier New', monospace;
    font-size: 0.82rem;
    background: var(--bg-app);
    padding: 2px 7px;
    border-radius: 4px;
    color: var(--primary);
}

/* ─── Dark theme ────────────────────────────────────────────────────────────────
   Every surface/border/text color in the whole app is driven by the variables in
   :root, so a dark palette is just a re-definition of those same variables. The
   toggle sets data-theme="dark" on <html> (persisted in localStorage, applied
   before first paint so there's no white flash). Sidebar stays its own dark slate
   in both modes, so only the light surfaces flip. */
html[data-theme="dark"] { color-scheme: dark; }
[data-theme="dark"] {
    --primary:       #3b82f6;   /* a touch brighter so it stays vivid on dark */
    --primary-dark:  #2563eb;
    --primary-light: rgba(59,130,246,0.16);

    --bg-app:        #0b1220;
    --bg-panel:      #1e293b;

    --text-primary:  #f1f5f9;
    --text-secondary:#cbd5e1;
    --text-muted:    #94a3b8;

    --border-color:  #334155;

    --shadow-sm:     0 1px 3px rgba(0,0,0,0.40);
    --shadow-md:     0 4px 12px rgba(0,0,0,0.45);
    --shadow-lg:     0 8px 24px rgba(0,0,0,0.50);
    --shadow-xl:     0 16px 48px rgba(0,0,0,0.60);
}
/* The QR quiet-zone box and print pages keep their own explicit white — a QR needs
   a light background to scan, so we never let the dark theme touch those. */

/* Theme toggle button in the header (and the login language row). */
.btn-theme {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; padding: 0;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-color);
    background: var(--bg-panel); color: var(--text-secondary);
    cursor: pointer; font-size: 0.95rem; line-height: 1;
    /* explicit properties, never `all`: animating layout properties makes a control
       feel loose and can cost a frame on every hover */
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.btn-theme:hover { color: var(--primary); border-color: var(--primary); }

/* Notes rendered inside data-table cells: readable at any width — they wrap between
   words (never mid-word) and never collapse into a one-letter column. */
.nca-cellnote {
    display: block; white-space: normal;
    overflow-wrap: break-word; word-break: normal; line-height: 1.65;
    min-width: 230px; max-width: 320px;
}

/* ── The two facts every request row now states about its lecture ─────────────
   Which DAY it runs on, and whether it is one lecture shared by several courses.
   Chips rather than sentences: they sit under a course code in a dense table and
   have to be readable at a glance without stretching the column. */
.nca-slot-when, .nca-slot-merged {
    display: inline-flex; align-items: center; gap: 5px;
    margin-top: 4px; padding: 2px 8px;
    border-radius: 999px; font-size: 0.7rem; font-weight: 800;
    white-space: nowrap; max-width: 100%;
}
.nca-slot-when {
    background: rgba(100,116,139,0.12); border: 1px solid rgba(100,116,139,0.32);
    color: #475569; white-space: normal;
}
/* The label is what makes the line unambiguous, so it must not read as decoration. */
.nca-slot-when .nca-slot-lbl { font-weight: 800; opacity: .78; }
/* The merged chip is deliberately the louder of the two: it changes what an
   approval DOES, while the day only helps you recognise the lecture. */
.nca-slot-merged {
    background: rgba(6,182,212,0.10); border: 1px solid rgba(6,182,212,0.38);
    color: #0e7490; white-space: normal;
}
.nca-slot-when i, .nca-slot-merged i { font-size: 0.62rem; opacity: .85; }
/* The card cell sets `overflow-wrap: anywhere` so a long code or email cannot push a
   phone sideways — but "anywhere" means exactly that, and it was splitting Arabic words
   mid-letter ("المطلو / ب:"). These chips hold short words and no runaway strings, so
   they opt back into breaking only BETWEEN words; the label never breaks at all. */
.nca-slot-when, .nca-slot-merged { overflow-wrap: break-word; word-break: normal; }
.nca-slot-when .nca-slot-lbl { white-space: nowrap; }
/* Several lines stack: give them their own row each instead of running together. */
.nca-slot-when + .nca-slot-when, .nca-slot-when + .nca-slot-merged { margin-top: 3px; }
:root[data-theme="dark"] .nca-slot-when {
    background: rgba(148,163,184,0.14); border-color: rgba(148,163,184,0.32); color: #cbd5e1;
}
:root[data-theme="dark"] .nca-slot-merged {
    background: rgba(6,182,212,0.14); border-color: rgba(6,182,212,0.40); color: #67e8f9;
}
