/*
 * CCESS dashboard — integration layer for the vendor theme in ./css/ and ./js/.
 *
 * The supplied theme ships no example HTML and two competing brand layers, so a
 * thin integration file is unavoidable. It does four jobs and nothing else:
 *
 *   1. Unifies both brand layers onto ONE palette by re-pointing their custom
 *      properties. crm-dashboard.css drives 25 rules off four --crm-* variables
 *      and global.css drives its own off four --cms-* ones; left alone the two
 *      sets of !important primary rules disagree on every button and page link.
 *
 *   2. Supplies the RTL shell. app-rtl.css is Bootstrap's RTL *grid* only — it has
 *      no shell rules at all — so the fixed sidebar and the .main-content offset
 *      would otherwise stay pinned to the left in Arabic.
 *
 *   3. Styles what the shell markup needs but the theme never defines: .nav-heading
 *      (the theme only toggles its display), the sidebar scroll region, and the
 *      sidebar/topnav brand divider.
 *
 *   4. Accessibility the theme omits: a visible focus ring, a skip link, and a
 *      reduced-motion escape hatch.
 *
 * PALETTE (Phase B2 — the approved CCESS dashboard palette).
 *
 * Primary / accent : #E94E3D  (exact, as specified — never altered)
 * Shell chrome     : #F4F4F4  (sidebar, topnav, login background)
 *
 * The B2 palette replaces B1's navy + gold entirely. Both requested colours are
 * preserved exactly as backgrounds; only the FOREGROUNDS are chosen, because the
 * requested pair does not carry text safely on its own:
 *
 *   #E94E3D + #FFFFFF = 3.74:1  FAILS WCAG AA for normal text
 *   #E94E3D + #141414 = 4.93:1  PASSES            <- what is used
 *   #F4F4F4 + #1F1F1F = 14.99:1 PASSES
 *
 * Two consequences worth knowing when editing this file:
 *
 *   1. Hover on a coral surface must get LIGHTER, not darker. Darkening the coral
 *      lowers its contrast against the dark foreground (#D43F2E + #141414 = 3.99:1,
 *      which fails), so --ccess-primary-hover is a lighter tint at 5.78:1.
 *
 *   2. Coral cannot be used as TEXT on a light background: #E94E3D on white is
 *      3.74:1. --ccess-primary-readable (#C63A2A, 5.20:1 on white / 4.73:1 on the
 *      shell) is the token for links, .text-primary and icon accents. The exact
 *      #E94E3D is still what every accent BACKGROUND uses.
 *
 * Bootstrap's own .text-muted (#6C757D) is only 4.26:1 on #F4F4F4, so it is
 * re-pointed too — otherwise the shell would fail on every secondary label.
 */

:root {
    /* ---- CCESS canonical tokens ---- */
    --ccess-primary: #E94E3D;
    --ccess-primary-hover: #ED6555;
    --ccess-primary-active: #E74B3A;
    --ccess-primary-readable: #C63A2A;
    --ccess-primary-alpha: rgba(233, 78, 61, 0.10);
    --ccess-on-primary: #141414;

    --ccess-shell-bg: #F4F4F4;
    --ccess-surface: #FFFFFF;

    /*
     * Card/panel surface, as distinct from the page surface behind it.
     *
     * In LIGHT mode the two are the same white — a card on the white content area is
     * separated by its border, not by a fill, which is what Part AG established. The
     * token exists so DARK mode can pull them apart (page charcoal, card one step
     * lighter) without every card rule needing a dark-specific duplicate.
     */
    --ccess-card-bg: var(--ccess-surface);

    /*
     * ---- Sidebar geometry ----
     *
     * The group headings have to line up with the LABEL column, not the icon column,
     * and the label column's position is the sum of three values that live on two
     * other rules. Expressing them as tokens is what stops the heading indent and the
     * label indent drifting apart the next time the icon size or the gap is touched:
     * the heading is derived from them rather than restating a number that happens to
     * match today.
     */
    --ccess-sidebar-gutter: 1rem;
    --ccess-sidebar-icon-size: 1.35rem;
    --ccess-sidebar-icon-gap: 0.65rem;
    --ccess-sidebar-label-inset: calc(
        var(--ccess-sidebar-gutter) + var(--ccess-sidebar-icon-size) + var(--ccess-sidebar-icon-gap)
    );

    /*
     * Sidebar scrollbar thumb (Phase D0, Part AH). A neutral medium grey that reads
     * against the --ccess-shell-bg sidebar without dominating it; it becomes
     * --ccess-primary on hover.
     */
    --ccess-scrollbar-thumb: #B9BDC2;
    --ccess-text: #1F1F1F;
    --ccess-text-muted: #5C636A;
    --ccess-border: #DCDCDC;
    --ccess-table-head-bg: #ECECEC;

    /*
     * ---- Vendor variables, re-pointed rather than edited ----
     *
     * global.css drives its rules off --cms-* and crm-dashboard.css off --crm-*.
     * Re-pointing them here is what keeps the vendor files in ./css/ untouched.
     *
     * --cms-color-dark is NOT set to the shell grey even though global.css uses it
     * as the sidebar/topnav background. It is also the foreground on coral buttons,
     * the .cms-page-title ink and the table-head text colour, so setting it to
     * #F4F4F4 would make four rules illegible. It stays dark ink, and the two chrome
     * backgrounds that genuinely need #F4F4F4 are overridden explicitly below.
     */
    --cms-color-dark: var(--ccess-on-primary);
    --cms-color-primary: var(--ccess-primary);
    --cms-color-primary-hover: var(--ccess-primary-hover);
    --cms-color-primary-readable: var(--ccess-primary-readable);

    --crm-primary: var(--ccess-primary-readable);
    --crm-primary-dark: #A82F21;
    --crm-primary-light: var(--ccess-primary-hover);
    --crm-primary-alpha: var(--ccess-primary-alpha);
}

/* ============================================================ B2 CHROME ===
 * global.css hardcodes light-on-dark foregrounds for the sidebar and topnav
 * (`color: #f1f1f1 !important`, `color: #fff !important`) because it was written
 * for a near-black chrome. Those are literals, not variables, so re-pointing the
 * palette is not enough — on the #F4F4F4 shell they would be invisible. These
 * overrides are the minimum needed to invert that, and they live here rather than
 * in the vendor file.
 */
.cms-sidebar,
.cms-topnav {
    background: var(--ccess-shell-bg) !important;
    border-color: var(--ccess-border) !important;
}

.cms-sidebar .text-muted,
.cms-sidebar .toggle-btn,
.cms-sidebar .navbar-nav .nav-link,
.cms-sidebar .nav-heading,
.cms-topnav .nav-link,
.cms-topnav .navbar-toggler,
.cms-topnav .navbar-toggler-icon,
.cms-topnav {
    color: var(--ccess-text) !important;
}

.cms-sidebar .navbar-brand,
.cms-sidebar .navbar-brand:hover,
.cms-sidebar .navbar-brand:focus {
    color: var(--ccess-text);
}

/* Icons carry the accent, but as a readable tint on a light surface. */
.cms-sidebar .navbar-nav .nav-link i {
    color: var(--ccess-primary-readable) !important;
}

.cms-sidebar .navbar-nav .nav-link:hover {
    color: var(--ccess-text) !important;
    background: var(--ccess-primary-alpha) !important;
}

/* Active item: the exact requested coral, with the AA-passing dark foreground. */
.cms-sidebar .navbar-nav .nav-item.active > .nav-link,
.cms-sidebar .navbar-nav .nav-item.active > .nav-link:hover {
    color: var(--ccess-on-primary) !important;
    background: var(--ccess-primary) !important;
}

