/* ============================================================================
   Typography — Sitka (Windows) with Spectral web-fallback (loaded from Google
   Fonts in each page's <head> by the build), then Georgia as universal fallback.
   Spectral is the closest free, web-served match to Sitka's character.
   ============================================================================ */
:root {
    --font-display: 'Sitka Banner', 'Sitka Display', 'Spectral', Georgia, 'Times New Roman', serif;
    --font-body:    'Sitka Text', 'Spectral', Georgia, 'Times New Roman', serif;
}
html {
    /* Reserve the scrollbar gutter on every page so the fixed header is
       exactly the same width everywhere — otherwise navigating between a
       scrolling and a non-scrolling page shifts it sideways by ~15px. */
    scrollbar-gutter: stable;
}
html, body {
    font-family: var(--font-body);
    font-feature-settings: "kern" 1, "liga" 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
h1, h2, h3, h4, h5, h6, .font-display, .font-bold, .font-semibold, .font-extrabold, .font-black {
    font-family: var(--font-display);
}

@keyframes pulse-slow {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 0.5; }
}
.animate-pulse-slow {
    animation: pulse-slow 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
/* ============================================================================
   APEX brand colour tokens — authoritative from the Apex Learning and Development
   Design System (June 2026). These are the brand hex values; everything else
   downstream (per-category accents, semantic states) refers to these.
   ============================================================================ */
:root {
    /* Primary brand */
    --apex-navy:         #20409a;  /* Deep navy — wordmark, primary ink-accent */
    --apex-light-blue:   #00bdf2;  /* "Learning and Development" lockup, focus ring, links */

    /* Allocated category colours (from the brand spec) */
    --apex-green:        #0b9444;  /* First Aid & CPR */
    --apex-yellow:       #ffc20e;  /* Health, Safety & Wellbeing — buttons use #b88600 for contrast */
    --apex-yellow-deep:  #b88600;  /* Safety button-safe variant */
    --apex-orange:       #f1592a;  /* Sports / Fitness & Coaching */
    --apex-purple:       #7f3f98;  /* Business */
    --apex-medium-blue:  #0e76bc;  /* AI & Future Skills */

    /* Unallocated brand leaves (held for future course areas) */
    --apex-light-green:  #8dc63f;
    --apex-light-orange: #f7941d;
    --apex-red:          #ed1c24;
    --apex-magenta:      #ec008c;

    /* Category-token aliases (use these in components when possible) */
    --cat-first-aid: var(--apex-green);
    --cat-safety:    var(--apex-yellow);
    --cat-sports:    var(--apex-orange);
    --cat-business:  var(--apex-purple);
    --cat-ai:        var(--apex-medium-blue);

    /* Soft tints (~12% of category over paper, for future light-mode work) */
    --tint-green:  #e6f4ec;
    --tint-yellow: #fff6db;
    --tint-orange: #fde7e0;
    --tint-blue:   #e0f6fd;
    --tint-navy:   #e7ebf6;

    /* Semantic */
    --success: var(--apex-green);
    --warning: var(--apex-yellow);
    --danger:  var(--apex-red);
    --info:    var(--apex-medium-blue);
    --focus:   var(--apex-light-blue);

    /* Legacy aliases kept so older inline references still resolve */
    --apex-cyan: var(--apex-medium-blue);
    --apex-pink: var(--apex-orange);
    --apex-dark-green: var(--apex-green);
}
.gradient-apex {
    background: linear-gradient(135deg,
        var(--apex-orange) 0%,
        var(--apex-yellow) 35%,
        var(--apex-green) 65%,
        var(--apex-navy) 100%);
}
.leaf-accent {
    position: fixed;
    opacity: var(--op, 0.12);
    z-index: 0;
    pointer-events: none;
    width: 80px;
    height: 80px;
    filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.1));
}

/* ============================================================================
   LEAF PHYSICS SYSTEM
   theme.js wraps each leaf img in three layers at load:
     .leaf-pos    fixed positioning + per-leaf randomised CSS vars
     .leaf-breeze pointer/scroll parallax (driven by --mx/--my on <html>)
     .leaf-rise   vertical drift up the viewport
     .leaf-sway   side-to-side oscillation (own period -> Lissajous paths)
     img          3D tumble on a randomised axis
   All transform-only: GPU compositor, no layout/paint. The no-JS fallback
   keeps the original single-keyframe float (img.leaf-N rules below).
   ============================================================================ */
