/* ===========================================================================
   Indigo-Mint LMS — application shell and app-specific surfaces
   ===========================================================================
   Everything that is *not* the design system lives here: the admin shell, the
   marketing hero, the global toast stack, the confirmation modal, and the few
   Bootstrap utilities that are colour-locked and need a dark-mode escape.

   Tokens live in lms-tokens.css. Components live in lms-components.css. This
   file loads after both and must not redefine either — if a rule here sets a
   colour, radius, or duration literally, it belongs in the token file instead.
   =========================================================================== */

body {
    font-family: var(--lms-font-sans);
    background-color: var(--lms-surface-page);
    color: var(--lms-text-body);
    font-size: var(--lms-body-md-size);
    line-height: var(--lms-body-md-lh);
    -webkit-font-smoothing: antialiased;

    /* Full-bleed sections escape their container with `margin-inline: calc(50% - 50vw)`
       (Home/Index's hero). `100vw` counts the vertical scrollbar and `100%` does not, so
       on any page tall enough to scroll the bleed overshoots by the scrollbar width and
       the whole document gains a horizontal scrollbar — 8px on the home page, in both
       directions, measured 2026-08-25.

       `clip`, not `hidden`: `overflow: hidden` would make body a scroll container, which
       silently kills `position: sticky` in every descendant — and the public header is
       `.sticky-top`. `clip` trims the overflow without becoming one.

       It has to be on `html` as well (below): the bleed escapes body's box too, and `html`
       is the element that actually scrolls. Setting it on body alone changes nothing. */
    overflow-x: clip;
}

html { overflow-x: clip; }

h1, h2, h3, h4, h5, h6 { color: var(--lms-text-heading); }

/* ---------------------------------------------------------------------------
   Application shell — sidebar, topbar, content well
   Used by _AdminLayout, which serves the Admin, Teacher and Student areas.
   --------------------------------------------------------------------------- */
.lms-wrapper {
    display: flex;
    min-height: 100vh;
    overflow: hidden;
}

.lms-sidebar {
    width: var(--lms-sidebar-w);
    background-color: var(--lms-surface-inverse);
    color: var(--lms-text-inverse);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    transition: width var(--lms-dur-slow) var(--lms-ease-standard);
    box-shadow: var(--lms-elev-3);
    z-index: 50;
}

.lms-sidebar.collapsed { width: 80px; }

.lms-sidebar .nav-link {
    color: var(--lms-text-inverse);
    opacity: 0.75;
    padding: var(--lms-space-md) var(--lms-space-xl);
    display: flex;
    align-items: center;
    gap: var(--lms-space-md);
    font-size: var(--lms-body-sm-size);
    font-weight: var(--lms-weight-medium);
    text-decoration: none;
    /* Logical, not physical: in Arabic the active marker belongs on the right. */
    border-inline-start: 3px solid transparent;
    transition: var(--lms-transition);
}

.lms-sidebar .nav-link:hover,
.lms-sidebar .nav-link.active {
    background-color: var(--lms-surface-inverse-alt);
    opacity: 1;
    border-inline-start-color: var(--lms-primary);
}

.lms-sidebar .nav-link i {
    font-size: 1.1rem;
    width: 24px;
    text-align: center;
}

.lms-sidebar .mt-auto { margin-top: auto !important; }

.lms-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x: hidden;
}

.lms-topbar {
    height: var(--lms-topbar-h);
    background-color: var(--lms-surface-card);
    border-bottom: 1px solid var(--lms-border-card);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-inline: var(--lms-space-xxl);
    box-shadow: var(--lms-shadow-sm);
    z-index: 40;
}

.lms-content-area {
    padding: var(--lms-space-xxl);
    flex: 1;
}

@media (max-width: 767.98px) {
    .lms-content-area { padding: var(--lms-space-lg); }
    .lms-topbar { padding-inline: var(--lms-space-lg); }
}

/* ---------------------------------------------------------------------------
   Admin shell — the concrete implementation of the shell above
   These rules lived in a 200-line <style> block inside _AdminLayout.cshtml.
   They are here now because a stylesheet is where a theme belongs, and because
   that block carried three defects a token layer cannot reach through markup:
   it pinned body to Inter (defeating the Arabic swap), it put the active-item
   marker on border-left (so it sat on the wrong edge in Arabic), and it painted
   that marker amber, a colour DESIGN.md reserves for locked content.
   --------------------------------------------------------------------------- */
/* The rail is fixed to the viewport, not a flex item in the page column.

   It used to be a sticky flex child with height: 100vh. A flex item cannot be
   taller than the height it is given, so on any page taller than the viewport
   the rail painted only the first screenful and the page background showed
   through underneath it — the dark panel visibly stopped after the last nav
   item. Sticky could not save it, because sticky repositions an element, it
   does not stretch one.

   inset-block: 0 pins it to the viewport instead, so it is exactly one screen
   tall at every scroll position and there is nothing below it to leave a gap.
   The content column is pushed clear with a margin rather than by flex sizing.
   Same construction as EVSS.Web/Pages/Shared/_Layout.cshtml + portal.css. */
.admin-layout {
    display: flex;
    min-height: 100vh;
}

.admin-sidebar {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--lms-sidebar-w);
    z-index: var(--lms-z-sticky);
    background-color: var(--lms-surface-inverse);
    color: var(--lms-text-inverse);
    display: flex;
    flex-direction: column;
    transition: width var(--lms-dur-slow) var(--lms-ease-standard);
}

