/*
 * ── Custom-HTML landing template: the `lc-*` class system ───────────────────
 *
 * WHY THIS FILE EXISTS
 * Instructors paste AI-generated HTML (ChatGPT/Claude) into the panel and it
 * renders as their public landing page. That HTML lives in a JSON database
 * column — it is NEVER on disk, so Tailwind's `@source '../views'` scanner
 * (app.css:3) cannot see it. Tailwind v4 only compiles utilities it finds at
 * BUILD time, which means every Tailwind class the AI emits is a silent no-op:
 * `class="grid grid-cols-3 gap-6"` passes validation and renders as an
 * unstyled vertical column. That is the single most likely way this feature
 * ships broken.
 *
 * So the generated authoring brief tells the AI to use these `lc-*` classes
 * INSTEAD of Tailwind. Because this is hand-written CSS in a real file, it is
 * always in the bundle and can never be tree-shaken.
 *
 * RULES FOR EDITING THIS FILE
 *  1. No `@apply`, no Tailwind directives — this file must stay independent of
 *     the scanner it exists to work around.
 *  2. Logical properties ONLY (`margin-inline`, `padding-block`,
 *     `inset-inline-start`, `text-align: start`). The platform is Arabic-first
 *     and these pages render `dir="rtl"`; a single `margin-left` mirrors wrong
 *     and nobody notices until an instructor complains.
 *  3. Mobile-first, breakpoints baked in — the AI must never have to write a
 *     media query, because a media query it invents will be a Tailwind
 *     variant (`md:`) that does not exist here.
 *  4. No font-family anywhere. The page inherits type from its host layout.
 *
 * SPECIFICITY CONTRACT (deliberate, don't "simplify" it)
 *  · `lc-*` classes are written `#lmsc-root .lc-x`     → (1,1,0)
 *  · bare-tag defaults are written `:where(#lmsc-root) h1` → (0,0,1)
 * so a class ALWAYS beats the tag default it sits on. Same trick, same reason
 * as the educator template's `:where()` resets (educator.blade.php:139).
 *
 * CASCADE-LAYER CONTRACT (fixed 2026-08-10, don't regress it)
 *  · The BARE-TAG DEFAULTS live in `@layer base`. This file is imported AFTER
 *    tailwindcss in app.css, so within that layer they come later than
 *    Tailwind's preflight and win the tie on equal specificity — restoring the
 *    heading sizes and list markers preflight strips — while REAL utilities
 *    (@layer utilities) still beat them. That last part is the point: the
 *    first-party course/bundle cards mount INSIDE #lmsc-root and are styled
 *    with Tailwind utilities. Unlayered, these element defaults overrode the
 *    cards' own classes regardless of specificity (underlined card text,
 *    un-sized icons — the riyal glyph rendered at 234×262px), a platform bug
 *    an author could only fight with !important (prod org 50 did exactly
 *    that, 17 saves of workarounds).
 *  · The `lc-*` CLASSES stay unlayered: they only match elements that carry
 *    them, and nothing inside a mounted card does, so they cannot leak — and
 *    unlayered they keep beating preflight without depending on order.
 *  · Known residual: the `:where(.lc-bg-brand, .lc-bg-dark, …) :where(a)`
 *    colour rescues below are also unlayered and DO reach into a mounted card
 *    if an author wraps a block token in a dark band. Not moved into the layer
 *    because the `.lc-text-muted`-on-dark rescue depends on unlayered
 *    equal-specificity ordering against `.lc-text-muted` itself; revisit only
 *    with a headless check on a card inside `.lc-bg-dark`.
 */

/* The wrapper the instructor's HTML renders inside. Also the blast door.
   `contain` + `overflow: clip` + `isolation`/`z-index` exist because the
   author's HTML is untrusted-by-competence: an AI happily emits
   `position: fixed; inset: 0; z-index: 99999`, which would otherwise hit-test
   over the entire platform chrome, and `width: 100vw` / fixed-width tables,
   which push the document wider than the viewport and trigger page-wide
   horizontal scroll. This repo has already needed `.educator-template
   { overflow-x: clip }` for exactly that (educator.blade.php:136); here the
   containment is stricter because the markup is not ours. */