.leaf-pos {
    position: fixed;
    top: 100vh;
    z-index: 0;
    pointer-events: none;
}
.leaf-pos .leaf-accent {
    position: static;
    display: block;
    width: var(--size, 80px);
    height: auto;
    animation: leaf-tumble var(--tdur, 8s) linear infinite;
}
.leaf-breeze,
.leaf-rise,
.leaf-sway {
    display: block; /* spans: transforms don't apply to inline boxes */
}
.leaf-breeze {
    transform: translate(
        calc(var(--mx, 0) * var(--bf, 0px)),
        calc(var(--my, 0) * var(--bf, 0px) * 0.6));
    transition: transform 0.75s cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* When the JS wind physics drives the leaves (html.leaf-js), the breeze
   layer is positioned per-frame by inline transforms — the CSS transition
   would smear them a frame behind, so it goes. */
html.leaf-js .leaf-breeze,
html.leaf-js.theme-transition .leaf-breeze {
    transition: none !important;
}
.leaf-rise {
    animation: leaf-rise var(--dur, 24s) linear infinite;
    animation-delay: var(--del, 0s);
}
.leaf-sway {
    animation: leaf-sway var(--sdur, 4s) ease-in-out infinite alternate;
    animation-delay: var(--del, 0s);
    perspective: 400px;
}
@keyframes leaf-rise {
    from { transform: translateY(0); }
    to   { transform: translateY(calc(-100vh - 220px)); }
}
@keyframes leaf-sway {
    from { transform: translateX(calc(var(--amp, 30px) * -1)); }
    to   { transform: translateX(var(--amp, 30px)); }
}
@keyframes leaf-tumble {
    from { transform: rotate3d(var(--rx, 1), var(--ry, 1), 1, 0deg); }
    to   { transform: rotate3d(var(--rx, 1), var(--ry, 1), 1, 360deg); }
}

/* Occasional gust: one leaf catches the wind and spirals across the screen.
   Spawned by theme.js every ~40s, removed after the animation ends. */
.gust-leaf {
    position: fixed;
    left: -120px;
    width: 56px;
    height: auto;
    z-index: 0;
    pointer-events: none;
    animation: gust-fly 2.6s cubic-bezier(0.3, 0.4, 0.4, 1) forwards;
}
@keyframes gust-fly {
    0%   { transform: translate(0, 0) rotate3d(1, 1, 1, 0deg); opacity: 0; }
    10%  { opacity: 0.45; }
    100% { transform: translate(calc(100vw + 240px), -30vh) rotate3d(1, 1, 1, 720deg); opacity: 0; }
}

/* Positions when wrapped (class moves from the img to .leaf-pos) */
.leaf-pos.leaf-1 { left: 5%; }
.leaf-pos.leaf-2 { left: 15%; }
.leaf-pos.leaf-3 { left: 25%; }
.leaf-pos.leaf-4 { left: 65%; }
.leaf-pos.leaf-5 { left: 75%; }
.leaf-pos.leaf-6 { left: 35%; }
.leaf-pos.leaf-7 { left: 85%; }

/* No-JS fallback: the original drift, scoped to unwrapped imgs only */
@keyframes float-up {
    0% {
        transform: translateY(100vh) rotate(0deg) scale(0.8);
        opacity: 0;
    }
    10% {
        opacity: 0.15;
    }
    90% {
        opacity: 0.12;
    }
    100% {
        transform: translateY(-100vh) rotate(360deg) scale(0.8);
        opacity: 0;
    }
}
img.leaf-1 { animation: float-up 20s linear infinite; left: 5%; }
img.leaf-2 { animation: float-up 25s linear infinite 5s; left: 15%; }
img.leaf-3 { animation: float-up 30s linear infinite 10s; left: 25%; }
img.leaf-4 { animation: float-up 28s linear infinite 3s; left: 65%; }
img.leaf-5 { animation: float-up 22s linear infinite 7s; left: 75%; }
img.leaf-6 { animation: float-up 26s linear infinite 2s; left: 35%; }
img.leaf-7 { animation: float-up 24s linear infinite 12s; left: 85%; }

/* Accessibility: Focus Styles */
a:focus-visible,
button:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
    border-radius: 4px;
}

/* Accessibility: Screen Reader Only Text */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

