/*
 * Moss theme — public-site palette swap.
 *
 * Applies the "Moss" background palette (soft-green surfaces) and
 * Ubuntu typography over the existing Crafto theme without
 * restructuring markup. Loaded AFTER the Crafto stylesheets in
 * `templates/public/base.html.twig` so these rules win the cascade.
 *
 * Spec: `Moss Theme Specification` provided by the user on
 * 2026-05-17. Branch: `experiment/app-courses-public-design`.
 *
 * Conventions:
 *   - `!important` is used to defeat Crafto utility-class colors
 *     and inline `style="background-image: url(...)"` on the
 *     page-title partial. Necessary because the existing markup
 *     uses very narrow selectors that we can't beat with specificity
 *     alone without `!important`.
 *   - `--brand-yellow` (#D4E300) and `--brand-ink` (#1A2E1E) stay
 *     constant; only surface + text tokens shift between palette
 *     variants. Yellow is ONLY a fill, never a text/icon color on
 *     a light background.
 */

/* ---------- 1. Tokens -------------------------------------------- */

:root {
    /* Brand (constant across palettes) */
    --brand-yellow: #D4E300;
    --brand-ink:    #1A2E1E;
    --on-yellow:    #1A2E1E;

    /* Moss surfaces */
    --surface-1:    #F1F4ED;
    --surface-2:    #E6EDDC;
    --surface-3:    #DDE6CD;
    --hero-bg:      #DDE6CB;
    --border:       #C9D5B5;
    --border-strong:#B7C9A0;
    --logo-mark-bg: #D2DEBE;
    --chip-bg:      #D8E3C5;

    /* Text on light surfaces */
    --text-1: #0F172A;
    --text-2: #334155;
    --text-3: #64748B;

    /* Footer (dark-green panel, unchanged from spec) */
    --footer-bg:  #1A2E1E;
    --on-dark-1:  rgba(255, 255, 255, 0.95);
    --on-dark-2:  rgba(255, 255, 255, 0.78);
    --on-dark-3:  rgba(255, 255, 255, 0.62);

    /* Crafto theme's display + body fonts default to Plus Jakarta
     * Sans / Inter (see style.min.css `:root`). moss-theme.css loads
     * after Crafto on every public page, so these two declarations
     * win the equal-specificity tie and rebind `.alt-font` consumers
     * (navbar nav, page-title heroes, headings, course cards, …)
     * + `var(--primary-font)` consumers (body, paragraphs) to
     * Ubuntu. Admin / Silva / student shells don't load Crafto and
     * don't read these vars, so the override is public-site-scoped
     * by virtue of where it's loaded.
     */
    --alt-font:     "Ubuntu", system-ui, sans-serif;
    --primary-font: "Ubuntu", system-ui, sans-serif;
}

/* ---------- 2. Typography ---------------------------------------- */