.cms-sidebar .navbar-nav .nav-item.active > .nav-link i {
    color: var(--ccess-on-primary) !important;
}

.cms-sidebar .navbar-brand,
.cms-topnav {
    border-bottom: 1px solid var(--ccess-border);
}

.cms-sidebar .navbar-brand {
    border-bottom-color: var(--ccess-border);
}

/* The shell itself, so the light chrome does not float on the theme's default. */
body.dashboard-page {
    background: var(--ccess-shell-bg);
    color: var(--ccess-text);
}

/*
 * Bootstrap's muted grey fails AA on the new shell background. Scoped to the
 * dashboard so nothing outside it is affected.
 */
.dashboard-page .text-muted,
.auth-page .text-muted {
    color: var(--ccess-text-muted) !important;
}

/* ----------------------------------------- vendor literals, neutralised ---
 * Re-pointing the custom properties covers most of the vendor theme, but three
 * loaded files also bake the old brand in as raw literals, which no variable can
 * reach. Each one below is a specific literal that would otherwise still render
 * gold or navy. Listed with its source so the list stays auditable.
 */

/* global.css:280 — form focus ring is a hardcoded gold glow. */
.dashboard-page .form-control:focus,
.dashboard-page .custom-select:focus,
.auth-page .form-control:focus,
.form-control:focus {
    border-color: var(--ccess-primary) !important;
    box-shadow: 0 0 0 0.2rem var(--ccess-primary-alpha) !important;
}

/* global.css:288 — headings are forced to --cms-color-dark, i.e. near-black ink.
 * Correct for body copy, but the page title reads better as the shell ink. */
.dashboard-page h1,
.dashboard-page h2,
.dashboard-page h3,
.dashboard-page h4,
.dashboard-page h5,
.dashboard-page h6,
.dashboard-page strong,
.cms-page-title {
    color: var(--ccess-text) !important;
}

/*
 * sweetalert2-custom.css:118-152 — the delete dialog's confirm button, its hover
 * and focus rings, the cancel button and the warning icon are all hardcoded gold
 * and #1e1e1e. Without these the confirmation dialog would be the last gold
 * surface in the dashboard.
 */
.ahcl-swal-confirm {
    background-color: var(--ccess-primary) !important;
    color: var(--ccess-on-primary) !important;
}

.ahcl-swal-confirm:hover {
    background-color: var(--ccess-primary-hover) !important;
    box-shadow: 0 6px 20px var(--ccess-primary-alpha) !important;
}

.ahcl-swal-confirm:focus {
    box-shadow: 0 0 0 3px var(--ccess-primary-alpha) !important;
}

.ahcl-swal-cancel {
    background-color: #E9ECEF !important;
    color: var(--ccess-text) !important;
}

.ahcl-swal-cancel:hover {
    background-color: #DEE2E6 !important;
    box-shadow: none !important;
}

.ahcl-swal-cancel:focus {
    box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.12) !important;
}

/*
 * delete-confirmation.js:36 passes iconColor: '#d1a52a', which SweetAlert applies
 * as an INLINE style on the icon — so this needs !important to win.
 */
.swal2-icon.swal2-warning,
.swal2-icon.swal2-warning.swal2-modern-icon {
    border-color: var(--ccess-primary) !important;
    color: var(--ccess-primary-readable) !important;
}

.swal2-icon.swal2-warning .swal2-icon-content {
    color: var(--ccess-primary-readable) !important;
}

/* crm-dashboard.css:94,158,235 — navy-tinted shadows and the toggle hover. */
.stat-card:hover {
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.10) !important;
}

.crm-page-progress {
    background: linear-gradient(90deg, var(--ccess-primary), var(--ccess-primary-hover)) !important;
    box-shadow: 0 0 12px var(--ccess-primary-alpha);
}

.theme-toggle-btn:hover,
.theme-toggle-btn:focus {
    background: var(--ccess-primary-alpha);
    border-color: var(--ccess-primary);
    color: var(--ccess-primary-readable);
}

/*
 * app-light.css:143 / 1818+ — the theme's own default blue (#1b68ff) still drives
 * bare links and the sidebar active marker bar.
 */
.dashboard-page a:not(.btn):not(.nav-link):not(.dropdown-item):not(.navbar-brand),
.auth-page a:not(.btn) {
    color: var(--ccess-primary-readable);
}

.vertical .sidebar-left .navbar-nav > .nav-item.active:after,
.vertical.hover .sidebar-left .navbar-nav > .nav-item.active:after,
.narrow.open .sidebar-left .navbar-nav > .nav-item.active:after,
.cms-sidebar .navbar-nav .nav-item.active::after {
    background-color: var(--ccess-primary) !important;
}

/* Pagination: crm-dashboard.css owns .page-link, global.css the active state. */
.dashboard-page .page-item.active .page-link,
.dashboard-page .page-item.active .page-link:hover,
.badge-warning {
    color: var(--ccess-on-primary) !important;
    background: var(--ccess-primary) !important;
    border-color: var(--ccess-primary) !important;
}

.dashboard-page .page-link {
    color: var(--ccess-primary-readable);
}

/* Cards and inputs sit on the shell, so their borders need the neutral token. */
.dashboard-page .card,
.auth-page .card {
    border-color: var(--ccess-border);
}

/* ------------------------------------------------------------------ shell ---
 * The sidebar is position:fixed with an explicit left:0, and .main-content /
 * .topnav carry a matching margin-left. All three have to be mirrored for RTL.
 */
html[dir="rtl"] .vertical .sidebar-left,
html[dir="rtl"] .vertical.hover .sidebar-left,
html[dir="rtl"] .narrow.open .sidebar-left {
    left: auto;
    right: 0;
    box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.05);
}

html[dir="rtl"] .vertical .topnav,
html[dir="rtl"] .vertical .main-content,
html[dir="rtl"] .vertical.hover .topnav,
html[dir="rtl"] .vertical.hover .main-content,
html[dir="rtl"] .narrow.open .topnav,
html[dir="rtl"] .narrow.open .main-content {
    margin-left: 0;
    margin-right: 16rem;
}

html[dir="rtl"] .vertical.collapsed .main-content,
html[dir="rtl"] .vertical.collapsed .topnav,
html[dir="rtl"] .vertical.narrow .main-content,
html[dir="rtl"] .vertical.narrow .topnav {
    margin-left: 0;
    margin-right: 5rem;
}

/* The active-item marker bar sits at left:-1rem in LTR. */
html[dir="rtl"] .vertical .sidebar-left .navbar-nav > .nav-item.active:after,
html[dir="rtl"] .vertical.hover .sidebar-left .navbar-nav > .nav-item.active:after,
html[dir="rtl"] .narrow.open .sidebar-left .navbar-nav > .nav-item.active:after {
    left: auto;
    right: -1rem;
}

/* Mirror of the theme's own mobile block, where the sidebar collapses to zero
 * width and .collapsed re-opens it as an overlay. */
@media (max-width: 767.98px) {
    html[dir="rtl"] .vertical .topnav,
    html[dir="rtl"] .vertical .main-content,
    html[dir="rtl"] .vertical.hover .topnav,
    html[dir="rtl"] .vertical.hover .main-content,
    html[dir="rtl"] .vertical.narrow .topnav,
    html[dir="rtl"] .vertical.narrow .main-content {
        margin-right: 0;
    }

    html[dir="rtl"] .vertical.collapsed .topnav,
    html[dir="rtl"] .vertical.collapsed .main-content,
    html[dir="rtl"] .vertical.narrow.open .topnav,
    html[dir="rtl"] .vertical.narrow.open .main-content {
        margin-right: 16rem;
    }
}