/* The collapse is driven by a sibling selector rather than a custom property
   set through :has() on the shell. That was tried first and Chrome kept the
   sidebar at its old computed width after the variable changed — the property
   updated, the width that read it did not. A literal width on each state and a
   sibling combinator for the content column has no such invalidation to miss. */
.admin-sidebar.collapsed { width: 80px; }

.admin-sidebar-brand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--lms-space-md);
    padding: var(--lms-space-xl) var(--lms-space-lg);
    border-block-end: 1px solid rgba(255, 255, 255, 0.1);
    color: #fff;
    font-size: var(--lms-heading-sm-size);
    font-weight: var(--lms-weight-bold);
    letter-spacing: -0.01em;
    text-decoration: none;
}

.admin-sidebar.collapsed .admin-sidebar-brand {
    flex-direction: column;
    justify-content: center;
    gap: var(--lms-space-lg);
    padding-inline: var(--lms-space-sm);
}

.admin-sidebar.collapsed .admin-nav-item a,
.admin-sidebar.collapsed .admin-nav-item button {
    justify-content: center;
    padding: var(--lms-space-md);
}

.admin-sidebar-nav {
    flex: 1;
    padding-block: var(--lms-space-md);
    margin: 0;
    list-style: none;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.35) rgba(0, 0, 0, 0.15);
}

.admin-sidebar-nav::-webkit-scrollbar { width: 10px; }
.admin-sidebar-nav::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.15); border-radius: var(--lms-radius-sm); }
.admin-sidebar-nav::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.35);
    border-radius: var(--lms-radius-sm);
    border: 2px solid transparent;
    background-clip: content-box;
}
.admin-sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.65); background-clip: content-box; }

/* Section heading inside the rail, per the SidebarNav spec. */
.admin-nav-section {
    padding: var(--lms-space-lg) var(--lms-space-xl) var(--lms-space-sm);
    font: var(--lms-micro-weight) var(--lms-micro-size)/var(--lms-micro-lh) var(--lms-font-sans);
    letter-spacing: var(--lms-micro-track);
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.45);
}

.admin-nav-item a,
.admin-nav-item button {
    display: flex;
    align-items: center;
    gap: var(--lms-space-md);
    width: 100%;
    padding: var(--lms-space-md) var(--lms-space-xl);
    border: 0;
    /* The active marker is transparent until active, so a row never shifts by
       3px when it becomes current. */
    border-inline-start: 3px solid transparent;
    background: none;
    color: rgba(255, 255, 255, 0.78);
    font-size: var(--lms-body-sm-size);
    font-weight: var(--lms-weight-medium);
    text-align: start;
    text-decoration: none;
    transition: background-color var(--lms-dur-fast) var(--lms-ease-standard),
                color var(--lms-dur-fast) var(--lms-ease-standard);
}

.admin-nav-item a:hover,
.admin-nav-item button:hover {
    background-color: var(--lms-surface-inverse-alt);
    color: #fff;
}

.admin-nav-item a.active {
    background-color: var(--lms-surface-inverse-alt);
    border-inline-start-color: var(--lms-primary);
    color: #fff;
    font-weight: var(--lms-weight-semibold);
}

.admin-nav-item a i,
.admin-nav-item button i {
    flex: 0 0 20px;
    font-size: 1.05rem;
    text-align: center;
}

.admin-sidebar-footer {
    padding: var(--lms-space-md);
    border-block-start: 1px solid rgba(255, 255, 255, 0.1);
}

.admin-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    /* The rail is out of flow now, so the column has to step around it. */
    margin-inline-start: var(--lms-sidebar-w);
    transition: margin-inline-start var(--lms-dur-slow) var(--lms-ease-standard);
}

.admin-sidebar.collapsed ~ .admin-main { margin-inline-start: 80px; }

.admin-topbar {
    height: var(--lms-topbar-h);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--lms-space-md);
    padding-inline: var(--lms-space-xxl);
    /* Frosted rather than solid: the content scrolls under it. */
    background-color: color-mix(in srgb, var(--lms-surface-card) 88%, transparent);
    backdrop-filter: var(--lms-blur-overlay);
    -webkit-backdrop-filter: var(--lms-blur-overlay);
    border-block-end: 1px solid var(--lms-border-card);
    position: sticky;
    top: 0;
    z-index: var(--lms-z-sticky);
}

/* The title is the only element in the bar allowed to give up space. Without
   this it holds its full width and pushes the controls off the end. */
.admin-topbar > :first-child { min-width: 0; }

.admin-topbar .lms-heading-sm {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-topbar .lms-teacher-chip { max-width: 220px; }
.admin-topbar .lms-teacher-chip span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-content {
    flex: 1;
    padding: var(--lms-space-xl);
    /* No overflow-y here: the page itself scrolls. A nested scroller would trap
       the wheel inside the content and leave the sticky topbar pinned to a bar
       that never moves. */
}

@media (max-width: 767.98px) {
    .admin-content { padding: var(--lms-space-lg); }
    .admin-topbar { padding-inline: var(--lms-space-lg); gap: var(--lms-space-sm); }

    /* Below the tablet breakpoint the rail always shows as icons only. A 280px
       sidebar beside content on a phone leaves neither enough room, and the
       toggle already in the topbar still expands it on demand. */
    .admin-sidebar,
    .admin-sidebar.collapsed { width: 72px; }

    .admin-main,
    .admin-sidebar.collapsed ~ .admin-main { margin-inline-start: 72px; }

    .admin-sidebar .admin-nav-item a,
    .admin-sidebar .admin-nav-item button { justify-content: center; padding: var(--lms-space-md); }

    .admin-sidebar .admin-nav-item span,
    .admin-sidebar .admin-nav-section { display: none; }

    .admin-sidebar-brand { flex-direction: column; gap: var(--lms-space-md); padding-inline: var(--lms-space-sm); }
    .admin-sidebar-brand span { display: none; }
}

/* Compact pill control shared by the language switch and the theme toggle. */
.lang-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--lms-space-xs);
    height: 34px;
    padding-inline: var(--lms-space-md);
    border: 1px solid var(--lms-border-card);
    border-radius: var(--lms-radius-pill);
    background: var(--lms-surface-card);
    color: var(--lms-text-body);
    font-size: var(--lms-caption-size);
    font-weight: var(--lms-weight-medium);
    text-decoration: none;
    transition: background-color var(--lms-dur-fast) var(--lms-ease-standard),
                color var(--lms-dur-fast) var(--lms-ease-standard);
}