html,
body {
    font-family: "Ubuntu", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Ubuntu has no 600/800 — Crafto's `fw-600` and `fw-800` classes
 * are mapped to 500 + 700 (the closest weights Ubuntu ships). */
.fw-600 { font-weight: 500 !important; }
.fw-800 { font-weight: 700 !important; }

/* ---------- 2a. Public-site type scale (2026-05-27) -------------
 *
 * Six-step responsive scale shared across every page rendered
 * inside `<main id="main-content">` (set by templates/public/
 * base.html.twig). Heading-tag selectors (`main h1` … `main h4`)
 * give us a single point of control for size + line-height +
 * weight + tracking + bottom margin across every public template,
 * regardless of the Crafto utility classes the per-page markup
 * still carries — the cascade-level rules below are
 * intentionally NOT marked `!important` for size/weight, so an
 * explicit `.fs-XX` class on a heading is still allowed to win
 * when a specific page needs a one-off ramp (hero numbers,
 * 90-pt stats, etc).
 *
 * H1 → 3xl  56 → 32 px   page hero (one per page)
 * H2 → 2xl  40 → 28 px   major section
 * H3 → xl   28 → 22 px   subsection
 * H4 → lg   22 → 18 px   card title, tile heading
 * H5 → md   18 → 16 px   lead paragraph, label
 * H6 → sm   14 → 13 px   eyebrow / caption
 *
 * Casing is enforced at the template level (Title Case across
 * H1-H4) — no `text-transform` here so admin-authored landing
 * page block content keeps the exact casing the author typed. */

:root {
    --fs-3xl: clamp(2.00rem, 1.40rem + 2.50vw, 3.50rem);  /* 32 → 56 */
    --fs-2xl: clamp(1.75rem, 1.40rem + 1.50vw, 2.50rem);  /* 28 → 40 */
    --fs-xl:  clamp(1.375rem, 1.20rem + 0.75vw, 1.75rem); /* 22 → 28 */
    --fs-lg:  clamp(1.125rem, 1.05rem + 0.30vw, 1.375rem);/* 18 → 22 */
    --fs-md:  clamp(1.00rem, 0.95rem + 0.20vw, 1.125rem); /* 16 → 18 */
    --fs-sm:  clamp(0.8125rem, 0.78rem + 0.10vw, 0.875rem);/* 13 → 14 */

    --lh-tight:   1.15;  /* display + H1 */
    --lh-snug:    1.25;  /* H2-H4 */
    --lh-normal:  1.55;  /* body */

    --tracking-tight: -0.02em;
    --tracking-snug:  -0.01em;
    --tracking-normal: 0;
}

main h1,
main .ceet-h1 {
    font-size: var(--fs-3xl);
    line-height: var(--lh-tight);
    font-weight: 700;
    letter-spacing: var(--tracking-tight);
    color: var(--text-1, var(--brand-ink));
    margin: 0 0 0.5em;
}
main h2,
main .ceet-h2 {
    font-size: var(--fs-2xl);
    line-height: var(--lh-snug);
    font-weight: 700;
    letter-spacing: var(--tracking-snug);
    color: var(--text-1, var(--brand-ink));
    margin: 0 0 0.6em;
}
main h3,
main .ceet-h3 {
    font-size: var(--fs-xl);
    line-height: var(--lh-snug);
    font-weight: 600;
    letter-spacing: var(--tracking-snug);
    color: var(--text-1, var(--brand-ink));
    margin: 0 0 0.5em;
}
main h4,
main .ceet-h4 {
    font-size: var(--fs-lg);
    line-height: var(--lh-snug);
    font-weight: 600;
    letter-spacing: var(--tracking-normal);
    color: var(--text-1, var(--brand-ink));
    margin: 0 0 0.5em;
}
main h5,
main .ceet-h5 {
    font-size: var(--fs-md);
    line-height: var(--lh-snug);
    font-weight: 600;
    letter-spacing: var(--tracking-normal);
    color: var(--text-1, var(--brand-ink));
    margin: 0 0 0.4em;
}
/* Crafto's vertical-counter component repurposes <h5> as a big stat
 * digit (home page hero counters). Treat it as display-scale + bold,
 * not the small label our generic H5 rule would shrink it to. */
main h5.vertical-counter,
main h5.vertical-counter-down,
main h5.vertical-counter-up {
    font-size: var(--fs-3xl);
    font-weight: 700;
    letter-spacing: var(--tracking-tight);
    line-height: var(--lh-tight);
    margin: 0;
}
main h6,
main .ceet-h6 {
    font-size: var(--fs-sm);
    line-height: var(--lh-snug);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-2, currentColor);
    margin: 0 0 0.4em;
}

/* Lead paragraph helper — for the one-line subtitle under a page
 * heading. Use as `<p class="ceet-lead">`. */
main .ceet-lead {
    font-size: var(--fs-md);
    line-height: var(--lh-normal);
    color: var(--text-2, currentColor);
    margin: 0 0 1em;
}

/* Caption / meta helper for thumbnails + footer notes. */
main .ceet-caption {
    font-size: var(--fs-sm);
    line-height: var(--lh-normal);
    color: var(--text-2, currentColor);
    margin: 0;
}

/* Reset Crafto's utility-class margin-bottoms on headings that we
 * now manage with the bottom margin above. Page-level mb-3/mb-4
 * still works (set on the wrapping div), this just kills doubled
 * spacing when the class lands on the <h*> itself. */
main h1.mb-0,
main h2.mb-0,
main h3.mb-0,
main h4.mb-0,
main h5.mb-0,
main h6.mb-0 {
    margin-bottom: 0;
}

/* ---------- 3. Page + body --------------------------------------- */

body {
    background-color: var(--surface-1);
    color: var(--text-2);
}

/* ---------- 4. Header -------------------------------------------- */

header .navbar.bg-white,
header .navbar.header-light.bg-white {
    background-color: var(--surface-1) !important;
    border-bottom: 1px solid var(--border);
}

header .nav-link,
header .nav-link:link,
header .nav-link:visited {
    color: var(--text-1) !important;
}

/* Responsive nav-link sizing. Crafto defaults every `.nav-link` to
 * `padding: 10px 20px; font-size: 16px` regardless of viewport. With
 * 6 nav items + phone CTA + Sign up pill + Login link competing for
 * horizontal space, the right-hand CTAs get clipped on 13"-15"
 * laptops (1366-1599 px) and even on some 1080p externals when
 * the browser chrome isn't full-width. Tighten the padding +
 * font-size in steps so the menu always fits.
 *
 * Above 1600 px:  Crafto defaults                (10 / 20 px, 16 px)
 * 1400-1599 px:   tighter padding                (10 / 14 px, 15 px)
 * 1200-1399 px:   tighter still, smaller font    (8 / 10 px, 14 px)
 * < 1200 px:      navbar collapses to hamburger via Bootstrap's
 *                 navbar-expand-lg breakpoint — nothing to do. */