/* ---------------------------------------------------------------- sidebar ---
 * .nav-heading only ever gets `display` toggled by the theme, so the group
 * labels need their own type treatment.
 */
.sidebar-left .nav-heading {
    /*
     * Logical, not the old `padding: 1.1rem 1rem 0.35rem` shorthand. Same computed
     * values in LTR; the inline edges now follow the text direction, which is what
     * the RTL alignment rule further down builds on. `text-align: start` is what the
     * heading already inherited from `dir` — stated here so the intent is explicit
     * and a stray `text-align: left` cannot quietly take over.
     */
    padding-block: 1.1rem 0.35rem;
    padding-inline: var(--ccess-sidebar-gutter);
    text-align: start;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    opacity: 0.6;
}

.cms-sidebar .nav-heading {
    color: var(--ccess-text-muted);
}

/* `gap` rather than a Bootstrap ml-* utility, so the icon/label spacing mirrors
 * itself in RTL instead of collapsing onto the wrong side. */
.sidebar-left .navbar-nav .nav-link {
    display: flex;
    align-items: center;
    gap: var(--ccess-sidebar-icon-gap);
    padding: 0.55rem var(--ccess-sidebar-gutter);
    font-size: 0.9rem;
}

/* Icon column stays a fixed width so labels line up across every group. */
.sidebar-left .navbar-nav .nav-link > .fe {
    flex: 0 0 var(--ccess-sidebar-icon-size);
    font-size: 1rem;
    text-align: center;
}

.sidebar-left .navbar-brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 1rem;
    margin: 0;
    border-bottom: 1px solid var(--ccess-border);
}



.sidebar-left .navbar-brand img {
    height: 34px;
    width: auto;
}

.sidebar-left .brand-text {
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.15;
    white-space: nowrap;
}

/* Collapsed rail hides the wordmark but keeps the logo centred. */
.vertical.collapsed .sidebar-left .brand-text,
.vertical.narrow .sidebar-left .brand-text {
    display: none;
}

.vertical.collapsed .sidebar-left .navbar-brand,
.vertical.narrow .sidebar-left .navbar-brand {
    justify-content: center;
}

@media (max-width: 767.98px) {
    .vertical.collapsed .sidebar-left .brand-text,
    .vertical.narrow.open .sidebar-left .brand-text {
        display: inline-block;
    }

    .vertical.collapsed .sidebar-left .navbar-brand,
    .vertical.narrow.open .sidebar-left .navbar-brand {
        justify-content: flex-start;
    }
}

/* ----------------------------------------------------------------- topnav --- */
.cms-topnav {
    min-height: 3.5rem;
}

.cms-topnav .dropdown-menu {
    color: var(--ccess-text);
}

.cms-topnav .nav {
    align-items: center;
    gap: 0.5rem;
}

/*
 * Logical spacing, not Bootstrap's physical margin utilities. app-rtl.css covers
 * only the grid, so a margin-right would stay on the right in Arabic.
 */
.cms-topnav .nav-link.d-flex {
    gap: 0.5rem;
}

.dropdown-item > .fe {
    margin-inline-end: 0.5rem;
}

/* ---------------------------------------------------------------- avatars ---
 * Used by the topnav trigger and by the inbox list on the dashboard home, so it is
 * a standalone class rather than a topnav-scoped one.
 */
.avatar-initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
    color: var(--cms-color-dark);
    background: var(--cms-color-primary);
}

.avatar-initials-lg {
    width: 44px;
    height: 44px;
    font-size: 1rem;
}

.avatar-initials-xl {
    width: 120px;
    height: 120px;
    font-size: 2.75rem;
}

/* ------------------------------------------------------------- stat cards ---
 * The theme animates .stat-card-cta in from translateX(-4px), which points the
 * wrong way once the page is mirrored.
 */
html[dir="rtl"] .stat-card-cta {
    transform: translateX(4px);
}

html[dir="rtl"] .stat-card-link:hover .stat-card-cta,
html[dir="rtl"] .stat-card-link:focus-visible .stat-card-cta {
    transform: translateX(0);
}

/* Keep the numbers on one optical baseline across a row of tiles. */
.stat-card .stat-value {
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
    margin-bottom: 0;
}

.stat-card .stat-label {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 0.15rem;
}

/* Reserves room between the number block and the icon without a physical padding. */
.stat-card .stat-text {
    min-width: 0;
    padding-inline-end: 0.5rem;
}

/* -------------------------------------------------------- language switch ---
 * The topnav toggle. Styled as a quiet control rather than a button: it sits beside
 * the user menu and must not compete with the page's primary action.
 */
.cms-locale-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ccess-text) !important;
    text-decoration: none !important;
    border-radius: 6px;
}

.cms-locale-switch:hover,
.cms-locale-switch:focus {
    background: var(--ccess-primary-alpha);
    color: var(--ccess-primary-readable) !important;
}

/* ------------------------------------------------------- bilingual forms ---
 * Phase B2.1 Part F: every *_ar / *_en pair is grouped into two language cards
 * rather than interleaved column-by-column.
 *
 * Cards rather than JS tabs, deliberately:
 *   - a validation error on an English field can never be hidden behind an
 *     inactive tab, which is the failure mode that makes a form feel broken
 *   - both languages are visible at once, so an editor can compare them
 *   - no extra JS, so nothing to break and nothing to load
 *
 * The accent edge is on the INLINE start, so it sits left in LTR and right in RTL
 * without a second rule.
 */
.lang-card {
    border: 1px solid var(--ccess-border);
    border-radius: 8px;
    height: 100%;
}

.lang-card > .card-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 1rem;
    background: var(--ccess-shell-bg);
    border-bottom: 1px solid var(--ccess-border);
    border-inline-start: 3px solid var(--ccess-primary);
}

.lang-card > .card-body {
    padding: 1rem;
}

/* The language name is written in its own language, so it must also be laid out
 * in its own direction regardless of the surrounding interface. */
.lang-card-ar > .card-header .lang-name {
    direction: rtl;
}

.lang-card-en > .card-header .lang-name {
    direction: ltr;
}

.lang-card .lang-name {
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--ccess-text);
}

.lang-card .lang-code {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ccess-text-muted);
}

/* An error anywhere inside a language card is flagged on the card itself, so it is
 * visible without scrolling the whole form. */
/* margin-inline-start, not Bootstrap's ml-auto, so the icon stays on the trailing
 * edge in RTL too. */
.lang-card-alert {
    margin-inline-start: auto;
}

.lang-card.has-error > .card-header {
    border-inline-start-color: #dc3545;
}

.lang-card.has-error .lang-name {
    color: #b02a37;
}

/*
 * Inputs keep their own direction even when the interface direction differs — an
 * Arabic field is RTL on an English dashboard and vice versa. Technical values stay
 * LTR in both: an email, URL, slug or phone number is not prose.
 */
input[dir="ltr"],
textarea[dir="ltr"] {
    text-align: left;
}

input[dir="rtl"],
textarea[dir="rtl"] {
    text-align: right;
}

input[type="email"],
input[type="url"],
input[type="tel"],
input[type="number"],
input[type="date"],
input[type="time"],
input[name="slug"],
input[name$="_url"],
input[name="icon"] {
    direction: ltr;
    text-align: left;
}