.lang-btn:hover {
    background: var(--lms-surface-muted);
    color: var(--lms-text-heading);
    text-decoration: none;
}

/* The wallet balance is money: tabular figures, mint, and never wrapped. */
.lms-wallet-badge {
    color: var(--lms-mint-success);
    border-color: var(--lms-mint-border);
    background: var(--lms-mint-soft);
    white-space: nowrap;
}

.lms-wallet-badge:hover { background: var(--lms-mint-soft); color: var(--lms-mint-hover); }
.lms-wallet-badge__amount { font-variant-numeric: tabular-nums; font-weight: var(--lms-weight-semibold); }

/* WhatsApp keeps its own brand green — it is that company's mark, not ours. */
.whatsapp-float {
    position: fixed;
    bottom: var(--lms-space-xl);
    inset-inline-end: var(--lms-space-xl);
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background-color: #25d366;
    color: #fff;
    font-size: 1.75rem;
    text-decoration: none;
    box-shadow: var(--lms-elev-3);
    z-index: 1040;
    transition: transform var(--lms-dur-fast) var(--lms-ease-standard);
}

.whatsapp-float:hover { transform: scale(1.08); color: #fff; }

/* Page header block used at the top of every area page. */
.lms-page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--lms-space-lg);
    flex-wrap: wrap;
    margin-block-end: var(--lms-space-xl);
}

.lms-page-head__title {
    font: var(--lms-display-lg-weight) var(--lms-display-lg-size)/var(--lms-display-lg-lh) var(--lms-font-sans);
    letter-spacing: var(--lms-display-lg-track);
    color: var(--lms-text-heading);
    margin: 0;
}

.lms-page-head__lead {
    margin: var(--lms-space-xs) 0 0;
    font-size: var(--lms-body-md-size);
    color: var(--lms-text-body);
}

/* ---------------------------------------------------------------------------
   Public site chrome — the marketplace header and footer
   --------------------------------------------------------------------------- */
.lms-public-nav {
    z-index: var(--lms-z-sticky);
    /* Translucent so content scrolls under it, per DESIGN.md §6.1. The fallback
       colour is opaque: without backdrop-filter support this must not go see-through. */
    background: var(--lms-canvas-dark);
    background: color-mix(in srgb, var(--lms-canvas-dark) 86%, transparent);
    backdrop-filter: var(--lms-blur-overlay);
    -webkit-backdrop-filter: var(--lms-blur-overlay);
    border-block-end: 1px solid rgba(255, 255, 255, 0.1);
}

.lms-public-nav .navbar { padding-block: var(--lms-space-md); }

.lms-public-nav .navbar-brand {
    color: #fff;
    font-size: var(--lms-heading-sm-size);
    letter-spacing: -0.02em;
}

.lms-public-nav .nav-link {
    color: rgba(255, 255, 255, 0.78);
    font-size: var(--lms-body-sm-size);
    font-weight: var(--lms-weight-medium);
}

.lms-public-nav .nav-link:hover,
.lms-public-nav .nav-link:focus-visible { color: #fff; }

/* The bell sits on midnight here and on the light topbar in the app shell, so it
   takes its colour from the bar around it rather than hardcoding either. */
.lms-public-nav .lms-icon-btn { color: rgba(255, 255, 255, 0.78); }
.lms-public-nav .lms-icon-btn:hover { background: rgba(255, 255, 255, 0.12); color: #fff; }

.lms-public-footer {
    background: var(--lms-canvas-dark);
    color: rgba(255, 255, 255, 0.65);
    font-size: var(--lms-body-sm-size);
}

.lms-public-footer a {
    color: rgba(255, 255, 255, 0.8);
    text-decoration: none;
}

.lms-public-footer a:hover { color: #fff; text-decoration: underline; }

/* ---------------------------------------------------------------------------
   Marketing surfaces — public home and landing sections
   --------------------------------------------------------------------------- */
/* The hero mesh of DESIGN.md §6.1, keyed to the Expert Academy sign: a brushed
   steel-blue plate warmed by the mark's navy at the top and its gold at the
   foot, with ink type on top. It is a full-bleed band rather than a floating
   card, so the page opens on the mesh. */
.lms-hero-wrapper {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(80% 120% at 82% 0%, rgba(20, 40, 94, 0.14) 0%, rgba(20, 40, 94, 0) 62%),
        radial-gradient(70% 110% at 8% 100%, rgba(197, 158, 78, 0.16) 0%, rgba(197, 158, 78, 0) 68%),
        linear-gradient(160deg, #eef2f8 0%, #dbe3ee 100%);
    border-block-end: 1px solid var(--lms-border-card);
}

[data-bs-theme="dark"] .lms-hero-wrapper {
    background:
        radial-gradient(80% 120% at 82% 0%, rgba(96, 133, 204, 0.20) 0%, rgba(96, 133, 204, 0) 62%),
        radial-gradient(70% 110% at 8% 100%, rgba(212, 175, 96, 0.13) 0%, rgba(212, 175, 96, 0) 68%),
        linear-gradient(160deg, var(--lms-surface-page) 0%, var(--lms-surface-muted) 100%);
}

/* The eyebrow above a hero headline. */
.lms-glow-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--lms-space-sm);
    padding: 6px var(--lms-space-md);
    border: 1px solid var(--lms-primary-bg-subdued-hover);
    border-radius: var(--lms-radius-pill);
    background: var(--lms-primary-bg-subdued);
    color: var(--lms-primary);
    font-size: var(--lms-caption-size);
    font-weight: var(--lms-weight-semibold);
}

/* Hero figure stats: value over a micro label, tabular so they hold their width. */
.lms-hero-stats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--lms-space-xxl);
}