/* ⚠️ Containment lives on the SHELL, not on #lmsc-root, and the two must stay
   separate elements.

   CssScoper prefixes every author selector with `#lmsc-root ` and rewrites
   `body` / `html` / `:root` to `#lmsc-root` itself — so an author CAN write
   rules that land on #lmsc-root. If containment lived there, `body { contain:
   none; overflow: visible }` would switch it off and let a fixed-position
   element cover the page. The shell is an ancestor, and a prefixed selector can
   never match an ancestor, so nothing an author writes can reach it.

   `contain: layout` makes this the containing block for fixed-position
   descendants; `overflow: clip` stops a too-wide element producing page-wide
   sideways scroll (the bug that already forced `.educator-template {
   overflow-x: clip }` to exist); `isolation: isolate` keeps author z-index in
   its own stacking context. */
.lmsc-shell {
    contain: layout paint style;
    overflow: clip;
    isolation: isolate;
    position: relative;
    z-index: 0;
    max-width: 100%;
}

#lmsc-root {
    max-width: 100%;

    /* Brand. The server re-declares `--lc-brand` / `--lc-brand-ink` for this
       element in a nonce'd <style> block emitted by the template (NOT an inline
       style attribute — the strict CSP on custom pages blocks those, which
       silently defeated the brand colour until it was caught in a browser).
       Later in document order, so it wins; these stay as the fallback for an
       org with no colour set. Everything else is
       derived from that one hex via color-mix in oklab — the same idiom the
       Learn panel uses to build its shade ramp (LearnPanelProvider.php:338). */
    --lc-brand: #2f3788;
    --lc-brand-ink: #ffffff;
    --lc-brand-press: color-mix(in oklab, var(--lc-brand) 82%, black);
    --lc-brand-tint: color-mix(in oklab, var(--lc-brand) 8%, white);
    --lc-brand-line: color-mix(in oklab, var(--lc-brand) 22%, white);

    --lc-ink: #17171c;
    --lc-ink-2: #45454f;
    --lc-ink-3: #6f6f7b;
    --lc-surface: #ffffff;
    --lc-line: #e6e6ec;
    --lc-dark: #14141a;

    --lc-radius: 14px;
    --lc-radius-lg: 22px;
    --lc-shadow-sm: 0 1px 0 rgba(0, 0, 0, 0.02), 0 2px 6px rgba(20, 20, 30, 0.05);
    --lc-shadow-md: 0 1px 0 rgba(0, 0, 0, 0.02), 0 10px 30px rgba(20, 20, 30, 0.08);

    /* One spacing scale for every mt/mb/gap utility below. */
    --lc-s1: 0.25rem;
    --lc-s2: 0.5rem;
    --lc-s3: 1rem;
    --lc-s4: 1.5rem;
    --lc-s5: 2.5rem;
    --lc-s6: 4rem;

    --lc-maxw: 1180px;

    color: var(--lc-ink);
    line-height: 1.7;
    /* A pasted URL or unbroken token must wrap, not widen the page. */
    overflow-wrap: break-word;
}

/* Bare-tag defaults. Tailwind's preflight has already flattened h1–h6 to
   inherit and stripped list markers, so pasted semantic HTML would render as
   undifferentiated grey text without these. Zero specificity (see contract
   above) so any `lc-*` class the author adds still wins.

   ⚠️ IN `@layer base` ON PURPOSE — see the cascade-layer contract in the file
   header. These selectors match EVERYTHING under #lmsc-root, including the
   first-party course/bundle cards a block token mounts there; the layer is
   what lets the cards' Tailwind utilities win again. Preflight still loses to
   these on the tie because this file is imported after tailwindcss. */