/* ----------------------------------------------------------- trash tabs ---
 * The Active / Trash switch on every deletable module's index.
 *
 * global.css sets `.nav-tabs .nav-link { margin-right: 0 !important;
 * margin-left: 1.7rem !important }`, a physical RTL-oriented gap that leaves a
 * stray indent in LTR. Neutralised here and replaced with a logical gap on the
 * list, so the tabs sit correctly in both directions.
 */
.cms-trash-tabs {
    gap: 0.25rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--ccess-border);
}

.cms-trash-tabs .nav-link {
    margin-left: 0 !important;
    margin-right: 0 !important;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--ccess-text-muted);
    border: 1px solid transparent;
    border-bottom: none;
}

.cms-trash-tabs .nav-link:hover {
    color: var(--ccess-text);
    background: var(--ccess-primary-alpha);
}

/* The selected tab carries the accent, as a bottom rule rather than a filled
 * block — a coral-filled tab would compete with the primary action button. */
.cms-trash-tabs .nav-link.active {
    color: var(--ccess-text);
    background: var(--ccess-surface);
    border-color: var(--ccess-border);
    border-bottom: 2px solid var(--ccess-primary);
    font-weight: 600;
}

/* A trashed row reads as inactive without relying on colour alone. */
.table tr.is-trashed td {
    opacity: 0.72;
}

.table tr.is-trashed td:first-child {
    box-shadow: inset 3px 0 0 var(--ccess-primary);
}

html[dir="rtl"] .table tr.is-trashed td:first-child {
    box-shadow: inset -3px 0 0 var(--ccess-primary);
}

/* ------------------------------------------------------------ inbox list ---
 * `gap` instead of a pl-* utility so the avatar and the text swap sides in RTL.
 */
.inbox-item {
    display: flex;
    gap: 0.75rem;
}

.inbox-item-body {
    min-width: 0;
}

.section-heading {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ccess-text-muted);
    margin: 1.5rem 0 0.75rem;
}

/* -------------------------------------------------------------- auth page ---
 * Replaces css/login.css, which was a bespoke two-column flex layout with its own
 * colours. The theme has no login screen of its own, so this is a plain centred
 * card built from the theme's card and spacing primitives.
 */
.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: var(--ccess-shell-bg);
}

.auth-page > main {
    width: 100%;
}

.auth-page-shell {
    width: 100%;
    max-width: 26rem;
    margin: 0 auto;
}

.auth-card {
    border: none;
    border-radius: 12px;
}

.auth-logo {
    max-width: 150px;
    height: auto;
}

.auth-page-shell > p {
    color: var(--ccess-text-muted) !important;
}

/* ------------------------------------------------------- file-picker preview ---
 * Injected by ccess-dashboard.js next to any input[type=file]. Small enough not to
 * push the submit button below the fold on a form with several image fields.
 */
.cms-file-chosen {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
    min-height: 0;
}

.cms-file-chosen:empty {
    display: none;
}

.cms-file-thumb {
    width: 44px;
    height: 44px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--ccess-border);
    background: var(--ccess-surface);
    flex: 0 0 auto;
}

.cms-file-name {
    font-size: 0.8rem;
    color: var(--ccess-text-muted);
    overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------ alerts ---
 * Bootstrap's .alert-dismissible reserves padding on the right and floats .close
 * there. app-rtl.css does not cover components, so both have to be mirrored.
 */
html[dir="rtl"] .alert-dismissible {
    padding-right: 1.25rem;
    padding-left: 4rem;
}

html[dir="rtl"] .alert-dismissible .close {
    right: auto;
    left: 0;
}

/* ------------------------------------------------------------ cards/tables ---
 * Applied globally rather than per view. Phase B1 rewrites ten representative
 * screens, but all 89 share these primitives, so theming them here is what stops
 * the dashboard looking half-converted while the remaining modules wait for B2.
 */

/*
 * Most module views open with their own <div class="container-fluid">, which now
 * sits inside the layout's. Bootstrap would apply the 15px gutter twice.
 */
.main-content > .container-fluid .container-fluid {
    padding-right: 0;
    padding-left: 0;
}

.card {
    border-radius: 8px;
}

.card > .card-header {
    background-color: var(--ccess-card-bg);
    border-bottom: 1px solid var(--ccess-border);
    padding: 0.9rem 1.25rem;
}

.card > .card-header .card-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--cms-color-dark);
    margin-bottom: 0;
}

/*
 * Table heads get the same navy treatment global.css defines for .cms-table-head,
 * applied by structure so the 79 views B1 does not touch match the ten it does.
 */
.card .table > thead > tr > th,
.card .table thead th {
    color: var(--ccess-text);
    background: var(--ccess-table-head-bg);
    border-top: none;
    border-bottom: none;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
    vertical-align: middle;
}

.card .table td {
    vertical-align: middle;
}

/* Action columns hold two to four small buttons; without this they collide. */
.table .btn-sm + .btn-sm,
.table .btn-sm + form,
.table form + .btn-sm,
.table form + form {
    margin-inline-start: 0.25rem;
}

/*
 * Overflow containment for the detail screens.
 *
 * The 24 two-column tables on the detail screens sit directly in a .card-body with
 * no .table-responsive wrapper and a fixed inline width on the label column
 * (120–190px). Combined with the theme's `.main-content { overflow: hidden }` a long
 * unbreakable value — a slug, an email, an absolute URL — is CLIPPED rather than
 * scrolled, which puts the content out of reach entirely.
 *
 * Letting those values break is the fix that needs no wrapper markup, so it applies
 * to every screen including the ones B1 does not rewrite.
 */
.card .table td,
.card .table th {
    overflow-wrap: anywhere;
}

/* Below the shell breakpoint the fixed label widths leave too little for the value. */
@media (max-width: 767.98px) {
    .card .table th[style*="width"],
    .card .table td[style*="width"] {
        width: auto !important;
    }
}

/* An empty-state row must not inherit the uppercase head styling. */
.card .table tbody td.text-center.text-muted {
    text-transform: none;
    letter-spacing: normal;
}

/* ------------------------------------------------------- retired-class shim ---
 * `.row gutters` appears in 75 places across the dashboard. It came from the old
 * css/main.css, which is no longer loaded, and it tightens Bootstrap's 15px gutter
 * to 8px. Reproducing the two rules here keeps the spacing of every screen that
 * Phase B1 does not rewrite, instead of editing 75 call sites to say the same thing.
 *
 * Values are copied verbatim from public/css/main.css:6279-6286.
 */
.gutters {
    margin-right: -8px;
    margin-left: -8px;
}

.gutters > .col,
.gutters > [class*="col-"] {
    padding-right: 8px;
    padding-left: 8px;
}

/* ------------------------------------------------------------------ misc --- */

/* Long tables must scroll inside the card, never widen the page. */
.table-scroll {
    overflow-x: auto;
}

/* Bootstrap 4 has no gap utility and the theme adds none. */
.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    align-items: center;
}

/* ---------------------------------------------------------- accessibility ---
 * The theme's reset strips outlines from .btn and .nav-link without providing a
 * replacement, which leaves keyboard users with no visible position.
 */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
.nav-link:focus-visible,
.page-link:focus-visible,
[tabindex]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--cms-color-primary);
    outline-offset: 2px;
    box-shadow: none;
}

.cms-sidebar .nav-link:focus-visible,
.cms-topnav .nav-link:focus-visible,
.cms-topnav button:focus-visible {
    outline-color: var(--cms-color-primary);
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2100;
    padding: 0.6rem 1rem;
    font-weight: 600;
    color: var(--cms-color-dark);
    background: var(--cms-color-primary);
}