.lms-stat-chip__value {
    font-size: 22px;
    font-weight: var(--lms-weight-bold);
    letter-spacing: -0.02em;
    color: var(--lms-text-heading);
    font-variant-numeric: tabular-nums;
}

.lms-stat-chip__label {
    font: var(--lms-micro-weight) var(--lms-micro-size)/var(--lms-micro-lh) var(--lms-font-sans);
    letter-spacing: var(--lms-micro-track);
    text-transform: uppercase;
    color: var(--lms-text-subtle);
}

/* Offering hero. Teacher artwork sits behind a midnight scrim rather than raw:
   whatever they uploaded, the title has to stay legible on top of it. */
.lms-course-hero {
    position: relative;
    background:
        linear-gradient(rgba(6, 27, 49, 0.82), rgba(6, 27, 49, 0.9)),
        var(--lms-hero-art, none),
        linear-gradient(135deg, var(--lms-canvas-dark) 0%, var(--lms-canvas-dark-alt) 100%);
    background-size: cover;
    background-position: center;
    color: rgba(255, 255, 255, 0.78);
}

.lms-course-hero .lms-breadcrumbs,
.lms-course-hero .lms-breadcrumbs a { color: rgba(255, 255, 255, 0.6); }
.lms-course-hero .lms-breadcrumbs a:hover { color: #fff; }
.lms-course-hero .lms-breadcrumbs__current { color: rgba(255, 255, 255, 0.9); }

.lms-course-hero .lms-badge--indigo {
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.24);
    color: #fff;
}

/* Checkout hero — the offering restated at the point of paying. */
.lms-checkout-hero {
    padding: var(--lms-space-xl);
    border-block-end: 1px solid var(--lms-border-card);
    background: linear-gradient(135deg, var(--lms-primary-bg-subdued) 0%, var(--lms-surface-card) 100%);
}

.lms-checkout-hero__art {
    inline-size: 140px;
    block-size: 140px;
    flex-shrink: 0;
    object-fit: cover;
    border-radius: var(--lms-radius-card);
    border: 1px solid var(--lms-border-card);
    box-shadow: var(--lms-elev-1);
}

/* Teacher profile hero — the teal counterpart to the offering hero. */
.lms-teacher-hero {
    background:
        radial-gradient(70% 120% at 85% 0%, rgba(13, 148, 136, 0.14) 0%, rgba(13, 148, 136, 0) 62%),
        linear-gradient(160deg, var(--lms-canvas) 0%, var(--lms-canvas-surface-alt) 100%);
    border-block-end: 1px solid var(--lms-border-card);
}

[data-bs-theme="dark"] .lms-teacher-hero {
    background:
        radial-gradient(70% 120% at 85% 0%, rgba(45, 212, 191, 0.16) 0%, rgba(45, 212, 191, 0) 62%),
        linear-gradient(160deg, var(--lms-surface-page) 0%, var(--lms-surface-muted) 100%);
}

/* Offering counts strip along the foot of the offering card. */
.lms-offering-stats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--lms-space-lg);
    padding: var(--lms-space-lg);
    border-block-start: 1px solid var(--lms-border-card);
    background: var(--lms-surface-muted);
    text-align: center;
}

@media (min-width: 576px) { .lms-offering-stats { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 992px) { .lms-offering-stats { grid-template-columns: repeat(6, 1fr); } }

.lms-offering-stats__value {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--lms-space-xs);
    font-size: var(--lms-heading-sm-size);
    font-weight: var(--lms-weight-semibold);
    color: var(--lms-text-heading);
    font-variant-numeric: tabular-nums;
}

.lms-offering-stats__value i { color: var(--lms-primary); font-size: 0.9em; }

.lms-offering-stats__label {
    margin-block-start: var(--lms-space-xxs);
    font: var(--lms-micro-weight) var(--lms-micro-size)/var(--lms-micro-lh) var(--lms-font-sans);
    letter-spacing: var(--lms-micro-track);
    text-transform: uppercase;
    color: var(--lms-text-subtle);
}

/* Star rating. Amber is this one's exception to §2.1 — a star rating is amber
   everywhere on the web, and reading it as "locked" is not a risk anyone runs. */
.lms-rating { color: var(--lms-amber-warning); white-space: nowrap; }

/* Section heading with an optional count and a trailing link. */
.lms-section-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--lms-space-md);
    margin-block-end: var(--lms-space-xl);
}

.lms-section-head h2 {
    font: var(--lms-heading-lg-weight) var(--lms-heading-lg-size)/var(--lms-heading-lg-lh) var(--lms-font-sans);
    letter-spacing: var(--lms-heading-lg-track);
    color: var(--lms-text-heading);
    margin: 0;
}