@media (max-width: 1599.98px) {
    header .navbar .navbar-nav .nav-link {
        padding: 10px 14px !important;
        font-size: 15px !important;
    }
}
@media (max-width: 1399.98px) {
    header .navbar .navbar-nav .nav-link {
        padding: 8px 10px !important;
        font-size: 14px !important;
    }
    /* Tighten the right-side CTA cluster gap too — Crafto's gap-3
     * (1 rem ≈ 16 px) eats too much space on narrow viewports. */
    header .navbar + div .gap-3,
    header .navbar .gap-3 {
        gap: 0.6rem !important;
    }
    /* Compact the Sign up pill at this breakpoint — drop the icon
     * down to keep the label readable while still under-20 px tall. */
    header .btn.btn-small.btn-base-color.btn-rounded {
        padding: 6px 12px !important;
        font-size: 12px !important;
    }
}

/* CTA cluster must never shrink. Bootstrap's `col-lg-auto` is
 * supposed to size to content, but when the row total exceeds the
 * container width, flex-shrink (default `1`) lets it compress and
 * clip — which manifested as a half-visible "Sign u…" + missing
 * Login on 1366×768 laptops. Pinning `flex-shrink: 0` keeps the
 * Sign up + Login cluster intact; the navbar items shrink first
 * (via the responsive nav-link padding above), and if they still
 * don't fit at very small widths Bootstrap's hamburger takes over
 * below 992 px. */
header .navbar .col-lg-auto.text-end,
header .navbar > .container-fluid > .col-lg-auto {
    flex-shrink: 0;
}

/* ---------- 5. Crafto color utilities (global overrides) ---------- */

/* Headings + body text */
.text-dark-gray,
.text-dark-gray:link,
.text-dark-gray:visited { color: var(--text-1) !important; }

.text-medium-gray { color: var(--text-2) !important; }

/* Brand accent — was yellow, now dark-green ink (icons + accents) */
.text-base-color { color: var(--brand-ink) !important; }
a.text-base-color-hover:hover,
.text-base-color-hover:hover { color: var(--brand-ink) !important; }

/* Brand fills */
.bg-base-color {
    background-color: var(--brand-yellow) !important;
    color: var(--on-yellow) !important;
}

/* Surfaces */
.bg-tranquil           { background-color: var(--surface-2) !important; }
.bg-very-light-gray    { background-color: var(--surface-1) !important; }
.bg-white              { background-color: var(--surface-1) !important; }

/* Borders */
.border-color-extra-medium-gray { border-color: var(--border) !important; }

/* ---------- 6. Buttons ------------------------------------------- */

/* Crafto's `.btn` defaults don't pin `white-space`, so a multi-word
 * label in a tight flex cell wraps mid-pill — splits as
 * "▶ Get the Android" / "app" with the wrapped word awkwardly
 * centred. Force every button label onto one line; if a button truly
 * doesn't fit its container, an honest overflow is easier to spot
 * and fix than a covertly-broken pill. Applies sitewide. */
.btn {
    white-space: nowrap;
}

/* Brand-filled primary — yellow fill, dark text */
.btn.btn-base-color,
.btn.btn-base-color:hover,
.btn.btn-base-color:focus {
    background-color: var(--brand-yellow) !important;
    border-color: var(--brand-yellow) !important;
    color: var(--on-yellow) !important;
}

/* Outlined dark-ink (was outlined yellow) */
.btn.btn-transparent-base-color,
.btn.btn-transparent-base-color:link,
.btn.btn-transparent-base-color:visited {
    background-color: transparent !important;
    border: 1.5px solid var(--brand-ink) !important;
    color: var(--brand-ink) !important;
}
.btn.btn-transparent-base-color:hover,
.btn.btn-transparent-base-color:focus {
    background-color: var(--brand-ink) !important;
    color: #ffffff !important;
}

/* Outlined dark-gray text — used for "Talk to us" */
.btn.btn-transparent-dark-gray,
.btn.btn-transparent-dark-gray:link,
.btn.btn-transparent-dark-gray:visited {
    background-color: transparent !important;
    border: 1.5px solid var(--text-1) !important;
    color: var(--text-1) !important;
}
.btn.btn-transparent-dark-gray:hover,
.btn.btn-transparent-dark-gray:focus {
    background-color: var(--text-1) !important;
    color: #ffffff !important;
}

/* btn-link inside the public site — kill the ghost-link tone in
 * favour of a readable link colour. */
.btn.btn-link {
    color: var(--brand-ink) !important;
    text-decoration: underline;
}

/* Firebase "Continue with Google" button — Material-style white
 * card with a light grey border. The Crafto `.btn` base strips
 * background + border, so we re-paint explicitly. Sits above the
 * email/password form on /login + /register. */