.skip-link:focus {
    left: 0.5rem;
    top: 0.5rem;
}

html[dir="rtl"] .skip-link {
    left: auto;
    right: -9999px;
}

html[dir="rtl"] .skip-link:focus {
    right: 0.5rem;
    left: auto;
}

@media (prefers-reduced-motion: reduce) {
    .vertical .sidebar-left,
    .vertical .main-content,
    .vertical .topnav,
    .crm-page-progress,
    .cms-sidebar .navbar-nav .nav-link {
        transition: none !important;
    }

    .submit-spinner {
        animation: none !important;
    }
}

/*
|--------------------------------------------------------------------------
| Phase D0 — main content surface and sidebar scrollbar
|--------------------------------------------------------------------------
|
| Still the integration layer: no vendor file under ./css/ is touched, and every
| value below comes from the tokens declared at the top of this file.
*/

/*
 * PART AF — the content area is WHITE, not the shell grey.
 *
 * The vendor's .main-content sets no background of its own, so it showed
 * body.dashboard-page's --ccess-shell-bg through. Manual QA flagged that: the
 * working surface should be white and the CHROME (sidebar, topnav) should be the
 * grey, which is the inverse of what was happening.
 *
 * The vendor rule already carries min-height: 100vh, so the white fills the
 * viewport on a short page instead of stopping where the content ends and leaving
 * a grey band above the footer. That is why this sets background only and does not
 * restate the height — restating it would duplicate a value that already works and
 * would have to be kept in step by hand.
 */
.vertical .main-content,
.vertical.hover .main-content,
.vertical.collapsed .main-content,
.vertical.narrow .main-content,
.narrow.open .main-content {
    background: var(--ccess-surface);
}

/*
 * The dashboard footer sits inside .main-content, so it inherits the white. It
 * keeps its own top border for separation.
 */
.main-footer {
    background: transparent;
    border-top-color: var(--ccess-border);
}

/*
 * PART AG — nested components stay distinguishable on white.
 *
 * A white card on a white page has no edge. The theme gives cards a very light
 * shadow that read well against grey and disappears against white, so cards get
 * an explicit neutral border instead. This is a border, not a new colour: no blue
 * or gold chrome returns, the primary stays #E94E3D, and the sidebar/topnav keep
 * --ccess-shell-bg.
 */
.main-content .card {
    border: 1px solid var(--ccess-border);
}

/*
 * Table headers, toolbars and the trash tabs need the faint grey they used to get
 * from the page behind them.
 */
.main-content .table thead th {
    background: var(--ccess-table-head-bg);
    border-bottom-color: var(--ccess-border);
}

.main-content .table td,
.main-content .table th {
    border-top-color: var(--ccess-border);
}

.main-content .card-header {
    background: transparent;
    border-bottom-color: var(--ccess-border);
}

/*
 * Inputs on a white card: the theme's default border is nearly invisible against
 * it, which makes a form look like floating labels.
 */
.main-content .form-control,
.main-content .custom-select,
.main-content .form-control-file {
    border-color: var(--ccess-border);
}

.main-content .form-control:focus,
.main-content .custom-select:focus {
    border-color: var(--ccess-primary);
    box-shadow: 0 0 0 0.2rem var(--ccess-primary-alpha);
}

/*
|--------------------------------------------------------------------------
| PARTS AH / AI — the sidebar navigation scrollbar
|--------------------------------------------------------------------------
|
| SCOPED TO THE SIDEBAR ONLY. Every selector below is prefixed with
| .cms-sidebar / #leftSidebar, so no other scrollable region in the dashboard —
| and nothing in the browser at large — is restyled. A bare `::-webkit-scrollbar`
| rule here would change every scrollbar on every dashboard page, including inside
| tables and modals, which is not what was asked for.
|
| .sidebar-left is the element that actually scrolls: the vendor sets
| `overflow-y: auto; height: 100%` on it.
*/

/* Firefox. Two properties, and it only supports a thumb/track pair. */
#leftSidebar.cms-sidebar {
    scrollbar-width: thin;
    scrollbar-color: var(--ccess-scrollbar-thumb) transparent;
}

/* WebKit and Blink. */
#leftSidebar.cms-sidebar::-webkit-scrollbar {
    width: 7px;
}

#leftSidebar.cms-sidebar::-webkit-scrollbar-track {
    /*
     * Transparent rather than a grey: the sidebar is already
     * --ccess-shell-bg, and painting a second grey over it produced a visible
     * channel down the edge of the nav.
     */
    background: transparent;
}

#leftSidebar.cms-sidebar::-webkit-scrollbar-thumb {
    background: var(--ccess-scrollbar-thumb);
    border-radius: 999px;
}

#leftSidebar.cms-sidebar::-webkit-scrollbar-thumb:hover,
#leftSidebar.cms-sidebar::-webkit-scrollbar-thumb:active {
    background: var(--ccess-primary);
}

/*
 * Firefox has no hover pseudo-class for a scrollbar thumb, so the coral is applied
 * when the sidebar itself is hovered — the closest equivalent it supports.
 */
#leftSidebar.cms-sidebar:hover {
    scrollbar-color: var(--ccess-primary) transparent;
}

/*
 * PART AI — nothing here adds padding, margin or width to the sidebar, so the nav
 * links do not shift and the 16rem width is unchanged in either direction. The
 * scrollbar is placed by the browser on the inline-end edge, which is the right
 * edge in LTR and the left edge in RTL automatically; no direction-specific rule
 * is needed and adding one would fight the browser.
 *
 * At the 390px mobile drawer the same element scrolls, so the same 7px thumb
 * applies there — narrow enough not to crowd the links, wide enough to drag.
 */

/*
|--------------------------------------------------------------------------
| RTL sidebar — group headings on the label column
|--------------------------------------------------------------------------
|
| THE BUG. A group heading sat 2rem closer to the outer edge than the links it
| heads, so in Arabic the eight headings (لوحة التحكم، المحتوى، الوسائط، الوظائف،
| الطلبات والرسائل، الصفحة الرئيسية، الإعدادات، الحساب) formed a second, misaligned
| column hanging off the right edge of the nav.
|
| WHY. A heading is padded by the sidebar gutter alone (1rem), but a link's LABEL
| starts after the gutter PLUS the fixed icon column PLUS the icon gap
| (1 + 1.35 + 0.65 = 3rem). The heading was therefore aligned to the ICONS, not to
| the text it introduces. Nothing was direction-specific about that — the same 2rem
| offset exists in LTR — but it only reads as broken in RTL, where the eye follows
| the right edge and the headings visibly break the text column.
|
| SCOPE. RTL only, as specified: English keeps its current heading-over-icon
| indent, byte for byte. The fix adds an inline-START padding, so it is the one
| declaration that differs between the two directions — no duplicated RTL block, and
| no compensation for the scrollbar (the browser places that on the inline-end edge
| and it is 7px wide, nowhere near the 3rem the headings move).
*/
html[dir="rtl"] .sidebar-left .nav-heading {
    padding-inline-start: var(--ccess-sidebar-label-inset);
}

/*
 * app-light.css:8758 pins `text-align: left` on every .nav-item — a physical value
 * that does not mirror, so a nav label long enough to wrap put its second line on
 * the wrong edge in Arabic. Neutralised for RTL only, at a specificity that beats
 * the vendor's four-class selector. LTR still computes to `left`, unchanged.
 */
html[dir="rtl"] .vertical .sidebar-left .navbar-nav > .nav-item,
html[dir="rtl"] .vertical.hover .sidebar-left .navbar-nav > .nav-item,
html[dir="rtl"] .narrow.open .sidebar-left .navbar-nav > .nav-item {
    text-align: start;
}