.lms-section-head__count {
    font-size: var(--lms-body-sm-size);
    color: var(--lms-text-subtle);
    font-variant-numeric: tabular-nums;
}

.lms-section-head__link { margin-inline-start: auto; font-size: var(--lms-body-sm-size); font-weight: var(--lms-weight-medium); }

.lms-feature-card {
    position: relative;
    padding: var(--lms-space-xxl);
    border: 1px solid var(--lms-border-card);
    border-radius: var(--lms-radius-card);
    background: var(--lms-surface-card);
    transition: var(--lms-transition);
}

.lms-feature-card:hover {
    transform: var(--lms-lift-hover);
    box-shadow: var(--lms-elev-2);
    border-color: var(--lms-primary-bg-subdued-hover);
}

/* Marketplace offering card — DESIGN.md §5.3. */
.lms-course-card {
    display: flex;
    flex-direction: column;
    background: var(--lms-surface-card);
    border: 1px solid var(--lms-border-card);
    border-radius: var(--lms-radius-card);
    overflow: hidden;
    box-shadow: var(--lms-elev-1);
    transition: var(--lms-transition);
}

.lms-course-card:hover {
    transform: var(--lms-lift-hover);
    box-shadow: var(--lms-elev-2);
    border-color: var(--lms-primary-bg-subdued-hover);
}

.lms-course-card__media {
    position: relative;
    aspect-ratio: 16 / 9;
    /* The placeholder is an indigo wash over midnight, not a grey box — an
       offering with no artwork should still look like part of the catalogue. */
    background:
        linear-gradient(135deg, rgba(83, 58, 253, 0.35), rgba(6, 27, 49, 0.05)),
        var(--lms-canvas-dark);
    overflow: hidden;
}

.lms-course-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.lms-course-card__placeholder {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    color: rgba(255, 255, 255, 0.55);
    font-size: 2rem;
}

/* Teacher chip floating over the thumbnail, at the start corner. */
.lms-course-card__teacher {
    position: absolute;
    inset-block-start: var(--lms-space-md);
    inset-inline-start: var(--lms-space-md);
    display: inline-flex;
    align-items: center;
    gap: var(--lms-space-sm);
    max-width: calc(100% - 2 * var(--lms-space-md));
    padding-block: 4px;
    padding-inline: 4px var(--lms-space-md);
    border-radius: var(--lms-radius-pill);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: var(--lms-blur-overlay);
    color: var(--lms-ink-primary);
    font-size: 12px;
    font-weight: var(--lms-weight-semibold);
    text-decoration: none;
}

[dir="rtl"] .lms-course-card__teacher { padding: 4px 4px 4px var(--lms-space-md); }

.lms-course-card__teacher span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lms-course-card__tag {
    position: absolute;
    inset-block-start: var(--lms-space-md);
    inset-inline-end: var(--lms-space-md);
}

.lms-course-card__body {
    padding: var(--lms-space-lg);
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--lms-space-md);
}

.lms-course-card__title {
    margin: 0;
    font: var(--lms-heading-sm-weight) var(--lms-heading-sm-size)/var(--lms-heading-sm-lh) var(--lms-font-sans);
    color: var(--lms-text-heading);
    text-wrap: pretty;
}

.lms-course-card__meta { display: flex; flex-wrap: wrap; gap: 6px; }

/* Price sits at the foot of the body, pushed down by margin so cards of
   different title lengths still line their prices up across a row. */
.lms-course-card__price {
    display: flex;
    align-items: baseline;
    gap: var(--lms-space-sm);
    margin-block-start: auto;
    padding-block-start: var(--lms-space-md);
    border-block-start: 1px solid var(--lms-border-card);
    font-size: var(--lms-heading-sm-size);
    font-weight: var(--lms-weight-bold);
    letter-spacing: -0.01em;
    color: var(--lms-text-heading);
    font-variant-numeric: tabular-nums;
}

.lms-course-card__price del {
    font-size: var(--lms-caption-size);
    font-weight: var(--lms-weight-medium);
    color: var(--lms-text-subtle);
}

/* Teacher tile for the "approved teachers" strip. */
.lms-teacher-card {
    display: block;
    padding: var(--lms-space-lg);
    border: 1px solid var(--lms-border-card);
    border-radius: var(--lms-radius-card);
    background: var(--lms-surface-card);
    box-shadow: var(--lms-elev-1);
    text-align: center;
    text-decoration: none;
    transition: var(--lms-transition);
}

.lms-teacher-card:hover {
    transform: var(--lms-lift-hover);
    box-shadow: var(--lms-elev-2);
    border-color: var(--lms-teal-soft);
    text-decoration: none;
}

.lms-teacher-card__name {
    margin: var(--lms-space-md) 0 0;
    font-size: var(--lms-body-sm-size);
    font-weight: var(--lms-weight-semibold);
    color: var(--lms-text-heading);
}

.lms-teacher-card__meta {
    margin-block-start: var(--lms-space-sm);
    font-size: var(--lms-caption-size);
    color: var(--lms-text-subtle);
}

/* Bundle card: an indigo header band over the included-courses list. */
.lms-bundle-head {
    padding: var(--lms-space-lg);
    background: linear-gradient(135deg, var(--lms-primary) 0%, var(--lms-primary-soft) 100%);
    color: #fff;
}

.lms-bundle-head h3 {
    margin: var(--lms-space-sm) 0 0;
    color: #fff;
    font: var(--lms-heading-sm-weight) var(--lms-heading-sm-size)/var(--lms-heading-sm-lh) var(--lms-font-sans);
}