.btn.firebase-google-btn,
.btn.firebase-google-btn:link,
.btn.firebase-google-btn:visited {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background-color: #ffffff !important;
    color: var(--text-1, #1F2937) !important;
    border: 1px solid var(--border, #C9D5B5) !important;
    border-radius: 999px !important;
    padding: 10px 18px !important;
    font-weight: 500 !important;
    font-size: 15px !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    line-height: 1.4 !important;
    transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.btn.firebase-google-btn:hover,
.btn.firebase-google-btn:focus {
    background-color: var(--surface-1, #F1F4ED) !important;
    border-color: var(--border-strong, #B7C9A0) !important;
    color: var(--text-1, #1F2937) !important;
    box-shadow: 0 1px 4px rgba(20, 60, 50, 0.08);
}
.btn.firebase-google-btn[disabled],
.btn.firebase-google-btn.is-loading {
    opacity: 0.6;
    cursor: not-allowed;
}
.firebase-google-btn-icon {
    display: inline-flex;
    align-items: center;
}

/* Bootstrap `.form-check` checkbox rescue. Crafto's
 * `style.min.css` has TWO rules that fight Bootstrap's native
 * checkbox UI:
 *   (a) `input[type=checkbox] { opacity:0; visibility:hidden;
 *       position:absolute }` — for Crafto's own
 *       custom-checkbox-via-label pattern. Hides every
 *       Bootstrap-styled checkbox.
 *   (b) `.form-control, .form-select, input, select, textarea {
 *       padding: 12px 25px; width: 100%; max-width: 100% }` —
 *       a blanket sizing rule that stretches a `<input
 *       type=checkbox>` into a ~24×50 px rectangle.
 * Override BOTH inside `.form-check` so Bootstrap's standard
 * remember-me / Turnstile-fallback / future-signup-options
 * checkboxes render correctly without disrupting the rest of
 * Crafto's form styling. Bootstrap's `.form-check-input`
 * sizes (1em × 1em, float left, -1.5em margin-left) take over. */
.form-check input[type=checkbox] {
    opacity: 1 !important;
    visibility: visible !important;
    position: static !important;
    width: 1em !important;
    height: 1em !important;
    max-width: 1em !important;
    padding: 0 !important;
    margin: 0 !important;
    flex-shrink: 0;
    /* Bootstrap's normal background-image + colours still render
     * because they're set on the `.form-check-input` class with
     * specificity 0,1,0 — lower than the inline `!important`
     * overrides above. */
}
/* Bootstrap defaults the `.form-check` to `display: block` +
 * float-left input, which puts the checkbox vertically wherever
 * its line-box anchor falls (typically a few px above the label
 * baseline). Switching to flex with `align-items: center` makes
 * the checkbox and label share a vertical centre — which then
 * aligns cleanly with sibling content in a parent
 * `.d-flex.align-items-center` row (e.g. the remember-me /
 * forgot-password row on /login). Also kills Bootstrap's
 * `padding-left: 1.5em` + `margin-left: -1.5em` dance since
 * flex-gap replaces it cleanly. */
.form-check {
    display: inline-flex !important;
    align-items: center;
    gap: 0.5em;
    padding-left: 0 !important;
    min-height: 0;
}
.form-check .form-check-input {
    float: none !important;
    margin-left: 0 !important;
}
.form-check .form-check-label {
    padding-left: 0;
    line-height: 1.2;
}

/* ---------- 7. Hero / page-title partial ------------------------- */

/* The crafto `page-title-big-typography` partial sets a
 * `background-image` via inline style. Force the Moss flat
 * fill — defeats both the .cover-background util AND the inline
 * style. */
.page-title-big-typography,
.page-title-big-typography.cover-background,
.page-title-big-typography.bg-very-light-gray {
    background-image: none !important;
    background-color: var(--hero-bg) !important;
}

.page-title-big-typography h1,
.page-title-big-typography .text-dark-gray { color: var(--text-1) !important; }

.page-title-big-typography p { color: var(--text-2) !important; }

/* Hero layout — symmetric padding + a navbar-clearing margin-top
 * that applies at EVERY viewport.
 *
 * Trap: the partial uses Crafto's `.ipad-top-space-margin` class
 * which sets `margin-top: 76px` — but only inside
 * `@media (max-width:991px)`. On desktop the rule never fires,
 * so the section sits at y=0 and the position:fixed navbar
 * (~96 px tall) overlays its top, clipping the heading.
 * Crafto's desktop equivalent is `.top-space-margin`
 * (margin-top: 96px, no media gate) but we can't retroactively
 * rename the utility class on the partial without touching it,
 * so we mirror the same 96 px push here unconditionally.
 *
 * Symmetric 80 px padding inside the navbar-cleared section
 * gives identical breathing room above + below the inner
 * content across every breakpoint. */
.page-title-big-typography.ipad-top-space-margin {
    margin-top: 96px !important;
    height: auto !important;
    padding-top: 80px !important;
    padding-bottom: 80px !important;
}

/* Home hero — restore top padding on mobile. The crafto-themed
 * markup uses `p-0` (zeroes every side) and pairs it with
 * `md-pb-70px sm-pb-40px` for bottom-only padding. No matching
 * top padding utility means the heading slams against the section's
 * top edge on mobile (looked clipped in the 2026-05-20 screenshot).
 * `ipad-top-space-margin` does push the section down via
 * `margin-top` outside the green surface, but that's OUTSIDE the
 * dark background — the heading still needs internal breathing
 * room above it. */
/* PERMANENT FIX for the home hero / navbar overlap.
 *
 * Crafto's `full-screen` utility hard-pins `height: 100vh` and the
 * paired `align-items-center` on the inner row centres content
 * inside that fixed box. Whenever the inner content is taller than
 * the (viewport − navbar) region — which happens whenever the H1
 * wraps to more lines than expected (narrow columns, short
 * viewports, OS chrome eating into the height) — the centred
 * column slides UP into the position:fixed navbar's overlapping
 * zone and the first line of the heading gets clipped.
 *
 * Three structural changes, no viewport-specific media queries:
 *
 *   1. `height: 100vh` → `min-height: 100vh`. The section keeps
 *      its full-bleed visual feel but can grow past the viewport
 *      when content demands it, so the centred column never has
 *      to bleed upward to fit.
 *
 *   2. Reserve the navbar's height as `padding-top` at every
 *      viewport. The inner row's effective vertical-centre is now
 *      (viewport − navbar) instead of (viewport), so the navbar
 *      can never overlap the content even at the tallest possible
 *      H1 wrap. Bottom padding stays symmetrical so the counter
 *      strip doesn't sit on top of the section edge.
 *
 *   3. Replace the fixed `fs-75 / lh-65` ramp on the H1 with a
 *      `clamp()` curve that scales fluidly from 36 px (smallest)
 *      through 56–72 px (typical laptop) up to 80 px (≥ 1900 px
 *      ultrawide). Single rule, no breakpoint hopping. The crafto
 *      `sm-fs-50` width-gated variant is overridden too so the
 *      clamp wins on every width.
 *
 * Scoped to the home hero alone via the long
 * `section.bg-dark-gray.full-screen.ipad-top-space-margin`
 * selector — other pages that adopt `full-screen` (notably the
 * leaderboards hero) keep Crafto's defaults. */
section.bg-dark-gray.full-screen.ipad-top-space-margin {
    height: auto !important;
    min-height: 100vh;
    padding-top: 120px !important;
    padding-bottom: 60px !important;
}
section.bg-dark-gray.full-screen.ipad-top-space-margin > .container > .row {
    /* Keep `align-items-center` but anchor the centring inside the
     * post-padding region — at any viewport, the row's min-height
     * equals (100vh − padding-top − padding-bottom) so content
     * vertically centres in the safe area without ever crossing
     * into the navbar zone. */
    min-height: calc(100vh - 180px);
}
section.bg-dark-gray.full-screen.ipad-top-space-margin .alt-font.fs-75,
section.bg-dark-gray.full-screen.ipad-top-space-margin .alt-font.fs-75.sm-fs-50 {
    /* 36 px on the smallest phones → ~56 px on a 1366 px laptop
     * → ~72 px on a 1920 px desktop → 80 px ceiling on 4K. The
     * 3.6vw + 1rem curve is gentle enough that the heading reads
     * the same at every typical viewport without ever forcing the
     * content past the section's visible region. */
    font-size: clamp(2.25rem, 3.6vw + 0.5rem, 5rem) !important;
    line-height: 1.05 !important;
}

/* Mobile-only inner padding kept from the previous rules — at
 * ≤ 991 px the `ipad-top-space-margin` adds margin OUTSIDE the
 * green panel (top of the section), which leaves the heading
 * pressed against the dark surface's top edge without breathing
 * room. These restore that breathing room inside the panel. */
@media (max-width: 991.98px) {
    section.bg-dark-gray.full-screen.ipad-top-space-margin {
        padding-top: 50px !important;
    }
}
@media (max-width: 575.98px) {
    section.bg-dark-gray.full-screen.ipad-top-space-margin {
        padding-top: 40px !important;
    }
}

/* ---------- 8. Online-course detail page hooks ------------------- */
/* Class hooks added in templates/public/online_course/detail.html.twig
 * for elements that need precise styling beyond the global utility
 * overrides above. Layout untouched — these add colours + chip
 * shapes only. */

/* Stats strip — surface-2 sits between page (-1) and hero (-bg) */
.oc-stats-strip {
    background-color: var(--surface-2) !important;
    border-bottom: 1px solid var(--border);
}
.oc-stats-strip .feather,
.oc-stats-strip i { color: var(--text-3) !important; }
.oc-stats-strip .alt-font.fw-700 { color: var(--text-1) !important; }
.oc-stats-strip .fs-13 { color: var(--text-2) !important; }

/* Unlock-all banner — sits below the curriculum on non-enrolled view */
.oc-unlock-banner {
    background-color: var(--surface-3) !important;
    border: 1px solid var(--border) !important;
    border-radius: 12px;
}
.oc-unlock-banner i.feather { color: var(--text-3) !important; }
.oc-unlock-banner strong { color: var(--text-1) !important; font-weight: 700; }

/* Sidebar buy card */
.oc-buy-card {
    background-color: var(--surface-1) !important;
    border: 1px solid var(--border) !important;
}
.oc-buy-card .featured-badge {
    background-color: var(--brand-yellow) !important;
    color: var(--on-yellow) !important;
}
.oc-buy-card .price { color: var(--text-1) !important; }
.oc-buy-card ul li i.feather { color: var(--text-2) !important; }
.oc-buy-card ul { border-top: 1px dashed var(--border) !important; }

/* Curriculum cards */
.oc-curriculum-card {
    background-color: var(--surface-1) !important;
    border: 1px solid var(--border) !important;
    transition: border-color 0.15s ease;
}
.oc-curriculum-card:hover { border-color: var(--border-strong) !important; }
.oc-curriculum-card details[open] > summary {
    border-bottom: 1px dashed var(--border);
}

/* Number chip in the curriculum row (01 / 02 / 03 …) */
.oc-curriculum-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    background-color: var(--chip-bg) !important;
    color: var(--brand-ink) !important;
    border-radius: 999px;
    font-weight: 700;
    font-size: 13px;
    flex-shrink: 0;
}

/* "Exams (N)" / "Notes (N)" / "Video lessons (N)" sub-pill —
 * `display: inline-flex !important` defeats Crafto's `.alt-font`
 * which can force `display: block` in certain ancestor contexts;
 * `white-space: nowrap` keeps icon + label + count on a single
 * line so the chip stays pill-shaped rather than blobbing into
 * a balloon when the content tries to wrap. `width: max-content`
 * caps the chip to its content so it never stretches into a
 * full-row block. */
.oc-resource-pill {
    display: inline-flex !important;
    align-items: center;
    gap: 4px;
    background-color: var(--chip-bg) !important;
    color: var(--brand-ink) !important;
    padding: 4px 12px;
    border-radius: 999px;
    font-weight: 500;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1.2;
    white-space: nowrap;
    width: max-content;
    max-width: 100%;
    margin-bottom: 8px;
}
.oc-resource-pill > i.feather {
    font-size: 12px;
    margin-right: 0 !important;
}
/* Small contextual suffix on the resource pill — "Notes (3) · mobile app".
   Slightly muted versus the main label so it reads as a note rather
   than competing for attention. */
.oc-resource-pill-suffix {
    color: var(--text-3) !important;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    margin-left: 4px;
}

/* Curriculum resource-row icons — never yellow */
.oc-curriculum-card .feather { color: var(--text-3); }
.oc-curriculum-card li > span.lh-22 { color: var(--text-2); }

/* ---------- 8.5 Notes-app-only callout (course detail) ---------- */
/* Sits between the at-a-glance stats and the main course body.
 * Visually distinct enough to be noticed before a prospect enrols,
 * but coherent with the rest of the moss palette so it doesn't
 * read as a system warning. The yellow-tinted left border anchors
 * it to the brand's primary fill while the white surface keeps it
 * readable on the mint-tinted page background. */
.oc-app-only-callout {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 18px 22px;
    background-color: var(--surface-1);
    border: 1px solid var(--border);
    border-left: 4px solid var(--brand-yellow);
    border-radius: 10px;
}
.oc-app-only-callout-icon {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    background-color: var(--brand-ink);
    color: var(--brand-yellow);
    display: grid;
    place-items: center;
    flex-shrink: 0;
}
.oc-app-only-callout-icon i.feather {
    font-size: 22px;
}
.oc-app-only-callout-body {
    flex: 1;
    min-width: 0;
}
.oc-app-only-callout-cta {
    flex-shrink: 0;
    white-space: nowrap;
}
/* On phone widths the CTA wraps below the text so the body has
 * full width to breathe. */
@media (max-width: 720px) {
    .oc-app-only-callout {
        flex-wrap: wrap;
        gap: 14px;
    }
    .oc-app-only-callout-cta {
        width: 100%;
        text-align: center;
    }
}

/* ---------- 9. Footer (dark green panel) ------------------------- */

footer {
    background-color: var(--footer-bg) !important;
}

footer h1, footer h2, footer h3, footer h4, footer h5, footer h6,
footer .h1, footer .h2, footer .h3, footer .h4, footer .h5, footer .h6 {
    color: #ffffff !important;
}

footer p,
footer li,
footer span,
footer a,
footer a:link,
footer a:visited { color: var(--on-dark-2) !important; }

footer a:hover { color: #ffffff !important; }

/* Bottom-row fine print (copyright, terms / privacy strip) */
footer .copyright,
footer small,
footer .text-medium-gray,
footer .fs-12 { color: var(--on-dark-3) !important; }

/* Social-icon circles — wrap each link with a 34px ring */
footer .social-icon-style-01 ul li a,
footer .elements-social a,
footer a.fa-brands,
footer a > i.fa-brands {
    color: #ffffff !important;
}

/* ---------- 10. Leaderboard ------------------------------------- */
/* Public daily-exam leaderboards page (`/leaderboards`). Tabs +
 * podium + ranked table. Sits on top of the Crafto + Moss tokens. */

.leaderboard-tabs {
    list-style: none;
}
.leaderboard-tabs .nav-link {
    color: var(--text-2) !important;
    background: transparent;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.leaderboard-tabs .nav-link:hover {
    background: var(--surface-2) !important;
    color: var(--text-1) !important;
}
.leaderboard-tabs .nav-link.is-active {
    background: var(--brand-ink) !important;
    color: #ffffff !important;
}

/* Podium: gold-silver-bronze for ranks 1/2/3. The 1st-place tile
 * is the visual centre — lifted a notch and given the yellow
 * brand fill. Ranks 2 + 3 share the surface tokens. Card markup
 * is identical for all three; the colour + lift come from
 * `data-rank` on the .leaderboard-podium-slot wrapper. */
.leaderboard-podium-slot[data-rank="1"] .leaderboard-podium-card {
    background: linear-gradient(180deg, #fffce4 0%, #ffffff 100%);
    border-color: var(--brand-yellow) !important;
    transform: translateY(-12px);
    box-shadow: 0 10px 24px -16px rgba(212, 227, 0, 0.6);
}
.leaderboard-podium-slot[data-rank="2"] .leaderboard-podium-card,
.leaderboard-podium-slot[data-rank="3"] .leaderboard-podium-card {
    background: var(--surface-1) !important;
}

/* Reorder on desktop only — 2nd place sits left, 1st in centre,
 * 3rd on the right. On phones the cards stack 1 → 2 → 3 vertically. */
@media (min-width: 768px) {
    .leaderboard-podium-slot[data-rank="2"] { order: 1; }
    .leaderboard-podium-slot[data-rank="1"] { order: 2; }
    .leaderboard-podium-slot[data-rank="3"] { order: 3; }
}

.leaderboard-medal {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    font-weight: 700;
    font-size: 14px;
    color: #ffffff;
    background: var(--text-3);
}
.leaderboard-medal.is-rank-1 { background: #d4a017; }   /* gold */
.leaderboard-medal.is-rank-2 { background: #9ea3a8; }   /* silver */
.leaderboard-medal.is-rank-3 { background: #cd7f32; }   /* bronze */

.leaderboard-avatar-wrap {
    width: 80px;
    height: 80px;
    border-radius: 999px;
    background: var(--surface-3);
    padding: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.leaderboard-avatar {
    width: 100%;
    height: 100%;
    border-radius: 999px;
    object-fit: cover;
    background: var(--surface-2);
}
.leaderboard-avatar-fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-3);
}

.leaderboard-score {
    font-size: 28px;
    line-height: 1;
}

.leaderboard-avatar-sm {
    width: 40px;
    height: 40px;
}

/* Ranked table (rows 4+). Real <table> markup — semantic for crawlers
 * + screen readers — with the table rendered via fixed columns so the
 * row layout stays predictable. Header row gets the surface-2 fill so
 * it reads as a tabular header on a card. */
.leaderboard-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}
.leaderboard-table thead {
    background: var(--surface-2);
}
.leaderboard-table th {
    text-align: left;
    padding: 12px 16px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-3);
    border-bottom: 1px solid var(--border);
}
.leaderboard-table td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}
.leaderboard-table tbody tr:last-child td {
    border-bottom: none;
}
.leaderboard-table .leaderboard-cell-rank {
    width: 64px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.leaderboard-table .leaderboard-cell-name {
    /* min-width via table-layout: fixed + the rank/score widths */
}
.leaderboard-table .leaderboard-cell-score {
    width: 120px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Mobile: tighter padding + narrower fixed columns. */
@media (max-width: 575.98px) {
    .leaderboard-table th,
    .leaderboard-table td {
        padding: 10px 12px;
    }
    .leaderboard-table .leaderboard-cell-rank { width: 40px; }
    .leaderboard-table .leaderboard-cell-score { width: 80px; }
}

/* Bootstrap 5 ships `.visually-hidden` — but only when its full CSS
 * loads. Crafto's vendors.min.css does include Bootstrap's util set
 * already, so this is a safety net for the unlikely case where the
 * Crafto bundle is swapped out. Idempotent + harmless when Bootstrap
 * defines its own copy. */
.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ---------- 11. WhatsApp float button (kept from base) ---------- */
/* The WhatsApp anchor in base.html.twig sets its own bg via inline
 * style — leave it alone. */

/* ---------- 12. Font-display overrides --------------------------- */
/* Crafto's icon.min.css declares @font-face for FontAwesome + Feather
 * WITHOUT `font-display`, which defaults to `block` — text rendering
 * is suppressed for up to 3s while the icon font downloads. Lighthouse
 * flags this as a FCP regression (50 ms savings).
 *
 * Re-declare the same @font-face entries with `font-display: swap` so
 * the browser uses a fallback glyph until the icon font lands. The
 * `local()` / `format()` declarations stay identical to icon.min.css —
 * only the `font-display` token changes.
 *
 * Source: /themes/crafto/css/icon.min.css (do not edit — vendor file). */

/* Mirror the real font-family + file names from
 * /themes/crafto/css/icon.min.css verbatim — same FAMILY string, same
 * file path. Only `font-display` changes from `block` → `swap`. The
 * override only wins when our @font-face is parsed AFTER icon.min.css,
 * which it is (moss-theme.css is the last <link> in base.html.twig). */

/* Font Awesome 7 — Solid */
@font-face {
    font-family: "Font Awesome 7 Free";
    font-style: normal;
    font-weight: 900;
    font-display: swap;
    src: url("/themes/crafto/fonts/fa-solid-900.woff2") format("woff2");
}
/* Font Awesome 7 — Regular */
@font-face {
    font-family: "Font Awesome 7 Free";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/themes/crafto/fonts/fa-regular-400.woff2") format("woff2");
}
/* Font Awesome 7 — Brands */
@font-face {
    font-family: "Font Awesome 7 Brands";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/themes/crafto/fonts/fa-brands-400.woff2") format("woff2");
}
/* Feather */
@font-face {
    font-family: "feather";
    font-style: normal;
    font-weight: normal;
    font-display: swap;
    src: url("/themes/crafto/fonts/feather.woff") format("woff"),
         url("/themes/crafto/fonts/feather.ttf") format("truetype");
}

/* ─────────── rich-text body rendering ───────────────────────────
 * Shared styles for every public-page render of CKEditor 5 output —
 * the LandingPage block bodies, News article bodies, Course /
 * AppCourse details. The Twig filter `|oembed_iframe` (App\Twig
 * \RichTextExtension) converts legacy `<oembed>` elements to
 * `<iframe>` wrapped in `<div class="lp-video-embed">`; new saves
 * from CKEditor 5 with `mediaEmbed.previewsInData: true` ship the
 * iframe inside a `<figure class="media">` instead. Both shapes
 * land at a 16:9 responsive frame via the rules below.
 * ───────────────────────────────────────────────────────────── */

.lp-video-embed {
    position: relative;
    aspect-ratio: 16 / 9;
    width: 100%;
    max-width: 720px;
    margin: 1rem auto;
    border-radius: 8px;
    overflow: hidden;
    background: #000;
}
.lp-video-embed iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}
@supports not (aspect-ratio: 16 / 9) {
    .lp-video-embed { padding-top: 56.25%; }
}

/* CKEditor 5 native media-embed output (previewsInData: true) —
 * matches `<figure class="media"><oembed>` once converted, or the
 * raw figure with an iframe inside on new saves. */
.rich-text-body figure.media,
.lp-block-body figure.media {
    margin: 1rem auto;
    max-width: 100%;
    text-align: center;
}
.rich-text-body figure.media iframe,
.lp-block-body figure.media iframe {
    width: 100%;
    max-width: 720px;
    aspect-ratio: 16 / 9;
    border: 0;
    display: block;
    margin: 0 auto;
}

/* Inline body images inserted via CKEditor — keep them within the
 * column. Same rules already shipped in show.html.twig for landing
 * pages; the broader `.rich-text-body` scope covers News + Course
 * + AppCourse detail pages too. */
.rich-text-body img,
.rich-text-body figure.image img {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
    margin: 1rem auto;
    display: block;
}
.rich-text-body figure.image_resized {
    max-width: 100%;
    margin: 1rem auto;
}
.rich-text-body figure.image_resized img {
    width: 100% !important;
    height: auto !important;
}
.rich-text-body figure.image-style-side,
.rich-text-body figure.image-style-align-right {
    float: right;
    margin: 0.5rem 0 1rem 1rem;
    max-width: 45%;
}
.rich-text-body figure.image-style-align-left {
    float: left;
    margin: 0.5rem 1rem 1rem 0;
    max-width: 45%;
}
.rich-text-body figure.image-style-block-align-center,
.rich-text-body figure.image-style-align-center {
    margin: 1rem auto;
    max-width: 80%;
}