/*
 * global.css:? nudges a hovered link with `translateX(2px)`, which pushes INTO the
 * page in LTR and OUT of it in RTL. Mirrored so the motion means the same thing in
 * both directions instead of drifting the label away from its heading.
 */
html[dir="rtl"] .cms-sidebar .navbar-nav .nav-link:hover {
    transform: translateX(-2px);
}

/*
|--------------------------------------------------------------------------
| DARK MODE
|--------------------------------------------------------------------------
|
| THE ROOT CAUSE. Dark mode swaps app-light.css for app-dark.css, but THIS file is
| loaded after both and its palette was declared unconditionally on :root. So dark
| mode rendered the vendor's dark sheet with the LIGHT integration layer stacked on
| top of it - and because most of those rules carry !important (they exist to beat
| global.css), the light values won. The working surface stayed #FFFFFF, the chrome
| stayed #F4F4F4, table heads stayed #ECECEC, and .text-muted was pinned to a grey
| chosen for contrast against white. That is why the secondary text "almost
| disappeared": it was near-black ink asked to read on a dark card.
|
| THE FIX. Everything in this file already draws from the --ccess-* tokens, so dark
| mode is a second value set for those tokens rather than a parallel stylesheet. The
| ~120 rules above inherit it for free, and no !important war is needed: a token
| redefinition wins wherever the token is consumed, however important the rule.
|
| Only the handful of places that hardcode a literal - SweetAlert's cancel button,
| the validation red, the black shadows - need an explicit dark counterpart, plus the
| three vendor dark defects called out inline below.
|
| SCOPING. `html.dark` AND `body.dark`. ccess-dashboard.js owns the body class; the
| pre-paint script in head.blade.php sets the html one, because <body> does not exist
| yet when it runs and without it a dark-mode reload would flash the light palette
| over the dark vendor sheet before the class landed. Either hook alone is enough for
| every rule here, so the two stay independent rather than one depending on the other.
|
| LIGHT MODE IS UNTOUCHED. Every declaration below is inside a .dark scope, so the
| light dashboard computes exactly what it did before this section existed.
|
| DARK PALETTE - measured, not eyeballed (WCAG 2.1 contrast against the surface the
| text actually sits on):
|
|   chrome      #16191C   sidebar, topnav, login page - recedes behind the content
|   page        #1E2226   .main-content working surface
|   card        #282D33   one step lighter than the page, so a card reads as raised
|   head        #31373E   table headers: distinct from the card, still subtle
|   text        #F1F3F5   14.4:1 on the page, 12.5:1 on a card
|   muted       #AEB6BE   7.8:1 on the page, 6.8:1 on a card  (was 3.4:1 - the bug)
|   border      #3C434A   1.38:1 against a card - a separator, not a line of noise
|   accent      #E94E3D   UNCHANGED, exactly as specified
|   accent-text #FF8B7A   6.1:1 on a card; the coral has to LIGHTEN to carry text on
|                         dark, the mirror of why it darkens to #C63A2A on white
*/
html.dark,
body.dark {
    --ccess-shell-bg: #16191C;
    --ccess-surface: #1E2226;
    --ccess-card-bg: #282D33;
    --ccess-table-head-bg: #31373E;

    --ccess-text: #F1F3F5;
    --ccess-text-muted: #AEB6BE;
    --ccess-border: #3C434A;

    /* Reads against the dark chrome the same way #B9BDC2 reads against the light one. */
    --ccess-scrollbar-thumb: #565E67;

    /*
     * The accent BACKGROUND is untouched (#E94E3D) and so is its foreground (#141414,
     * 4.93:1) - a coral button looks identical in both modes, which is the point of a
     * brand colour. Only the TEXT tint flips, and the alpha wash is lifted from 0.10
     * to 0.20 because a 10% coral veil is invisible on charcoal.
     */
    --ccess-primary-readable: #FF8B7A;
    --ccess-primary-alpha: rgba(233, 78, 61, 0.20);

    --crm-primary-dark: #FF6E59;

    /*
     * The vendor aliases are re-stated, not left to the :root indirection.
     *
     * `--crm-primary: var(--ccess-primary-readable)` on :root resolves against the
     * value --ccess-primary-readable holds ON :ROOT. If the mode class ever sits only
     * on <body>, :root still holds the LIGHT tint, so every crm-driven rule — stat
     * icons, the sidebar active label, pagination links — would keep #C63A2A while
     * everything around it went dark. Re-declaring them on the same element that
     * redefines the source token makes the palette independent of which hook landed.
     */
    --crm-primary: var(--ccess-primary-readable);
    --crm-primary-light: var(--ccess-primary-hover);
    --crm-primary-alpha: var(--ccess-primary-alpha);
    --cms-color-primary-readable: var(--ccess-primary-readable);
}

/*
 * The mode toggle itself. crm-dashboard.css gives it `border: 1px solid
 * rgba(0,0,0,0.1)` and `color: #495057` — a black hairline and dark-grey glyph, i.e.
 * 2.2:1 on the dark chrome. The gold sun it swaps in for dark mode is visible, but
 * the button around it was not.
 */
.dark .theme-toggle-btn {
    border-color: rgba(255, 255, 255, 0.18);
    color: var(--ccess-text);
}

/*
 * The page and the card surfaces.
 *
 * .main-content already reads --ccess-surface, so the page follows the token. Cards
 * are pinned explicitly because the vendor sets .card { background-color: #343a40 }
 * as a literal: left alone every card would ignore --ccess-card-bg and the token
 * would be a lie the next time someone tuned it.
 */
.dark .main-content .card,
.dark .auth-card,
.dark .modal-content,
.dark .dropdown-menu {
    background-color: var(--ccess-card-bg);
}

.dark .dropdown-menu {
    border-color: var(--ccess-border);
}

/*
 * VENDOR DEFECT 1 - app-dark.css gives .dropdown-item:hover `#16181b on #f8f9fa`, a
 * near-WHITE row inside a dark menu. Readable, but it flashes white under the cursor
 * on every menu in the dashboard. Replaced with the coral wash the shell already
 * uses for hover everywhere else.
 */
.dark .dropdown-item {
    color: var(--ccess-text);
}

.dark .dropdown-item:hover,
.dark .dropdown-item:focus {
    color: var(--ccess-text);
    background-color: var(--ccess-primary-alpha);
}

/*
 * Tables. The vendor's own dark text (#ced4da) is fine on its #343a40 card but not
 * on the darker page, and the head/border colours come from tokens that now hold
 * dark values. Row hover is lifted from the vendor's rgba(0,0,0,0.075) - darkening
 * an already-dark row is close to a no-op - to a light wash that is actually visible.
 */
.dark .main-content .table {
    color: var(--ccess-text);
}

.dark .main-content .table-hover tbody tr:hover {
    color: var(--ccess-text);
    background-color: rgba(255, 255, 255, 0.045);
}

/*
 * Forms.
 *
 * The field sits on a card, so it must not be the SAME colour as the card or the
 * input has no edge; it goes one step darker than the card and keeps the neutral
 * border. The vendor's #6c757d border is dropped because it reads as a disabled
 * control, and its disabled grey (#6c757d, a LIGHTER fill than the enabled state) is
 * inverted so a disabled field looks recessed rather than highlighted.
 */
.dark .main-content .form-control,
.dark .main-content .custom-select,
.dark .main-content .form-control-file,
.dark .auth-page .form-control {
    color: var(--ccess-text);
    background-color: var(--ccess-surface);
    border-color: var(--ccess-border);
}