.lms-bundle-head .lms-badge {
    background: rgba(255, 255, 255, 0.18);
    border-color: rgba(255, 255, 255, 0.28);
    color: #fff;
}

/* Truncation utilities. line-clamp-2 was used by two views and defined by none,
   so those descriptions ran to full length and broke the card grid's rhythm. */
.lms-clamp-1,
.lms-clamp-2,
.lms-clamp-3 {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.lms-clamp-1 { -webkit-line-clamp: 1; }
.lms-clamp-2 { -webkit-line-clamp: 2; }
.lms-clamp-3 { -webkit-line-clamp: 3; }

.lms-meta-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--lms-space-xs);
    padding: var(--lms-space-xs) var(--lms-space-md);
    border-radius: var(--lms-radius-md);
    background: var(--lms-surface-muted);
    color: var(--lms-text-body);
    font-size: var(--lms-caption-size);
    font-weight: var(--lms-weight-semibold);
}

.hover-lift { transition: var(--lms-transition); }
.hover-lift:hover { transform: var(--lms-lift-hover); }

/* ---------------------------------------------------------------------------
   Dark-mode repairs for colour-locked Bootstrap utilities
   .bg-white / .bg-light / .text-dark / .text-black are fixed values in
   Bootstrap and do not follow data-bs-theme. Views use them widely, so they are
   remapped rather than hunted down one by one.
   --------------------------------------------------------------------------- */
[data-bs-theme="light"] { color-scheme: light; }
[data-bs-theme="dark"] { color-scheme: dark; }

[data-bs-theme="dark"] .bg-white { background-color: var(--lms-surface-card) !important; }
[data-bs-theme="dark"] .bg-light { background-color: var(--lms-surface-muted) !important; }
[data-bs-theme="dark"] .text-dark:not(.badge) { color: var(--lms-text-heading) !important; }
[data-bs-theme="dark"] .text-black:not(.badge) { color: var(--lms-text-heading) !important; }
[data-bs-theme="dark"] .border { border-color: var(--lms-border-card) !important; }

[data-bs-theme="dark"] .table-light {
    --bs-table-bg: var(--lms-surface-muted);
    --bs-table-color: var(--lms-text-heading);
}

/* These sit on a fixed dark or coloured ground and must stay truly white. */
[data-bs-theme="dark"] .lms-glass-dark .bg-white,
[data-bs-theme="dark"] .lms-hero-wrapper .bg-white,
[data-bs-theme="dark"] .btn.bg-white { background-color: #ffffff !important; }

.lms-glass-dark {
    background: rgba(6, 27, 49, 0.8);
    border: 1px solid rgba(255, 255, 255, 0.1);
    backdrop-filter: var(--lms-blur-overlay);
    -webkit-backdrop-filter: var(--lms-blur-overlay);
}

body,
.admin-topbar,
.lms-card,
.lms-topbar {
    transition: background-color var(--lms-dur-slow) var(--lms-ease-standard),
                border-color var(--lms-dur-slow) var(--lms-ease-standard),
                color var(--lms-dur-slow) var(--lms-ease-standard);
}

.navbar.sticky-top { z-index: var(--lms-z-sticky); }

/* Alpine: hide x-show elements until Alpine has initialised, otherwise
   everything a view intends to keep hidden flashes on screen first. Global
   because it is an app-wide convention — a view that forgets gets the flash. */
[x-cloak] { display: none !important; }

/* ---------------------------------------------------------------------------
   Global UI kit — toast stack + confirmation modal (see wwwroot/js/lms-ui.js)
   These are the ONLY notification and confirmation styles in the app; no view
   ships its own alert markup. DESIGN.md §5.5: bottom-end stack, 4px accent on
   the inline-start edge, scale-in dialog.
   --------------------------------------------------------------------------- */
:root {
    --lms-toast-success: var(--lms-mint-success);
    --lms-toast-error: var(--lms-ruby-danger);
    --lms-toast-warning: var(--lms-amber-warning);
    --lms-toast-info: var(--lms-primary);
}

.lms-toast-container {
    position: fixed;
    bottom: var(--lms-space-xl);
    inset-inline-end: var(--lms-space-xl);
    z-index: var(--lms-z-toast); /* above Bootstrap modals so errors are never hidden */
    display: flex;
    flex-direction: column;
    gap: var(--lms-space-md);
    width: min(400px, calc(100vw - 2.5rem));
    pointer-events: none;
}

.lms-toast {
    pointer-events: auto;
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--lms-space-md);
    padding: var(--lms-space-lg);
    border: 1px solid var(--lms-border-card);
    border-inline-start: 4px solid var(--lms-toast-accent, var(--lms-toast-info));
    border-radius: var(--lms-radius-panel);
    background: var(--lms-surface-card);
    color: var(--lms-text-heading);
    box-shadow: var(--lms-elev-3);
    overflow: hidden;
    opacity: 0;
    transform: translateY(12px) scale(var(--lms-modal-in-scale));
    transition: opacity var(--lms-dur-slow) var(--lms-ease-standard),
                transform var(--lms-dur-slow) var(--lms-ease-standard);
}

.lms-toast--visible { opacity: 1; transform: translateY(0) scale(1); }
.lms-toast--leaving { opacity: 0; transform: translateY(-6px) scale(var(--lms-modal-in-scale)); }