/* Accessibility: Respect Motion Preferences */
@media (prefers-reduced-motion: reduce) {
    .leaf-accent,
    .leaf-pos,
    .gust-leaf {
        display: none;
    }
    * {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ===========================================================================
   THEME TOGGLE BUTTON
   =========================================================================== */
.theme-toggle {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.15);
    background: rgba(255, 255, 255, 0.05);
    color: white;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s, border-color 0.2s, transform 0.2s;
    font-size: 14px;
    margin-right: 4px;
}
.theme-toggle:hover {
    background: rgba(255, 255, 255, 0.1);
    transform: scale(1.05);
}
.theme-toggle:active {
    transform: scale(0.95);
}

/* ===========================================================================
   LIGHT MODE — overrides applied when <html> has .light-mode class
   The site is dark-first; these selectors invert hardcoded Tailwind utilities.
   =========================================================================== */
html.light-mode {
    color-scheme: light;
}

html.light-mode body,
html.light-mode .bg-\[\#0a0a0a\] {
    background-color: #fafafa !important;
}

html.light-mode .bg-\[\#0a0a0a\]\/80 {
    background-color: rgba(250, 250, 250, 0.85) !important;
}

html.light-mode .bg-\[\#0a0a0a\]\/95 {
    background-color: rgba(250, 250, 250, 0.95) !important;
}

/* Card / surface backgrounds */
html.light-mode .bg-black\/40 {
    background-color: rgba(255, 255, 255, 0.75) !important;
}
html.light-mode .bg-black\/30 {
    background-color: rgba(255, 255, 255, 0.6) !important;
}
html.light-mode .bg-black\/60 {
    background-color: rgba(255, 255, 255, 0.9) !important;
}

/* Glass tints — invert white-on-dark to black-on-light */
html.light-mode .bg-white\/5 {
    background-color: rgba(15, 23, 42, 0.04) !important;
}
html.light-mode .bg-white\/8 {
    background-color: rgba(15, 23, 42, 0.05) !important;
}
html.light-mode .bg-white\/10 {
    background-color: rgba(15, 23, 42, 0.07) !important;
}

/* Text colours */
html.light-mode .text-white {
    color: #0f172a !important;
}
html.light-mode .text-white\/40 {
    color: rgba(15, 23, 42, 0.5) !important;
}
html.light-mode .text-white\/50 {
    color: rgba(15, 23, 42, 0.55) !important;
}
html.light-mode .text-white\/60 {
    color: rgba(15, 23, 42, 0.65) !important;
}
html.light-mode .text-white\/70 {
    color: rgba(15, 23, 42, 0.75) !important;
}
html.light-mode .text-white\/80 {
    color: rgba(15, 23, 42, 0.85) !important;
}
html.light-mode .text-white\/90 {
    color: rgba(15, 23, 42, 0.9) !important;
}

/* Hover text-white state */
html.light-mode .hover\:text-white:hover {
    color: #0f172a !important;
}
html.light-mode .focus-visible\:text-white:focus-visible {
    color: #0f172a !important;
}

/* Low-opacity white text — used for footer separator pipes "|" and similar
   decorative dividers. Without an override these render as 30%-white on a
   light surface, which is invisible. Map to low-opacity dark slate so the
   divider stays as a thin visual rule. */
html.light-mode .text-white\/10 {
    color: rgba(15, 23, 42, 0.15) !important;
}
html.light-mode .text-white\/15 {
    color: rgba(15, 23, 42, 0.2) !important;
}
html.light-mode .text-white\/20 {
    color: rgba(15, 23, 42, 0.25) !important;
}
html.light-mode .text-white\/25 {
    color: rgba(15, 23, 42, 0.3) !important;
}
html.light-mode .text-white\/30 {
    color: rgba(15, 23, 42, 0.35) !important;
}

/* Borders */
html.light-mode .border-white\/10 {
    border-color: rgba(15, 23, 42, 0.1) !important;
}
html.light-mode .border-white\/20 {
    border-color: rgba(15, 23, 42, 0.15) !important;
}

/* Hover backgrounds */
html.light-mode .hover\:bg-white\/5:hover {
    background-color: rgba(15, 23, 42, 0.04) !important;
}
html.light-mode .hover\:bg-white\/10:hover {
    background-color: rgba(15, 23, 42, 0.07) !important;
}
html.light-mode .hover\:bg-white\/20:hover {
    background-color: rgba(15, 23, 42, 0.1) !important;
}

/* Hover border states */
html.light-mode .hover\:border-white\/20:hover,
html.light-mode .hover\:border-white\/30:hover,
html.light-mode .hover\:border-white\/40:hover {
    border-color: rgba(15, 23, 42, 0.2) !important;
}

/* Aurora / glow background blobs — much subtler on light */
html.light-mode .bg-emerald-900\/10,
html.light-mode .bg-emerald-900\/20,
html.light-mode .bg-emerald-900\/30 {
    background-color: rgba(16, 185, 129, 0.06) !important;
}
html.light-mode .bg-blue-900\/10,
html.light-mode .bg-blue-900\/15,
html.light-mode .bg-blue-900\/20 {
    background-color: rgba(59, 130, 246, 0.06) !important;
}
html.light-mode .bg-pink-900\/15,
html.light-mode .bg-pink-900\/20 {
    background-color: rgba(236, 72, 153, 0.06) !important;
}
html.light-mode .bg-purple-900\/10,
html.light-mode .bg-purple-900\/15,
html.light-mode .bg-purple-900\/20 {
    background-color: rgba(168, 85, 247, 0.06) !important;
}
html.light-mode .bg-orange-900\/15,
html.light-mode .bg-orange-900\/20 {
    background-color: rgba(249, 115, 22, 0.06) !important;
}
html.light-mode .bg-cyan-900\/20 {
    background-color: rgba(6, 182, 212, 0.06) !important;
}
html.light-mode .bg-yellow-900\/15,
html.light-mode .bg-yellow-900\/20 {
    background-color: rgba(234, 179, 8, 0.06) !important;
}

/* Grid pattern overlay */
html.light-mode .grid-pattern {
    background-image:
        linear-gradient(rgba(15, 23, 42, 0.04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(15, 23, 42, 0.04) 1px, transparent 1px) !important;
}

/* Coloured card tints — slightly bumped so they read on light background */
html.light-mode .bg-pink-500\/10,
html.light-mode .bg-pink-500\/15 {
    background-color: rgba(236, 72, 153, 0.1) !important;
}
html.light-mode .bg-cyan-500\/10,
html.light-mode .bg-cyan-500\/15 {
    background-color: rgba(6, 182, 212, 0.1) !important;
}
html.light-mode .bg-emerald-500\/10,
html.light-mode .bg-emerald-500\/15 {
    background-color: rgba(16, 185, 129, 0.1) !important;
}
html.light-mode .bg-purple-500\/10,
html.light-mode .bg-purple-500\/15 {
    background-color: rgba(168, 85, 247, 0.1) !important;
}
html.light-mode .bg-orange-500\/10,
html.light-mode .bg-orange-500\/15 {
    background-color: rgba(249, 115, 22, 0.1) !important;
}
html.light-mode .bg-yellow-500\/10,
html.light-mode .bg-yellow-500\/15 {
    background-color: rgba(234, 179, 8, 0.1) !important;
}
html.light-mode .bg-blue-500\/10,
html.light-mode .bg-blue-500\/15 {
    background-color: rgba(59, 130, 246, 0.1) !important;
}
html.light-mode .bg-red-500\/10,
html.light-mode .bg-red-500\/15 {
    background-color: rgba(239, 68, 68, 0.1) !important;
}
html.light-mode .bg-green-500\/10,
html.light-mode .bg-green-500\/15 {
    background-color: rgba(34, 197, 94, 0.1) !important;
}
html.light-mode .bg-indigo-500\/10,
html.light-mode .bg-indigo-500\/15 {
    background-color: rgba(99, 102, 241, 0.1) !important;
}

/* Coloured card text — darken so it reads on light cards */
html.light-mode .text-pink-100,
html.light-mode .text-pink-200,
html.light-mode .text-pink-300 {
    color: #be185d !important;
}
html.light-mode .text-cyan-100,
html.light-mode .text-cyan-200,
html.light-mode .text-cyan-300 {
    color: #0e7490 !important;
}
html.light-mode .text-emerald-100,
html.light-mode .text-emerald-200,
html.light-mode .text-emerald-300 {
    color: #047857 !important;
}
html.light-mode .text-purple-100,
html.light-mode .text-purple-200,
html.light-mode .text-purple-300 {
    color: #7e22ce !important;
}
html.light-mode .text-orange-100,
html.light-mode .text-orange-200,
html.light-mode .text-orange-300 {
    color: #c2410c !important;
}
html.light-mode .text-yellow-100,
html.light-mode .text-yellow-200,
html.light-mode .text-yellow-300 {
    color: #a16207 !important;
}
html.light-mode .text-blue-100,
html.light-mode .text-blue-200,
html.light-mode .text-blue-300 {
    color: #1d4ed8 !important;
}
html.light-mode .text-red-100,
html.light-mode .text-red-200,
html.light-mode .text-red-300 {
    color: #b91c1c !important;
}
/* Tailwind's `green` is a separate palette from `emerald`. The First Aid &
   CPR category uses green-* (per the brand category remap), so it needs the
   same dark-variant treatment as the other category colours. */
html.light-mode .text-green-100,
html.light-mode .text-green-200,
html.light-mode .text-green-300 {
    color: #15803d !important;
}
/* `indigo` is used in one news article callout (the Latrobe Health source
   citation). Cover for completeness. */
html.light-mode .text-indigo-100,
html.light-mode .text-indigo-200,
html.light-mode .text-indigo-300 {
    color: #3730a3 !important;
}

/* Accent text shades 400 and 500 — used for small labels and codes on coloured cards.
   These need darker variants in light mode for sufficient contrast against
   pale-tinted card backgrounds. Using the 700 shade matches the 100-300 overrides. */
html.light-mode .text-pink-400,
html.light-mode .text-pink-500 { color: #be185d !important; }
html.light-mode .text-cyan-400,
html.light-mode .text-cyan-500 { color: #0e7490 !important; }
html.light-mode .text-emerald-400,
html.light-mode .text-emerald-500 { color: #047857 !important; }
html.light-mode .text-purple-400,
html.light-mode .text-purple-500 { color: #7e22ce !important; }
html.light-mode .text-orange-400,
html.light-mode .text-orange-500 { color: #c2410c !important; }
html.light-mode .text-yellow-400,
html.light-mode .text-yellow-500 { color: #a16207 !important; }
html.light-mode .text-blue-400,
html.light-mode .text-blue-500 { color: #1d4ed8 !important; }
html.light-mode .text-red-400,
html.light-mode .text-red-500 { color: #b91c1c !important; }
html.light-mode .text-green-400,
html.light-mode .text-green-500 { color: #15803d !important; }
html.light-mode .text-indigo-400,
html.light-mode .text-indigo-500 { color: #3730a3 !important; }

/* Hover variants too — same idea */
html.light-mode .hover\:text-pink-300:hover,
html.light-mode .hover\:text-pink-400:hover { color: #be185d !important; }
html.light-mode .hover\:text-cyan-300:hover,
html.light-mode .hover\:text-cyan-400:hover { color: #0e7490 !important; }
html.light-mode .hover\:text-emerald-300:hover,
html.light-mode .hover\:text-emerald-400:hover { color: #047857 !important; }
html.light-mode .hover\:text-purple-300:hover,
html.light-mode .hover\:text-purple-400:hover { color: #7e22ce !important; }
html.light-mode .hover\:text-orange-300:hover,
html.light-mode .hover\:text-orange-400:hover { color: #c2410c !important; }
html.light-mode .hover\:text-yellow-300:hover,
html.light-mode .hover\:text-yellow-400:hover { color: #a16207 !important; }
html.light-mode .hover\:text-blue-300:hover,
html.light-mode .hover\:text-blue-400:hover { color: #1d4ed8 !important; }
html.light-mode .hover\:text-red-300:hover,
html.light-mode .hover\:text-red-400:hover { color: #b91c1c !important; }
html.light-mode .hover\:text-green-300:hover,
html.light-mode .hover\:text-green-400:hover { color: #15803d !important; }
html.light-mode .hover\:text-indigo-300:hover,
html.light-mode .hover\:text-indigo-400:hover { color: #3730a3 !important; }

/* ============================================================================
   IMAGE OVERLAY EXCEPTION
   Text that sits inside an absolute-positioned overlay on top of an image
   should remain white in BOTH themes — the dark gradient overlay keeps the
   area dark regardless of theme, so inverting the text breaks contrast.
   Uses :has() (broad browser support since 2024).
   ============================================================================ */
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-white,
html.light-mode .relative.overflow-hidden:has(> img) .absolute p.text-white,
html.light-mode .relative.overflow-hidden:has(> img) .absolute h1,
html.light-mode .relative.overflow-hidden:has(> img) .absolute h2,
html.light-mode .relative.overflow-hidden:has(> img) .absolute h3 {
    color: white !important;
}
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-white\/60 { color: rgba(255, 255, 255, 0.6) !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-white\/70 { color: rgba(255, 255, 255, 0.7) !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-white\/80 { color: rgba(255, 255, 255, 0.8) !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-white\/90 { color: rgba(255, 255, 255, 0.9) !important; }

/* Bright accent colours stay vivid on dark image overlays */
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-pink-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-pink-400 { color: #f472b6 !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-cyan-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-cyan-400 { color: #22d3ee !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-emerald-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-emerald-400 { color: #34d399 !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-purple-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-purple-400 { color: #c084fc !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-orange-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-orange-400 { color: #fb923c !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-yellow-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-yellow-400 { color: #facc15 !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-blue-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-blue-400 { color: #60a5fa !important; }
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-red-300,
html.light-mode .relative.overflow-hidden:has(> img) .absolute .text-red-400 { color: #f87171 !important; }

/* News cards have a separate structure — .overflow-hidden + a flex column with text.
   The same containing :has() rule applies. */
html.light-mode article:has(> a > div > .overflow-hidden img) .text-white {
    /* Leave news card body text in default (now-dark) state — those are NOT on the image */
}

/* But the featured news article banner DOES have absolute text over image — already covered */

/* Background gradient overlays on image cards — keep them dark in light mode too,
   otherwise the image text becomes unreadable. */
html.light-mode .relative.overflow-hidden:has(> img) .bg-gradient-to-r.from-black\/80,
html.light-mode .relative.overflow-hidden:has(> img) .bg-gradient-to-t.from-black,
html.light-mode .relative.overflow-hidden:has(> img) .bg-gradient-to-t.from-black\/80 {
    /* These already use --tw-gradient-from which my generic overrides don't catch.
       The dark gradient persists naturally. */
}

/* Group/hover cards on the home page Training tiles use anchor not div */
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-white {
    color: white !important;
}
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-white\/70 { color: rgba(255, 255, 255, 0.7) !important; }
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-pink-300,
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-cyan-300,
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-orange-300,
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-emerald-300,
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-purple-300,
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-blue-300 {
    /* Keep these as the original Tailwind 300 — already bright */
    color: revert !important;
}
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-pink-300 { color: #f9a8d4 !important; }
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-cyan-300 { color: #67e8f9 !important; }
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-orange-300 { color: #fdba74 !important; }
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-emerald-300 { color: #6ee7b7 !important; }
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-purple-300 { color: #d8b4fe !important; }
html.light-mode a.relative.overflow-hidden:has(> img) .absolute .text-blue-300 { color: #93c5fd !important; }

/* Tinted text on coloured cards (e.g. pink-200/80) */
html.light-mode .text-pink-200\/80 { color: rgba(190, 24, 93, 0.85) !important; }
html.light-mode .text-cyan-200\/80 { color: rgba(14, 116, 144, 0.85) !important; }
html.light-mode .text-emerald-200\/80 { color: rgba(4, 120, 87, 0.85) !important; }
html.light-mode .text-purple-200\/80 { color: rgba(126, 34, 206, 0.85) !important; }
html.light-mode .text-orange-200\/80 { color: rgba(194, 65, 12, 0.85) !important; }
html.light-mode .text-yellow-200\/80 { color: rgba(161, 98, 7, 0.85) !important; }
html.light-mode .text-pink-200\/70 { color: rgba(190, 24, 93, 0.75) !important; }
html.light-mode .text-cyan-200\/70 { color: rgba(14, 116, 144, 0.75) !important; }
html.light-mode .text-emerald-200\/70 { color: rgba(4, 120, 87, 0.75) !important; }
html.light-mode .text-purple-200\/70 { color: rgba(126, 34, 206, 0.75) !important; }
html.light-mode .text-orange-200\/70 { color: rgba(194, 65, 12, 0.75) !important; }
html.light-mode .text-yellow-200\/70 { color: rgba(161, 98, 7, 0.75) !important; }
html.light-mode .text-pink-200\/60 { color: rgba(190, 24, 93, 0.65) !important; }
html.light-mode .text-cyan-200\/60 { color: rgba(14, 116, 144, 0.65) !important; }
html.light-mode .text-emerald-200\/60 { color: rgba(4, 120, 87, 0.65) !important; }
html.light-mode .text-purple-200\/60 { color: rgba(126, 34, 206, 0.65) !important; }
html.light-mode .text-orange-200\/60 { color: rgba(194, 65, 12, 0.65) !important; }
html.light-mode .text-yellow-200\/60 { color: rgba(161, 98, 7, 0.65) !important; }
/* green-* opacity variants (First Aid card body and list items) */
html.light-mode .text-green-200\/80 { color: rgba(21, 128, 61, 0.85) !important; }
html.light-mode .text-green-200\/70 { color: rgba(21, 128, 61, 0.75) !important; }
html.light-mode .text-green-200\/60 { color: rgba(21, 128, 61, 0.7) !important; }
/* indigo-* opacity variants (Latrobe article callout) */
html.light-mode .text-indigo-200\/80 { color: rgba(55, 48, 163, 0.85) !important; }
html.light-mode .text-indigo-200\/70 { color: rgba(55, 48, 163, 0.75) !important; }
html.light-mode .text-indigo-200\/60 { color: rgba(55, 48, 163, 0.7) !important; }
/* blue-* opacity variants (AI & Future Skills panes, courses AI card).
   Blue was the one palette missed when the 200-shade variants were added. */
html.light-mode .text-blue-200\/80 { color: rgba(29, 78, 216, 0.85) !important; }
html.light-mode .text-blue-200\/70 { color: rgba(29, 78, 216, 0.75) !important; }
html.light-mode .text-blue-200\/60 { color: rgba(29, 78, 216, 0.7) !important; }

/* Form inputs */
html.light-mode input[type="text"],
html.light-mode input[type="email"],
html.light-mode input[type="tel"],
html.light-mode input[type="url"],
html.light-mode select,
html.light-mode textarea {
    background-color: rgba(15, 23, 42, 0.04) !important;
    color: #0f172a !important;
    border-color: rgba(15, 23, 42, 0.15) !important;
}
html.light-mode input::placeholder,
html.light-mode textarea::placeholder {
    color: rgba(15, 23, 42, 0.4) !important;
}
html.light-mode select option {
    background-color: white !important;
    color: #0f172a !important;
}

/* Leaf accents — slightly stronger on light, scaled per-leaf by depth */
html.light-mode .leaf-accent {
    opacity: calc(var(--op, 0.12) * 1.5);
    mix-blend-mode: multiply;
    filter: drop-shadow(0 0 10px rgba(15, 23, 42, 0.05));
}
html.light-mode .gust-leaf {
    mix-blend-mode: multiply;
}

/* Active nav item indicator */
html.light-mode nav a[aria-current="page"].bg-white\/10 {
    background-color: rgba(15, 23, 42, 0.08) !important;
    color: #0f172a !important;
}
html.light-mode nav a[aria-current="page"].bg-white\/5 {
    background-color: rgba(15, 23, 42, 0.05) !important;
    color: #0f172a !important;
}

/* Theme toggle button in light mode */
html.light-mode .theme-toggle {
    border-color: rgba(15, 23, 42, 0.15);
    background: rgba(15, 23, 42, 0.04);
    color: #0f172a;
}
html.light-mode .theme-toggle:hover {
    background: rgba(15, 23, 42, 0.08);
}

/* Focus outline — dark in light mode */
html.light-mode a:focus-visible,
html.light-mode button:focus-visible {
    outline-color: #0f172a;
}

/* Gradient-clipped text — invert so it darkens to light bg */
/* The two-stop hero gradient used across most pages */
html.light-mode .bg-gradient-to-b.from-white.to-white\/50,
html.light-mode .bg-gradient-to-b.from-white.to-white\/60 {
    background-image: linear-gradient(to bottom, #0f172a, rgba(15, 23, 42, 0.5)) !important;
}
/* The three-stop variant used on the 404 page's giant "404" number */
html.light-mode .bg-gradient-to-b.from-white.via-white\/80.to-white\/30 {
    background-image: linear-gradient(to bottom, #0f172a, rgba(15, 23, 42, 0.8) 50%, rgba(15, 23, 42, 0.3)) !important;
}

/* Soft shadows */
html.light-mode .shadow-2xl {
    box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.08) !important;
}
html.light-mode .shadow-lg {
    box-shadow: 0 10px 15px -3px rgba(15, 23, 42, 0.06) !important;
}

/* ============================================================================
   SOLID COLOURED BUTTONS WITH text-white
   The global text-white override flips text to dark slate, which is correct
   for plain copy on the now-light background. But buttons with a solid bright
   coloured background (bg-purple-500 etc.) were designed for white text, and
   dark-on-bright-purple has worse contrast (and reads as a glitch). Preserve
   the white text on those specific button surfaces.

   Specificity: two class selectors beats the single .text-white rule above.
   ============================================================================ */
html.light-mode .bg-purple-500.text-white,
html.light-mode .bg-blue-500.text-white,
html.light-mode .bg-pink-500.text-white,
html.light-mode .bg-red-500.text-white,
html.light-mode .bg-cyan-500.text-white,
html.light-mode .bg-medium-blue.text-white {
    color: white !important;
}
/* Hover state mirrors */
html.light-mode .hover\:bg-purple-400:hover.text-white,
html.light-mode .hover\:bg-blue-400:hover.text-white,
html.light-mode .hover\:bg-pink-400:hover.text-white,
html.light-mode .hover\:bg-red-400:hover.text-white,
html.light-mode .hover\:bg-cyan-400:hover.text-white {
    color: white !important;
}

/* ============================================================================
   COLOURED BACKGROUND TINTS — opacity variants /20, /25, /30
   The /10 and /15 variants already have light-mode overrides; the higher
   opacities work natively (a tinted-yellow overlay shows on white) but read
   washed-out. Bump the alpha so the card silhouette is clear on light.
   ============================================================================ */
html.light-mode .bg-yellow-500\/20 { background-color: rgba(234, 179, 8, 0.18) !important; }
html.light-mode .bg-yellow-500\/25 { background-color: rgba(234, 179, 8, 0.22) !important; }
html.light-mode .bg-yellow-500\/30 { background-color: rgba(234, 179, 8, 0.28) !important; }

html.light-mode .bg-orange-500\/20 { background-color: rgba(249, 115, 22, 0.15) !important; }
html.light-mode .bg-orange-500\/25 { background-color: rgba(249, 115, 22, 0.18) !important; }
html.light-mode .bg-orange-500\/30 { background-color: rgba(249, 115, 22, 0.22) !important; }

html.light-mode .bg-pink-500\/20 { background-color: rgba(236, 72, 153, 0.15) !important; }
html.light-mode .bg-pink-500\/25 { background-color: rgba(236, 72, 153, 0.18) !important; }
html.light-mode .bg-pink-500\/30 { background-color: rgba(236, 72, 153, 0.22) !important; }

html.light-mode .bg-cyan-500\/20 { background-color: rgba(6, 182, 212, 0.15) !important; }
html.light-mode .bg-cyan-500\/25 { background-color: rgba(6, 182, 212, 0.18) !important; }
html.light-mode .bg-cyan-500\/30 { background-color: rgba(6, 182, 212, 0.22) !important; }

html.light-mode .bg-emerald-500\/20 { background-color: rgba(16, 185, 129, 0.15) !important; }
html.light-mode .bg-emerald-500\/25 { background-color: rgba(16, 185, 129, 0.18) !important; }
html.light-mode .bg-emerald-500\/30 { background-color: rgba(16, 185, 129, 0.22) !important; }

html.light-mode .bg-purple-500\/20 { background-color: rgba(168, 85, 247, 0.15) !important; }
html.light-mode .bg-purple-500\/25 { background-color: rgba(168, 85, 247, 0.18) !important; }
html.light-mode .bg-purple-500\/30 { background-color: rgba(168, 85, 247, 0.22) !important; }

html.light-mode .bg-blue-500\/20 { background-color: rgba(59, 130, 246, 0.15) !important; }
html.light-mode .bg-blue-500\/25 { background-color: rgba(59, 130, 246, 0.18) !important; }
html.light-mode .bg-blue-500\/30 { background-color: rgba(59, 130, 246, 0.22) !important; }

html.light-mode .bg-green-500\/20 { background-color: rgba(34, 197, 94, 0.15) !important; }
html.light-mode .bg-green-500\/25 { background-color: rgba(34, 197, 94, 0.18) !important; }
html.light-mode .bg-green-500\/30 { background-color: rgba(34, 197, 94, 0.22) !important; }

html.light-mode .bg-red-500\/20 { background-color: rgba(239, 68, 68, 0.15) !important; }
html.light-mode .bg-red-500\/25 { background-color: rgba(239, 68, 68, 0.18) !important; }
html.light-mode .bg-red-500\/30 { background-color: rgba(239, 68, 68, 0.22) !important; }

/* Hover variants */
html.light-mode .hover\:bg-yellow-500\/20:hover,
html.light-mode .group:hover .group-hover\:bg-yellow-500\/20 { background-color: rgba(234, 179, 8, 0.18) !important; }
html.light-mode .hover\:bg-yellow-500\/25:hover { background-color: rgba(234, 179, 8, 0.22) !important; }
html.light-mode .hover\:bg-orange-500\/20:hover { background-color: rgba(249, 115, 22, 0.15) !important; }
html.light-mode .hover\:bg-pink-500\/20:hover { background-color: rgba(236, 72, 153, 0.15) !important; }
html.light-mode .hover\:bg-cyan-500\/20:hover { background-color: rgba(6, 182, 212, 0.15) !important; }
html.light-mode .hover\:bg-emerald-500\/20:hover { background-color: rgba(16, 185, 129, 0.15) !important; }
html.light-mode .hover\:bg-emerald-500\/30:hover { background-color: rgba(16, 185, 129, 0.22) !important; }
html.light-mode .hover\:bg-purple-500\/20:hover { background-color: rgba(168, 85, 247, 0.15) !important; }
html.light-mode .hover\:bg-blue-500\/20:hover { background-color: rgba(59, 130, 246, 0.15) !important; }

/* ============================================================================
   NEWS ARTICLE .prose-custom OVERRIDES
   Each news article has an inline <style> block defining .prose-custom rules
   with hard-coded `color: white` on strong and h2. Those bypass Tailwind class
   overrides and would render white-on-light in light mode. Patch them globally
   here so we don't have to touch eight article files.
   ============================================================================ */
html.light-mode .prose-custom strong,
html.light-mode .prose-custom h2,
html.light-mode .prose-custom h3,
html.light-mode .prose-custom h4 {
    color: #0f172a !important;
}

/* Anchors inside articles stay accent-coloured (already handled via the
   text-emerald-400 override above, but reinforce here in case the article
   uses an inline color). */
html.light-mode .prose-custom a {
    color: #047857;
}
html.light-mode .prose-custom a:hover {
    color: #065f46;
}

/* Callouts in standards-for-rtos / latrobe articles use coloured boxes with
   .text-cyan-300 / .text-indigo-200 etc — already covered by colour overrides.
   No further work needed for callout text. */

/* Smooth theme transition (after initial load) */
html.theme-transition,
html.theme-transition body,
html.theme-transition * {
    transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease !important;
}
/* The universal transition above is a shorthand and would clobber the breeze
   layer's slow transform easing — restore it with equal importance. */
html.theme-transition .leaf-breeze {
    transition: transform 0.75s cubic-bezier(0.2, 0.8, 0.2, 1) !important;
}

/* ============================================================================
   CROSS-DOCUMENT VIEW TRANSITIONS
   The site is multi-page static HTML, so every nav click is a full document
   reload — the aurora blobs, grid pattern, and leaf accents all visibly
   restart, which feels like the background is "reloading" each time.
   Opting in to cross-document view transitions makes the browser smoothly
   cross-fade between the two documents instead of flashing. Supported in
   Chrome 126+, Safari 18+, Firefox 132+ (all GA by mid-2025). Browsers that
   don't support it fall back to normal navigation — no breakage.
   ============================================================================ */
@view-transition {
    navigation: auto;
}

/* Respect motion preferences — skip the transition entirely for users who
   have requested reduced motion. */
@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

/* ============================================================================
   NAVIGATION CHOREOGRAPHY
   A plain crossfade still reads as "page reload". Coherence comes from
   persistence: the header is NAMED, so the browser snapshots it as its own
   group and it simply stays put across navigations while the rest of the
   page transitions underneath. The incoming content rises 14px as it fades
   in; the outgoing page just fades. Combined with the prerendered pages
   from the speculation rules, navigation reads as one continuous place.
   ============================================================================ */
header {
    view-transition-name: site-header;
}
::view-transition-group(site-header) {
    animation-duration: 0s;
}
/* The wind. theme.js intercepts internal link clicks, adds .page-exit, and
   navigates ~240ms later: the leaves blow off the left edge and the content
   leans into the gust. The view transition then slides the new page in from
   the right, travelling the same direction the leaves went. */
@keyframes leaf-blow-out {
    0%   { transform: translate(0, 0) rotate(0deg); opacity: 1; }
    70%  { opacity: 1; }
    100% { transform: translate(-135vw, -12vh) rotate(-320deg); opacity: 0; }
}
html.page-exit .leaf-pos {
    animation: leaf-blow-out 0.5s cubic-bezier(0.45, 0, 0.7, 0.4) forwards;
    animation-delay: var(--gd, 0s);
}
/* The gust is the moment the leaves star in — brighten them for it so
   every leaf is clearly seen tumbling off, then they fade as they exit */
html.page-exit .leaf-pos .leaf-accent {
    opacity: min(0.55, calc(var(--op, 0.12) * 3.5));
}
@keyframes main-blow-out {
    to { transform: translateX(-7vw); opacity: 0; }
}
html.page-exit main {
    /* The wind reaches the leaves first; the page gets caught a beat later */
    animation: main-blow-out 0.26s ease-in 0.2s forwards;
}
html.page-exit .gust-leaf {
    display: none;
}

@keyframes vt-fade-out {
    to { opacity: 0; }
}
@keyframes vt-blow-in {
    from { opacity: 0; transform: translateX(9vw); }
}
::view-transition-old(root) {
    animation: vt-fade-out 120ms ease both;
}
::view-transition-new(root) {
    animation: vt-blow-in 340ms cubic-bezier(0.16, 0.84, 0.28, 1) both;
}