.dark .main-content .form-control::placeholder,
.dark .auth-page .form-control::placeholder {
    color: var(--ccess-text-muted);
    opacity: 1;
}

.dark .main-content .form-control:disabled,
.dark .main-content .form-control[readonly],
.dark .main-content .custom-select:disabled {
    color: var(--ccess-text-muted);
    background-color: #14171A;
    border-color: var(--ccess-border);
}

/*
 * VENDOR DEFECT 2 - app-dark.css carries the SAME arrow SVG as the light sheet on
 * .custom-select, `fill='%23343a40'`, over a `#343a40` field: the chevron is
 * invisible in dark mode. Only background-image is overridden, so the vendor's
 * position, size and no-repeat from the `background` shorthand still apply.
 */
.dark .main-content .custom-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23AEB6BE' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e");
}

/*
 * VENDOR DEFECT 3 - app-dark.css pins `.text-muted { color: #6c757d !important }`,
 * which is 3.41:1 on the page and fails AA. This file already re-points .text-muted
 * through --ccess-text-muted with !important, so the token above fixes it globally;
 * the rule is restated here only for the auth page, whose scope differs.
 *
 * That one token is what rescues the stat-card labels, every table's secondary
 * values, the empty-state rows, breadcrumbs and both footer lines at once - the
 * central fix that avoids patching dozens of screens.
 */
.dark .auth-page .text-muted,
.dark .auth-page-shell > p {
    color: var(--ccess-text-muted) !important;
}

/*
 * Stat cards. Background, border, label and meta text all come from tokens already;
 * only the big number needs saying, because it is a bare <p> that inherits the
 * vendor body colour rather than a heading. Dimensions and layout are untouched.
 */
.dark .stat-card .stat-value {
    color: var(--ccess-text);
}

/* A 10%-black shadow is invisible on charcoal - the lift needs a much darker one. */
.dark .stat-card:hover {
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55) !important;
}

/*
 * The RTL sidebar/content divider is an inset BLACK hairline, which disappears on
 * dark chrome. Flipped to a faint light one. Both class hooks are spelled out
 * because the dir attribute and the mode class can land on the same html element.
 */
html[dir="rtl"].dark .vertical .sidebar-left,
html[dir="rtl"] body.dark .vertical .sidebar-left {
    box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.06);
}

/*
 * SweetAlert. sweetalert2.min.css is the LIGHT build and the theme's dark build was
 * not carried over when the asset trees were consolidated, so the delete dialog
 * would open as a white sheet in the middle of a dark dashboard. These rules are the
 * minimum to seat it: surface, title, body copy, and the cancel button whose
 * #E9ECEF / #DEE2E6 greys are hardcoded earlier in this file.
 */
.dark .swal2-popup {
    background: var(--ccess-card-bg);
    color: var(--ccess-text);
}

.dark .swal2-title,
.dark .swal2-html-container {
    color: var(--ccess-text);
}

.dark .ahcl-swal-cancel {
    background-color: #3C434A !important;
    color: var(--ccess-text) !important;
}

.dark .ahcl-swal-cancel:hover {
    background-color: #4A525A !important;
}

.dark .ahcl-swal-cancel:focus {
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18) !important;
}

/*
 * Validation red. #dc3545 / #b02a37 were chosen against white; the darker of the two
 * is 4.1:1 on a dark card and the pair reads as brown. Lifted to the tints Bootstrap
 * itself uses on dark surfaces.
 */
.dark .lang-card.has-error > .card-header {
    border-inline-start-color: #F1707C;
}

.dark .lang-card.has-error .lang-name {
    color: #FF9AA4;
}

/*
 * The language-card header used the shell grey to sit apart from the card body. In
 * dark that token is the CHROME colour, which is darker than the page - correct for
 * a sidebar, too heavy for a header band inside a card, so it takes the table-head
 * neutral instead.
 */
.dark .lang-card > .card-header {
    background: var(--ccess-table-head-bg);
}

/*
 * Trash tabs: the active tab is the one that should read as "on the surface". Its
 * background is --ccess-surface, i.e. the page - on dark that makes it recede BELOW
 * the inactive tabs, so it takes the card colour instead.
 */
.dark .cms-trash-tabs .nav-link.active {
    background: var(--ccess-card-bg);
}

/*
 * Alerts. Bootstrap's contextual alert backgrounds are pale washes computed for a
 * white page (.alert-success is #d4edda with #155724 text). They stay legible on
 * dark because the dark text travels with the pale fill, and they are the one place
 * a light block is deliberate - a flash message should interrupt. Left alone on
 * purpose; the only change is the border, which vanished against the darker page.
 */
.dark .main-content .alert {
    border-color: transparent;
}

/*
 * VENDOR DEFECT 4 - app-dark.css ships the outline buttons byte-identical to the
 * light sheet. Their resting state is a mid-tone hue on white, so on the dark page
 * they land at (measured against #1E2226):
 *
 *   .btn-outline-dark       #212529   1.04:1  invisible - the page colour itself
 *   .btn-outline-primary    #1b68ff   3.41:1  fails AA
 *   .btn-outline-danger     #dc3545   3.54:1  fails AA
 *   .btn-outline-secondary  #6c757d   3.41:1  fails AA
 *   .btn-link               #1b68ff   3.41:1  fails AA
 *   .btn-outline-info       #17a2b8   5.26:1  passes - left alone
 *   .btn-outline-success    #3ad29f   8.31:1  passes - left alone
 *
 * The replacements measure 7.71:1, 5.60:1, 6.88:1 and 14.4:1 on the same surface.
 *
 * There are 80 outline buttons across the dashboard views, so this is the second
 * half of the "weak contrast inside cards" report. Each hue is LIGHTENED rather than
 * replaced, so a dark screen keeps the same visual language as its light counterpart
 * — outline-danger is still red, outline-primary still blue. Only outline-dark has to
 * change meaning: "dark" is what the surface now IS, so on dark it becomes the light
 * ink. Hover states are untouched; they fill with the solid hue and set white text,
 * which already reads on both surfaces.
 */
.dark .main-content .btn-outline-secondary {
    color: #ADB5BD;
    border-color: #ADB5BD;
}

.dark .main-content .btn-outline-danger {
    color: #F1707C;
    border-color: #F1707C;
}

.dark .main-content .btn-outline-primary {
    color: #7FA9FF;
    border-color: #7FA9FF;
}

.dark .main-content .btn-outline-dark {
    color: var(--ccess-text);
    border-color: var(--ccess-text);
}

.dark .main-content .btn-link {
    color: #7FA9FF;
}

/*
|--------------------------------------------------------------------------
| Cairo — the public site's typeface, self-hosted for the dashboard
|--------------------------------------------------------------------------
|
| WHY THIS EXISTS. global.css already ends with `* { font-family: "Cairo", …
| !important }`, so the dashboard has been ASKING for Cairo all along — but nothing
| ever served it. There was no @font-face for Cairo anywhere in public/, so every
| screen silently fell through to the next name in that list and rendered in Segoe UI
| or Tahoma. The font was a request with no supply.
|
| SOURCE OF TRUTH. The public site declares it in src/app/[locale]/layout.js as
| `Cairo({ subsets: ["arabic", "latin"], display: "swap" })` from next/font/google, with
| no `weight` array — which means the VARIABLE font, and `cairo.className` on <body>, so
| the whole site uses it in both languages. The three .woff2 files below were copied out
| of that build (fvar/avar/HVAR/STAT confirmed present, i.e. genuinely variable) into
| public/dashboard-theme/fonts/, so the backend serves its own copy and stays
| independently deployable — nothing here points into the Next.js tree. Cairo is OFL-1.1,
| which permits self-hosting.
|
| ONE FILE PER SUBSET, NOT ONE PER WEIGHT. A variable face covers the whole
| 200–1000 axis in a single file, so the four weights the dashboard actually uses
| (400 body, 600 labels, 700 headings/brand, and the theme's own 500) come out of
| ~79 KB total rather than four static downloads each.
|
| The unicode-range values, the weight range and the fallback metrics are reproduced
| exactly as next/font emitted them, so a glyph resolves to the same subset here as it
| does on the public site and the swap does not reflow.
*/