@layer base {
    :where(#lmsc-root) *,
    :where(#lmsc-root) *::before,
    :where(#lmsc-root) *::after { box-sizing: border-box; }
    :where(#lmsc-root) h1 { font-size: 2.25rem; font-weight: 700; line-height: 1.2; margin-block: 0 var(--lc-s3); }
    :where(#lmsc-root) h2 { font-size: 1.75rem; font-weight: 700; line-height: 1.25; margin-block: 0 var(--lc-s3); }
    :where(#lmsc-root) h3 { font-size: 1.25rem; font-weight: 600; line-height: 1.35; margin-block: 0 var(--lc-s2); }
    :where(#lmsc-root) h4,
    :where(#lmsc-root) h5,
    :where(#lmsc-root) h6 { font-size: 1.05rem; font-weight: 600; line-height: 1.4; margin-block: 0 var(--lc-s2); }
    :where(#lmsc-root) p { margin-block: 0 var(--lc-s3); }
    :where(#lmsc-root) ul { list-style: disc; padding-inline-start: 1.4rem; margin-block: 0 var(--lc-s3); }
    :where(#lmsc-root) ol { list-style: decimal; padding-inline-start: 1.4rem; margin-block: 0 var(--lc-s3); }
    :where(#lmsc-root) li { margin-block: var(--lc-s1); }
    :where(#lmsc-root) a { color: var(--lc-brand); text-decoration: underline; }
    :where(#lmsc-root) strong, :where(#lmsc-root) b { font-weight: 700; }
    :where(#lmsc-root) em, :where(#lmsc-root) i { font-style: italic; }
    :where(#lmsc-root) img, :where(#lmsc-root) svg, :where(#lmsc-root) video { max-width: 100%; height: auto; }
    :where(#lmsc-root) blockquote {
        border-inline-start: 3px solid var(--lc-brand-line);
        padding-inline-start: var(--lc-s3);
        margin-block: var(--lc-s3);
        color: var(--lc-ink-2);
    }
    :where(#lmsc-root) :is(h1, h2, h3, h4, h5, h6, p, li, blockquote) {
        /* dir="auto" in CSS: each block resolves its own direction from its
           first strong character, so a stray English heading inside an Arabic
           page doesn't render mirrored. Same as app.css's .lesson-prose. */
        unicode-bidi: plaintext;
    }
}

/* ── Layout ─────────────────────────────────────────────────────────────── */

#lmsc-root .lc-page { width: 100%; background: var(--lc-surface); }

#lmsc-root .lc-section { padding-block: 3rem; padding-inline: 1.25rem; }
#lmsc-root .lc-section--tight { padding-block: 1.75rem; }

#lmsc-root .lc-container {
    width: 100%;
    max-width: var(--lc-maxw);
    margin-inline: auto;
}

#lmsc-root .lc-stack { display: flex; flex-direction: column; gap: var(--lc-s3); }

/* Wraps by default: an author's 4-item row must never force a scrollbar. */
#lmsc-root .lc-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--lc-s3);
}

/* ── Grids ──────────────────────────────────────────────────────────────────
   One column below 720px, always, with no media query on the author's side —
   that is the whole point. 3- and 4-up step through 2 columns first, because
   1 → 4 at a single breakpoint reads as a broken layout on a tablet. */

#lmsc-root .lc-grid-2,
#lmsc-root .lc-grid-3,
#lmsc-root .lc-grid-4 {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--lc-s4);
}

@media (min-width: 720px) {
    #lmsc-root .lc-section { padding-block: 4.5rem; padding-inline: 2rem; }
    #lmsc-root .lc-section--tight { padding-block: 2.5rem; }
    #lmsc-root .lc-grid-2,
    #lmsc-root .lc-grid-3,
    #lmsc-root .lc-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1000px) {
    #lmsc-root .lc-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    #lmsc-root .lc-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ── Text ───────────────────────────────────────────────────────────────────
   clamp() rather than breakpoints so display type scales continuously — again,
   so the author never reaches for a media query. No letter-spacing anywhere:
   Arabic letterforms join, and tracking visibly breaks the joins. */

#lmsc-root .lc-h1 {
    font-size: clamp(1.9rem, 1.35rem + 2.6vw, 3.25rem);
    font-weight: 700;
    line-height: 1.15;
    margin-block: 0 var(--lc-s3);
}
#lmsc-root .lc-h2 {
    font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.25rem);
    font-weight: 700;
    line-height: 1.2;
    margin-block: 0 var(--lc-s3);
}
#lmsc-root .lc-h3 {
    font-size: clamp(1.15rem, 1.02rem + 0.6vw, 1.4rem);
    font-weight: 600;
    line-height: 1.35;
    margin-block: 0 var(--lc-s2);
}
#lmsc-root .lc-lede {
    font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem);
    line-height: 1.75;
    color: var(--lc-ink-2);
    max-width: 62ch;
}
#lmsc-root .lc-body { font-size: 1rem; line-height: 1.75; color: var(--lc-ink-2); }
#lmsc-root .lc-caption { font-size: 0.85rem; line-height: 1.6; color: var(--lc-ink-3); }
#lmsc-root .lc-eyebrow {
    display: block;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--lc-brand);
    margin-block-end: var(--lc-s2);
}
#lmsc-root .lc-center { text-align: center; }
#lmsc-root .lc-start { text-align: start; }
/* A centred lede would otherwise stay pinned to the start edge by its max-width. */
#lmsc-root .lc-center .lc-lede,
#lmsc-root .lc-lede.lc-center { margin-inline: auto; }

/* ── Surfaces ───────────────────────────────────────────────────────────── */

#lmsc-root .lc-card {
    background: var(--lc-surface);
    border: 1px solid var(--lc-line);
    border-radius: var(--lc-radius);
    padding: var(--lc-s4);
    box-shadow: var(--lc-shadow-sm);
}
#lmsc-root .lc-card--soft { background: var(--lc-brand-tint); border-color: var(--lc-brand-line); box-shadow: none; }
#lmsc-root .lc-panel {
    background: var(--lc-brand-tint);
    border: 1px solid var(--lc-brand-line);
    border-radius: var(--lc-radius-lg);
    padding: var(--lc-s5);
}
/* Works as either <hr> or <div>; `border: 0` first so the UA hr rule loses. */
#lmsc-root .lc-divider {
    border: 0;
    border-block-start: 1px solid var(--lc-line);
    block-size: 0;
    margin-block: var(--lc-s4);
}
#lmsc-root .lc-rounded { border-radius: var(--lc-radius-lg); overflow: hidden; }
#lmsc-root .lc-shadow { box-shadow: var(--lc-shadow-md); }

/* ── Colour ─────────────────────────────────────────────────────────────────
   Tinted/dark surfaces set `color` and let it inherit, so headings and body
   copy follow automatically — an author can't produce black-on-black. Links
   and muted text need explicit rescuing; both use `:where()` on the descendant
   so a button or utility placed inside still wins. */

#lmsc-root .lc-bg-brand { background: var(--lc-brand); color: var(--lc-brand-ink); }
#lmsc-root .lc-bg-tint { background: var(--lc-brand-tint); }
#lmsc-root .lc-bg-dark { background: var(--lc-dark); color: #ffffff; }
#lmsc-root .lc-on-dark { color: #ffffff; }
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) :where(a) {
    color: inherit;
    text-decoration-color: color-mix(in oklab, currentColor 50%, transparent);
}
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) :where(blockquote) {
    border-inline-start-color: color-mix(in oklab, currentColor 35%, transparent);
    color: inherit;
}
#lmsc-root .lc-text-brand { color: var(--lc-brand); }
#lmsc-root .lc-text-muted { color: var(--lc-ink-3); }
/* Placed after .lc-text-muted on purpose — equal specificity, later wins, so
   muted text on a dark surface fades from white instead of staying dark grey. */
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) .lc-text-muted,
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) .lc-caption {
    color: color-mix(in oklab, currentColor 72%, transparent);
}
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) .lc-text-brand,
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) .lc-eyebrow { color: inherit; }