.lms-toast--success { --lms-toast-accent: var(--lms-toast-success); }
.lms-toast--error   { --lms-toast-accent: var(--lms-toast-error); }
.lms-toast--warning { --lms-toast-accent: var(--lms-toast-warning); }
.lms-toast--info    { --lms-toast-accent: var(--lms-toast-info); }

.lms-toast__icon {
    color: var(--lms-toast-accent);
    font-size: 1.15rem;
    line-height: 1.4;
    flex-shrink: 0;
}

.lms-toast__body { flex: 1; min-width: 0; }

.lms-toast__title {
    font-weight: var(--lms-weight-semibold);
    font-size: var(--lms-body-sm-size);
    margin-bottom: var(--lms-space-xxs);
}

.lms-toast__message {
    font-size: var(--lms-body-sm-size);
    line-height: var(--lms-body-sm-lh);
    color: var(--lms-text-body);
    overflow-wrap: anywhere;
}

.lms-toast__close {
    border: 0;
    background: transparent;
    color: var(--lms-text-subtle);
    padding: 0.1rem 0.2rem;
    line-height: 1;
    font-size: 0.75rem;
    border-radius: var(--lms-radius-sm);
    flex-shrink: 0;
    transition: var(--lms-transition);
}

.lms-toast__close:hover {
    color: var(--lms-text-heading);
    background: var(--lms-surface-muted);
}

.lms-toast__progress {
    position: absolute;
    bottom: 0;
    inset-inline-start: 0;
    height: 3px;
    width: 100%;
    background: var(--lms-toast-accent);
    opacity: 0.55;
    animation-name: lms-toast-progress;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}

.lms-toast--paused .lms-toast__progress { animation-play-state: paused; }

@keyframes lms-toast-progress {
    from { width: 100%; }
    to   { width: 0%; }
}

@media (prefers-reduced-motion: reduce) {
    .lms-toast { transition: none; }
    .lms-toast__progress { animation: none; }
}

/* --- Confirmation modal ---------------------------------------------------
   The header carries a real background, not a .btn-* class: in Bootstrap 5 those
   only set --bs-btn-* variables and paint nothing, which produced white title
   text on a white bar. */
.lms-modal-header {
    border: 0;
    color: #fff;
    padding: var(--lms-space-lg) var(--lms-space-xl);
    background: var(--lms-modal-header-bg, var(--lms-primary));
}