@font-face {
    font-family: "Cairo";
    font-style: normal;
    font-weight: 200 1000;
    font-display: swap;
    src: url("fonts/cairo-arabic.woff2") format("woff2");
    /* subset: arabic */
    unicode-range: U+6??, U+750-77F, U+870-88E, U+890-891, U+897-8E1, U+8E3-8FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC4, U+10EFC-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}

@font-face {
    font-family: "Cairo";
    font-style: normal;
    font-weight: 200 1000;
    font-display: swap;
    src: url("fonts/cairo-latin.woff2") format("woff2");
    /* subset: latin */
    unicode-range: U+??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC, U+304, U+308, U+329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Cairo";
    font-style: normal;
    font-weight: 200 1000;
    font-display: swap;
    src: url("fonts/cairo-latin-ext.woff2") format("woff2");
    /* subset: latin-ext */
    unicode-range: U+100-2BA, U+2BD-2C5, U+2C7-2CC, U+2CE-2D7, U+2DD-2FF, U+304, U+308, U+329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/*
 * Metric-matched fallback, values verbatim from next/font. Arial stretched to Cairo's
 * proportions, so the text does not jump when the real face finishes loading — the
 * same trick the public site uses, which is why it is copied rather than invented.
 */
@font-face {
    font-family: "Cairo Fallback";
    src: local("Arial");
    ascent-override: 137.65%;
    descent-override: 60.32%;
    line-gap-override: 0.0%;
    size-adjust: 94.66%;
}

/*
 * Applying it.
 *
 * Scoped to real elements and components rather than `*`. global.css's universal
 * `!important` rule is what makes the `!important` here necessary: without it the
 * vendor's own chain (Cairo, Segoe UI, Tahoma, Arial) would win and the metric-matched
 * fallback below would never be reached. Every selector carries at least one element or
 * class, so all of them outrank the vendor's `*` (0,0,0) and the cascade is decided by
 * specificity rather than by load order.
 *
 * `Cairo Fallback` sits second, before the system stack, exactly as the public site
 * orders it.
 */
html,
body,
button,
input,
select,
optgroup,
textarea,
table,
.cms-sidebar,
.cms-topnav,
.dropdown-menu,
.modal,
.tooltip,
.popover,
.swal2-popup {
    font-family: "Cairo", "Cairo Fallback", system-ui, "Segoe UI", Tahoma, Arial, sans-serif !important;
}

/*
 * ICON FONT PROTECTION — this is the rule that must never be removed.
 *
 * A glyph in an icon font is a private-use codepoint: with any other family applied the
 * character is simply absent and the browser draws a blank or a tofu box. Every sidebar
 * and toolbar icon in the dashboard depends on this.
 *
 * `.fe` in feather.css already defends itself with `font-family: "feather" !important`,
 * and it beats global.css's `*` on specificity — but TWO vendor icon rules do NOT carry
 * !important and were therefore already losing to that universal rule before this work:
 *
 *   app-light.css  .dropdown-toggle::after   the dropdown caret
 *   app-light.css  .searchform:before        the search glyph
 *
 * Restated here with !important so all of them are safe from the universal rule, from
 * the Cairo rule above, and from whatever a future theme refresh does. The pseudo-element
 * selectors are listed explicitly rather than relying on inheritance, because ::before is
 * where the glyph is actually drawn.
 */
.fe,
.fe::before,
[class^="fe-"],
[class^="fe-"]::before,
[class*=" fe-"],
[class*=" fe-"]::before,
.dropdown-toggle::after,
.searchform::before,
.searchform:before {
    font-family: "feather" !important;
}

/*
 * Monospace survives too. The vendor's universal rule had already flattened `pre`, `code`
 * and .text-monospace to a proportional face, which matters on the one screen that edits
 * raw JSON (a page section's extra data) and anywhere a slug or URL is shown as code.
 */
pre,
code,
kbd,
samp,
.text-monospace,
textarea.cms-json {
    font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
}

/*
|--------------------------------------------------------------------------
| Market refresh cards
|--------------------------------------------------------------------------
|
| The two live-price cards on the dashboard home.
|
| NOT ONE COLOUR LITERAL. Every value is an existing --ccess-* token, which is the whole
| reason these need no dark-mode block of their own: the dark palette redefines those
| tokens on `html.dark, body.dark`, so the cards follow it for free. A hardcoded #FFF
| surface here is exactly the "white card in dark mode" this would otherwise reintroduce.
|
| Logical properties throughout, so the figures and the meta list mirror correctly in
| Arabic without a second RTL block.
*/

.cms-market-card .card-title {
    font-size: 0.95rem;
}

/* The accent mark, sized like the stat-card icons so the two sections agree. */
.cms-market-icon {
    font-size: 1.25rem;
    color: var(--ccess-primary-readable);
    flex: 0 0 auto;
    margin-inline-start: 0.5rem;
}

/*
 * Buy and sell sit side by side and wrap together. `gap` rather than margins, so the
 * spacing does not need mirroring and a single figure (gold) is not left with a stray
 * outer margin.
 */
.cms-market-figures {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    margin-block: 0.25rem 0.75rem;
}

.cms-market-figure-value {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.15;
    color: var(--ccess-text);
}

.cms-market-figure-label {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ccess-text-muted);
}

/*
 * "Last updated" / "Source" as a definition list: two short label/value pairs, laid out
 * as a grid so the values align with each other rather than each finding its own indent.
 */
.cms-market-meta {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.15rem 0.6rem;
    margin-block-start: 0.25rem;
    font-size: 0.8rem;
}

.cms-market-meta dt {
    font-weight: 600;
    color: var(--ccess-text-muted);
}

.cms-market-meta dd {
    margin: 0;
    color: var(--ccess-text);
    overflow-wrap: anywhere;
}

/*
 * The footer holds the one action. Transparent rather than the theme's default tint, so
 * the button sits on the card surface in both modes; the border is the shared token, so
 * it stays visible against the dark card.
 */
.cms-market-card .card-footer.cms-market-footer {
    background: transparent;
    border-top: 1px solid var(--ccess-border);
}

.cms-market-refresh {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
}

/*
 * Submitted state. The form is a normal POST, so the browser navigates and the button
 * cannot be clicked twice in one page — but a slow provider leaves it visibly idle for a
 * few seconds, and `:active` alone does not survive the wait. The real duplicate-write
 * guard is server side (a per-market lock); this is only feedback.
 */
.cms-market-refresh:disabled,
.cms-market-refresh[aria-disabled="true"] {
    opacity: 0.65;
    cursor: progress;
}

/* Below the shell breakpoint the two cards are already stacked by the grid; this keeps
 * the figures from crowding on a 390px screen. */
@media (max-width: 575.98px) {
    .cms-market-figures {
        gap: 1rem;
    }

    .cms-market-figure-value {
        font-size: 1.3rem;
    }
}