/* ── Buttons ────────────────────────────────────────────────────────────────
   The author will use <a> as often as <button>, so the base neutralises both.
   :focus-visible is kept because these are real public pages. */

#lmsc-root .lc-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--lc-s2);
    padding-block: 0.7rem;
    padding-inline: 1.4rem;
    border: 1px solid transparent;
    border-radius: 10px;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    background: none;
    color: inherit;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
#lmsc-root .lc-btn:focus-visible { outline: 2px solid var(--lc-brand); outline-offset: 2px; }
#lmsc-root .lc-btn--primary { background: var(--lc-brand); color: var(--lc-brand-ink); border-color: var(--lc-brand); }
#lmsc-root .lc-btn--primary:hover { background: var(--lc-brand-press); border-color: var(--lc-brand-press); }
#lmsc-root .lc-btn--ghost { background: transparent; color: var(--lc-brand); border-color: var(--lc-brand-line); }
#lmsc-root .lc-btn--ghost:hover { background: var(--lc-brand-tint); border-color: var(--lc-brand); }
#lmsc-root .lc-btn--lg { padding-block: 0.95rem; padding-inline: 2rem; font-size: 1.05rem; }
/* A brand-coloured button on a brand-coloured band would vanish; invert it. */
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) .lc-btn--primary {
    background: var(--lc-brand-ink);
    color: var(--lc-brand);
    border-color: var(--lc-brand-ink);
}
#lmsc-root :where(.lc-bg-brand, .lc-bg-dark, .lc-on-dark) .lc-btn--ghost {
    color: inherit;
    border-color: color-mix(in oklab, currentColor 45%, transparent);
}