.lms-modal-header .modal-title { font-weight: var(--lms-weight-bold); }
.lms-modal-header--primary { --lms-modal-header-bg: linear-gradient(135deg, var(--lms-primary), var(--lms-primary-hover)); }
.lms-modal-header--danger  { --lms-modal-header-bg: linear-gradient(135deg, var(--lms-ruby-danger), var(--lms-ruby-danger-hover)); }
.lms-modal-header--error   { --lms-modal-header-bg: linear-gradient(135deg, var(--lms-ruby-danger), var(--lms-ruby-danger-hover)); }
.lms-modal-header--warning { --lms-modal-header-bg: linear-gradient(135deg, var(--lms-amber-warning), #b45309); }
.lms-modal-header--success { --lms-modal-header-bg: linear-gradient(135deg, var(--lms-mint-success), var(--lms-mint-hover)); }
.lms-modal-header--info    { --lms-modal-header-bg: linear-gradient(135deg, var(--lms-primary), var(--lms-primary-hover)); }

.lms-confirm-modal .modal-content {
    border-radius: var(--lms-radius-card);
    overflow: hidden;
    background: var(--lms-surface-card);
    color: var(--lms-text-heading);
}

.lms-confirm-modal .modal-body,
.lms-confirm-modal .modal-footer { background: var(--lms-surface-card); }

.lms-modal-header .btn-close { opacity: 0.85; filter: invert(1) grayscale(100%) brightness(200%); }
.lms-modal-header .btn-close:hover { opacity: 1; }

/* The floating WhatsApp button shares the bottom-end corner — lift the stack. */
body:has(.whatsapp-float) .lms-toast-container { bottom: 6.25rem; }

@media (max-width: 575.98px) {
    .lms-toast-container { inset-inline: var(--lms-space-md); width: auto; }
    body:has(.whatsapp-float) .lms-toast-container { bottom: 5.75rem; }
}

/* --- Dialog polish (every modal, not only the confirm one) ----------------- */
.modal-content {
    border-radius: var(--lms-radius-card);
    background-color: var(--lms-surface-card);
    color: var(--lms-text-body);
    border-color: var(--lms-border-card);
}

.modal-header,
.modal-footer { border-color: var(--lms-border-card); }

/* Bootstrap's default slide-down replaced with the softer scale-in of §5.5. */
.modal.fade .modal-dialog {
    transform: translateY(12px) scale(0.97);
    transition: transform var(--lms-dur-base) var(--lms-ease-standard);
}

.modal.show .modal-dialog { transform: none; }

@media (prefers-reduced-motion: reduce) {
    .modal.fade .modal-dialog { transition: none; transform: none; }
}

/* Consistent, visible keyboard focus across the app — DESIGN.md §7.3. */
.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.lms-toast__close:focus-visible,
a:focus-visible {
    outline: var(--lms-focus-outline);
    outline-offset: var(--lms-focus-offset);
    box-shadow: none;
}

/* ---------------------------------------------------------------------------
   Brand mark — Views/Shared/_BrandMark.cshtml
   The mark is inlined rather than linked as an <img> so these rules can reach
   its paths; CSS does not cross an <img> boundary. Colours live here rather
   than inside the SVG so the mark can be re-toned per surface without editing
   the artwork, and so the timings read from the motion tokens.
   --------------------------------------------------------------------------- */
.ea-mark {
    display: block;
    inline-size: 100%;
    block-size: auto;
}

.ea-mark .ea-ray--a { fill: #e8e8f0; }
.ea-mark .ea-ray--b { fill: #d6d6e2; }
.ea-mark #eaGlobe { fill: none; stroke: #ffa800; stroke-width: 14; stroke-linecap: round; }
.ea-mark #eaBook { fill: none; stroke: #131957; stroke-width: 16; stroke-linecap: round; }
.ea-mark #eaFigure { fill: #131957; }
/* The head keeps the amber even though it sits inside the navy figure group. */
.ea-mark .ea-head { fill: #ffa800; }

/* Dark mode gets the reversed mark, the way a brand ships a light logo for dark
   grounds. Amber is untouched — it carries the identity and reads fine on carbon.
   The navy does not: #131957 on the #0f1011 card is far below any usable contrast,
   so the book and figure lift to the dark-mode ink, and the pale rays drop to a
   tone that still reads as a sunburst instead of glaring. */
[data-bs-theme="dark"] .ea-mark .ea-ray--a { fill: #2b2e34; }
[data-bs-theme="dark"] .ea-mark .ea-ray--b { fill: #1f2126; }
[data-bs-theme="dark"] .ea-mark #eaBook { stroke: #eceaf6; }
[data-bs-theme="dark"] .ea-mark #eaFigure { fill: #eceaf6; }

/* ---------------------------------------------------------------------------
   Draw-on. Plays once on load, never loops: DESIGN.md is explicit that nothing
   loops for attention. Rays fan out, the globe grid draws itself, the book
   pages follow, then the figure lifts in.

   Every path carries pathLength="1", so one dashoffset value drives the draw
   whatever the real path length is — no JS measuring getTotalLength().
   --------------------------------------------------------------------------- */
@keyframes ea-fan {
    from { opacity: 0; transform: scale(0.6); }
    to { opacity: 1; transform: scale(1); }
}

@keyframes ea-draw {
    from { stroke-dashoffset: 1; }
    to { stroke-dashoffset: 0; }
}

@keyframes ea-pop {
    from { opacity: 0; transform: translateY(10px) scale(0.9); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.ea-mark--animate .ea-ray {
    transform-origin: 301px 336px;
    animation: ea-fan var(--lms-dur-slow) var(--lms-ease-out) backwards;
}

.ea-mark--animate #eaGlobe .ea-draw,
.ea-mark--animate #eaBook .ea-draw {
    stroke-dasharray: 1;
    animation: ea-draw 560ms var(--lms-ease-standard) backwards;
}

.ea-mark--animate .ea-pop {
    transform-origin: 300px 140px;
    animation: ea-pop var(--lms-dur-slow) var(--lms-ease-out) backwards;
}

/* Stagger. nth-child rather than a custom property per element so the artwork
   stays plain SVG that another tool can regenerate. */
.ea-mark--animate .ea-ray:nth-child(1) { animation-delay: 0ms; }
.ea-mark--animate .ea-ray:nth-child(2) { animation-delay: 40ms; }
.ea-mark--animate .ea-ray:nth-child(3) { animation-delay: 80ms; }
.ea-mark--animate .ea-ray:nth-child(4) { animation-delay: 120ms; }
.ea-mark--animate .ea-ray:nth-child(5) { animation-delay: 160ms; }
.ea-mark--animate .ea-ray:nth-child(6) { animation-delay: 200ms; }
.ea-mark--animate .ea-ray:nth-child(7) { animation-delay: 240ms; }
.ea-mark--animate .ea-ray:nth-child(8) { animation-delay: 280ms; }
.ea-mark--animate .ea-ray:nth-child(9) { animation-delay: 320ms; }

.ea-mark--animate #eaGlobe .ea-draw:nth-child(1) { animation-delay: 380ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(2) { animation-delay: 430ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(3) { animation-delay: 470ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(4) { animation-delay: 500ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(5) { animation-delay: 500ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(6) { animation-delay: 470ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(7) { animation-delay: 560ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(8) { animation-delay: 540ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(9) { animation-delay: 620ms; }
.ea-mark--animate #eaGlobe .ea-draw:nth-child(10) { animation-delay: 660ms; }

.ea-mark--animate #eaBook .ea-draw:nth-child(1) { animation-delay: 900ms; }
.ea-mark--animate #eaBook .ea-draw:nth-child(2) { animation-delay: 990ms; }
.ea-mark--animate #eaBook .ea-draw:nth-child(3) { animation-delay: 1080ms; }

.ea-mark--animate .ea-pop:nth-child(1) { animation-delay: 1320ms; }
.ea-mark--animate .ea-pop:nth-child(2) { animation-delay: 1400ms; }
.ea-mark--animate .ea-pop:nth-child(3) { animation-delay: 1460ms; }

/* The token layer already zeroes the durations under prefers-reduced-motion,
   but a 0ms animation still runs its keyframes; the mark would flash from the
   `from` state. Drop the animations outright so it is simply there. */
@media (prefers-reduced-motion: reduce) {
    .ea-mark--animate .ea-ray,
    .ea-mark--animate .ea-draw,
    .ea-mark--animate .ea-pop {
        animation: none;
        stroke-dashoffset: 0;
        opacity: 1;
        transform: none;
    }
}

/* Hero panel that holds the mark. The mark brings its own whitespace, so the
   card pads less than a content card would. */
.lms-hero-mark {
    padding: var(--lms-space-sm);
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 991.98px) {
    .lms-hero-mark { max-width: 420px; margin-inline: auto; }
}