/* ── Images ─────────────────────────────────────────────────────────────── */

#lmsc-root .lc-img { display: block; width: 100%; height: auto; border-radius: var(--lc-radius); }
#lmsc-root .lc-img--round { aspect-ratio: 1; border-radius: 50%; object-fit: cover; }
#lmsc-root .lc-img--cover { aspect-ratio: 16 / 9; height: 100%; object-fit: cover; }
#lmsc-root .lc-logo { display: block; block-size: 40px; inline-size: auto; object-fit: contain; }

/* ── Spacing ────────────────────────────────────────────────────────────────
   Block-axis logical props: identical to top/bottom in a horizontal writing
   mode (RTL only mirrors the inline axis), and they keep this file free of
   physical directions so the RTL grep stays clean. */

#lmsc-root .lc-mt-1 { margin-block-start: var(--lc-s1); }
#lmsc-root .lc-mt-2 { margin-block-start: var(--lc-s2); }
#lmsc-root .lc-mt-3 { margin-block-start: var(--lc-s3); }
#lmsc-root .lc-mt-4 { margin-block-start: var(--lc-s4); }
#lmsc-root .lc-mt-5 { margin-block-start: var(--lc-s5); }
#lmsc-root .lc-mt-6 { margin-block-start: var(--lc-s6); }

#lmsc-root .lc-mb-1 { margin-block-end: var(--lc-s1); }
#lmsc-root .lc-mb-2 { margin-block-end: var(--lc-s2); }
#lmsc-root .lc-mb-3 { margin-block-end: var(--lc-s3); }
#lmsc-root .lc-mb-4 { margin-block-end: var(--lc-s4); }
#lmsc-root .lc-mb-5 { margin-block-end: var(--lc-s5); }
#lmsc-root .lc-mb-6 { margin-block-end: var(--lc-s6); }

#lmsc-root .lc-gap-1 { gap: var(--lc-s2); }
#lmsc-root .lc-gap-2 { gap: var(--lc-s3); }
#lmsc-root .lc-gap-3 { gap: var(--lc-s4); }
#lmsc-root .lc-gap-4 { gap: var(--lc-s5); }

/* Motion: the author's HTML may carry transitions we didn't write, but ours
   should still respect the OS preference. */
@media (prefers-reduced-motion: reduce) {
    #lmsc-root .lc-btn { transition: none; }
}
