/* ============================================================
   Semos Education — Design System (theme layer)
   Loaded AFTER main.css so these tokens/components take
   precedence. Clean corporate ed-tech: bright white surfaces,
   a bold Semos blue primary, a trustworthy blue secondary,
   near-black navy ink, generous space, soft shadows.
   ============================================================ */

/* ─────────────────────────────────────────────
   1. Design Tokens
   ───────────────────────────────────────────── */
:root {
    /* Brand — Semos Education blue (primary / CTA).
       The logo blue is #0F4EFF (see --cf-brand-blue); the CTA tone is a slightly
       deeper blue so white button text meets WCAG AA contrast. */
    --cf-brand-blue:     #0F4EFF;   /* exact logo blue — for logo-matching accents */
    --cf-coral:          #0F4EFF;   /* legacy alias → now brand blue */
    --cf-primary:        #1150E6;   /* Semos blue (AA-safe with white text) */
    --cf-primary-dark:   #0B3FC4;   /* hover / pressed */
    --cf-primary-light:  #E4ECFF;   /* tint for soft fills & active pills */

    /* Brand — blue (secondary accent: links, info highlights) */
    --cf-secondary:      #0A66C2;
    --cf-secondary-dark: #084F98;
    --cf-secondary-light:#E7F1FB;
    --cf-violet:         var(--cf-secondary);  /* legacy alias → now blue */

    /* Brand fill: a Semos blue gradient for buttons & key accents */
    --cf-accent-grad:    linear-gradient(135deg, #1E5BFF 0%, #0B3FC4 100%);

    /* Retarget Bootstrap's own primary so every .btn-primary, .bg-primary,
       .text-primary, form-check/switch, pagination, etc. reads Semos blue.
       Links follow the blue secondary accent. */
    --bs-primary:              #1150E6;
    --bs-primary-rgb:          17, 80, 230;
    --bs-primary-text-emphasis:#0A2E8F;
    --bs-primary-bg-subtle:    #E4ECFF;
    --bs-primary-border-subtle:#C3D4FF;
    --bs-link-color:           #0A66C2;
    --bs-link-color-rgb:       10, 102, 194;
    --bs-link-hover-color:     #084F98;
    --bs-link-hover-color-rgb: 8, 79, 152;

    /* Semantic (verdicts: keep meaning, harmonized tone) */
    --cf-success:        #12A150;   /* Accepted */
    --cf-success-light:  #e8f7ee;
    --cf-warning:        #E08600;   /* TLE */
    --cf-warning-light:  #fff5e6;
    --cf-danger:         #DC2F2F;   /* Wrong Answer / errors — a clear red, distinct from the blue primary */
    --cf-danger-light:   #fdeaed;
    --cf-info:           #0A66C2;

    /* Surfaces & text */
    --cf-bg:             #F6F7F9;
    --cf-surface:        #ffffff;
    --cf-surface-2:      #F4F6F8;
    --cf-text:           #14161D;   /* near-black navy ink */
    --cf-text-muted:     #5A6472;
    --cf-text-faint:     #7c869c;   /* darkened for projector/low-contrast legibility */
    --cf-border:         #E6E9EE;
    --cf-border-strong:  #D3D8E0;

    /* Dark (hero / footer surfaces, and the dark navbar in dark theme) */
    --cf-dark:           #0F1420;
    --cf-dark-2:         #171D2B;
    --cf-dark-border:    rgba(255,255,255,.09);
    --cf-on-dark:        #E8EBF2;
    --cf-on-dark-muted:  #9AA3B7;

    /* Navbar — theme-aware. Light theme = clean white bar; dark theme
       overrides these to the dark glass (see §16). */
    --cf-nav-bg:         rgba(255,255,255,.82);
    --cf-nav-bg-scroll:  rgba(255,255,255,.96);
    --cf-nav-border:     #E6E9EE;
    --cf-nav-shadow:     0 6px 24px -14px rgba(15,22,41,.28);
    --cf-nav-text:       #475467;
    --cf-nav-text-hover: #14161D;
    --cf-nav-hover-bg:   rgba(20,22,29,.055);
    --cf-nav-brand:      #14161D;

    /* Footer — theme-aware. Light theme = clean light band that matches the
       page; dark theme overrides to the deep navy footer (see §16). */
    --cf-footer-bg:          #FFFFFF;
    --cf-footer-border:      #E6E9EE;
    --cf-footer-text:        #5A6472;
    --cf-footer-head:        #14161D;
    --cf-footer-link:        #5A6472;
    --cf-footer-link-hover:  #1150E6;
    --cf-footer-chip-bg:     #F4F6F8;
    --cf-footer-chip-border: #E6E9EE;
    --cf-footer-chip-text:   #5A6472;

    /* Radius */
    --cf-radius-xs:      8px;
    --cf-radius-sm:      10px;
    --cf-radius:         14px;
    --cf-radius-lg:      20px;
    --cf-radius-xl:      28px;

    /* Shadows */
    --cf-shadow-xs:      0 1px 2px rgba(15,23,42,.06);
    --cf-shadow:         0 1px 3px rgba(15,23,42,.07), 0 1px 2px rgba(15,23,42,.04);
    --cf-shadow-md:      0 8px 24px -6px rgba(15,23,42,.12), 0 2px 6px -2px rgba(15,23,42,.06);
    --cf-shadow-lg:      0 20px 48px -12px rgba(15,23,42,.18), 0 4px 12px -4px rgba(15,23,42,.08);
    --cf-shadow-glow:    0 8px 28px -6px rgba(17,80,230,.45);

    /* Motion */
    --cf-ease:           cubic-bezier(.22, 1, .36, 1);
    --cf-ease-out:       cubic-bezier(.16, 1, .3, 1);
    --cf-ease-spring:    cubic-bezier(.34, 1.56, .64, 1);
    --cf-dur-fast:       .16s;
    --cf-dur:            .28s;
    --cf-dur-slow:       .55s;

    /* Fonts */
    --cf-font:           'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --cf-font-mono:      'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

    /* Legacy alias kept in sync */
    --cf-card-shadow:    var(--cf-shadow);
}

/* ─────────────────────────────────────────────
   2. Base
   ───────────────────────────────────────────── */
/* Fluid base type: stays 16px on phones/laptops (no iOS input zoom,
   preserves the tuned laptop look) and scales up smoothly toward 18px
   on large monitors & projectors for legibility from a distance.
   All rem-based sizing across the app scales with it. */
html {
    scroll-behavior: smooth;
    font-size: clamp(16px, 14.6px + 0.14vw, 18px);
}

body {
    font-family: var(--cf-font);
    background-color: var(--cf-bg);
    background-image:
        radial-gradient(900px 500px at 100% -5%, rgba(10,102,194,.07), transparent 60%),
        radial-gradient(800px 500px at -10% 0%, rgba(17,80,230,.07), transparent 55%);
    background-attachment: fixed;
    color: var(--cf-text);
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Sticky footer — main fills leftover height so the footer
   stays pinned to the bottom on short pages. */
body > main { flex: 1 0 auto; }
body > .cf-footer { flex-shrink: 0; }

a { text-decoration: none; }
::selection { background: rgba(17,80,230,.22); }
.text-muted { color: var(--cf-text-muted) !important; }
.cf-mono { font-family: var(--cf-font-mono); }

.cf-gradient-text {
    background: var(--cf-accent-grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-thumb {
    background: #cbd2e0;
    border: 3px solid var(--cf-bg);
    border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover { background: #aeb6c9; }

/* ─────────────────────────────────────────────
   3. Navbar — theme-aware (clean white in light,
      dark glass in dark), sticky
   ───────────────────────────────────────────── */
.cf-navbar {
    background: var(--cf-nav-bg);
    backdrop-filter: saturate(180%) blur(16px);
    -webkit-backdrop-filter: saturate(180%) blur(16px);
    border-bottom: 1px solid var(--cf-nav-border);
    min-height: 64px;
    animation: cf-nav-in .6s var(--cf-ease-out) both;
    transition: box-shadow var(--cf-dur) var(--cf-ease), background var(--cf-dur) var(--cf-ease);
}
.cf-navbar.cf-scrolled {
    background: var(--cf-nav-bg-scroll);
    box-shadow: var(--cf-nav-shadow);
}

/* ── Centred contents ──
   Bootstrap gives .navbar-collapse flex-grow:1, so it eats the whole
   container and brand + links + user actions pack against the left edge —
   every spare pixel pools on the right. Shrinking the collapse to its
   content and centring the row splits that slack evenly instead.
   xl-and-up only: below that the bar is a stacked drawer. ── */
@media (min-width: 1200px) {
    .cf-navbar > .container { justify-content: center; }
    .cf-navbar .navbar-collapse { flex-grow: 0; }
}

@keyframes cf-nav-in {
    from { opacity: 0; transform: translateY(-14px); }
    to   { opacity: 1; transform: translateY(0); }
}

.cf-brand {
    font-weight: 800;
    font-size: 1.2rem;
    color: var(--cf-nav-brand) !important;
    letter-spacing: -.4px;
    display: flex;
    align-items: center;
    gap: .6rem;
}
.cf-brand-text {
    color: var(--cf-nav-brand);
    -webkit-text-fill-color: var(--cf-nav-brand);
    letter-spacing: -.2px;
}
[data-bs-theme="dark"] .cf-brand-text { text-shadow: 0 1px 2px rgba(0, 0, 0, .35); }

/* Official Semos Education logo (see the brand_lockup macro). The asset is
   full-colour with black wordmark text on a transparent background, so it
   reads on light surfaces as-is; on dark surfaces we invert it to solid
   white (brightness(0) makes every visible pixel black, invert(1) → white,
   transparency preserved). */
.cf-brand-logo { height: 34px; width: auto; display: block; }
.cf-brand-logo.is-lg { height: 46px; }              /* login / signup hero */
[data-bs-theme="dark"] .cf-brand-logo { filter: brightness(0) invert(1); }
.cf-hero .cf-brand-logo { filter: brightness(0) invert(1); }  /* hero band is always dark */

/* Sortable table-header links (admin submissions browser). Inherit the header
   colour; the arrow-hint dims until you hover, the active column highlights. */
.cf-sort-link { color: inherit; text-decoration: none; white-space: nowrap;
    display: inline-flex; align-items: center; gap: .3rem; }
.cf-sort-link .bi-arrow-down-up { opacity: 0; font-size: .8em; transition: opacity var(--cf-dur) var(--cf-ease); }
.cf-sort-link:hover { color: var(--cf-primary); }
.cf-sort-link:hover .bi-arrow-down-up { opacity: .45; }
.cf-sort-link.is-active { color: var(--cf-primary); font-weight: 700; }

.cf-brand-icon {
    width: 34px;
    height: 34px;
    background: var(--cf-accent-grad);
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1rem;
    flex-shrink: 0;
    box-shadow: 0 4px 14px rgba(17,80,230,.4);
    transition: transform var(--cf-dur) var(--cf-ease-spring), box-shadow var(--cf-dur) var(--cf-ease);
}
.cf-brand:hover .cf-brand-icon {
    transform: rotate(-6deg) scale(1.08);
    box-shadow: 0 6px 20px rgba(17,80,230,.6);
}

.cf-navbar .navbar-toggler { color: var(--cf-nav-text); border: none; }
.cf-navbar .navbar-toggler:focus { box-shadow: none; }
/* Toggler bars use currentColor via a mask so they follow the nav text token */
.cf-navbar .navbar-toggler-icon {
    background-image: none;
    -webkit-mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='black' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") center/100% no-repeat;
    mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='black' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") center/100% no-repeat;
    background-color: var(--cf-nav-text);
}

.cf-nav-link {
    position: relative;
    color: var(--cf-nav-text) !important;
    font-size: .9rem;
    font-weight: 500;
    padding: .45rem .85rem !important;
    border-radius: var(--cf-radius-xs);
    transition: color var(--cf-dur) var(--cf-ease), background var(--cf-dur) var(--cf-ease);
    display: flex;
    align-items: center;
    gap: .4rem;
}
.cf-nav-link::after {
    content: "";
    position: absolute;
    left: .85rem; right: .85rem;
    bottom: .2rem;
    height: 2px;
    border-radius: 2px;
    background: var(--cf-accent-grad);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--cf-dur) var(--cf-ease-out);
}
.cf-nav-link:hover { color: var(--cf-nav-text-hover) !important; background: var(--cf-nav-hover-bg); }
.cf-nav-link:hover::after,
.cf-nav-link.active::after { transform: scaleX(1); }
.cf-nav-link.active { color: var(--cf-primary) !important; }

.cf-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--cf-accent-grad);
    color: #fff;
    font-size: .8rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-shadow: 0 2px 8px rgba(17,80,230,.4);
}

/* ── Profile menu — the avatar is the trigger for a Profile / Settings /
   Logout popup, the same trio the sidebar layout keeps in its footer
   (.cf-sb-menu in sidebar.css). main.js owns the toggle. ── */
.cf-user-menu { position: relative; }

.cf-user-trigger {
    color: var(--cf-nav-text-hover);
    font-size: .9rem;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem .55rem;
    background: transparent;
    border: 0;
    border-radius: var(--cf-radius-xs);
    cursor: pointer;
    transition: background var(--cf-dur) var(--cf-ease);
}
.cf-user-trigger:hover,
.cf-user-trigger[aria-expanded="true"] { background: var(--cf-nav-hover-bg); }

.cf-user-caret {
    font-size: .7rem;
    color: var(--cf-nav-text);
    transition: transform var(--cf-dur) var(--cf-ease);
}
.cf-user-trigger[aria-expanded="true"] .cf-user-caret { transform: rotate(180deg); }

.cf-user-drop {
    position: absolute;
    /* Enough to clear the bar's bottom border, which the trigger sits 12px
       short of — a smaller offset lands the panel's corners on that line. */
    top: calc(100% + 16px);
    right: 0;
    z-index: 1030;
    min-width: 200px;
    padding: 6px;
    background: var(--cf-surface);
    border: 1px solid var(--cf-border);
    border-radius: 14px;
    box-shadow: var(--cf-shadow-lg);
    animation: cf-user-pop .16s var(--cf-ease-out);
}
.cf-user-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--cf-text-muted);
    font-size: .88rem;
    font-weight: 500;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--cf-dur-fast) ease, color var(--cf-dur-fast) ease;
}
.cf-user-item:hover { background: var(--cf-nav-hover-bg); color: var(--cf-text); }
.cf-user-item.active { color: var(--cf-primary); }
.cf-user-item.is-danger { color: var(--cf-danger); }
.cf-user-item.is-danger:hover { background: var(--cf-danger-light); color: var(--cf-danger); }

@keyframes cf-user-pop {
    from { opacity: 0; transform: translateY(-4px) scale(.98); }
    to   { opacity: 1; transform: none; }
}

/* Below the xl hamburger breakpoint the nav is a stacked list, so the menu
   opens inline (pushing the list down) instead of floating over it. */
@media (max-width: 1199.98px) {
    .cf-user-trigger { width: 100%; }
    .cf-user-caret { margin-left: auto; }
    .cf-user-drop {
        position: static;
        min-width: 0;
        margin-top: .25rem;
        background: var(--cf-nav-hover-bg);
        box-shadow: none;
        animation: none;
    }
}
@media (prefers-reduced-motion: reduce) {
    .cf-user-drop { animation: none; }
    .cf-user-caret { transition: none; }
}

.cf-role-badge {
    background: var(--cf-secondary-light);
    color: var(--cf-secondary-dark);
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .4px;
    padding: .2rem .5rem;
    border-radius: 99px;
}

/* ─────────────────────────────────────────────
   4. Buttons
   ───────────────────────────────────────────── */
.btn-cf-primary {
    position: relative;
    background: var(--cf-accent-grad);
    border: none;
    color: #fff;
    font-weight: 600;
    border-radius: var(--cf-radius-sm);
    box-shadow: var(--cf-shadow-glow);
    transition: transform var(--cf-dur-fast) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease), filter var(--cf-dur) var(--cf-ease);
    overflow: hidden;
}
.btn-cf-primary::before {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(120deg, transparent 20%, rgba(255,255,255,.35) 50%, transparent 80%);
    transform: translateX(-130%);
    transition: transform .7s var(--cf-ease);
}
.btn-cf-primary:hover:not(:disabled):not(.disabled) {
    color: #fff;
    transform: translateY(-2px);
    box-shadow: 0 12px 28px -6px rgba(17,80,230,.6);
    filter: saturate(1.1);
}
.btn-cf-primary:hover:not(:disabled):not(.disabled)::before { transform: translateX(130%); }
.btn-cf-primary:active:not(:disabled):not(.disabled) { transform: translateY(0) scale(.98); }

.btn-cf-outline {
    border: 1.5px solid var(--cf-border-strong);
    color: var(--cf-text);
    font-weight: 600;
    border-radius: var(--cf-radius-sm);
    background: var(--cf-surface);
    transition: border-color var(--cf-dur) var(--cf-ease), color var(--cf-dur) var(--cf-ease), transform var(--cf-dur-fast) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease);
}
.btn-cf-outline:hover:not(:disabled):not(.disabled) {
    border-color: var(--cf-primary);
    color: var(--cf-primary);
    transform: translateY(-2px);
    box-shadow: var(--cf-shadow-md);
}

.btn-cf-light {
    background: #fff;
    border: none;
    color: var(--cf-primary-dark);
    font-weight: 600;
    border-radius: var(--cf-radius-sm);
    transition: transform var(--cf-dur-fast) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease);
}
.btn-cf-light:hover:not(:disabled) {
    color: var(--cf-primary-dark);
    transform: translateY(-2px);
    box-shadow: 0 12px 28px -8px rgba(0,0,0,.4);
}

.btn-cf-ghost-light {
    background: rgba(255,255,255,.1);
    border: 1.5px solid rgba(255,255,255,.28);
    color: #fff;
    font-weight: 600;
    border-radius: var(--cf-radius-sm);
    transition: background var(--cf-dur) var(--cf-ease), transform var(--cf-dur-fast) var(--cf-ease), border-color var(--cf-dur) var(--cf-ease);
}
.btn-cf-ghost-light:hover:not(:disabled) {
    background: rgba(255,255,255,.2);
    border-color: rgba(255,255,255,.5);
    color: #fff;
    transform: translateY(-2px);
}
/* In the theme-aware navbar the ghost button must read on a light bar too. */
.cf-navbar .btn-cf-ghost-light {
    background: transparent;
    border-color: var(--cf-nav-border);
    color: var(--cf-nav-text);
}
.cf-navbar .btn-cf-ghost-light:hover:not(:disabled) {
    background: var(--cf-primary-light);
    border-color: var(--cf-primary);
    color: var(--cf-primary);
}

.btn-primary {
    background: var(--cf-accent-grad);
    border: none;
    font-weight: 600;
    border-radius: var(--cf-radius-sm);
}
.btn-primary:hover, .btn-primary:focus { background: var(--cf-primary-dark); }
.btn-outline-primary {
    border-color: var(--cf-primary);
    color: var(--cf-primary);
    border-radius: var(--cf-radius-sm);
    font-weight: 600;
}
.btn-outline-primary:hover { background: var(--cf-primary); border-color: var(--cf-primary); }
.btn:disabled, .btn.disabled { opacity: .5; box-shadow: none; }

/* ─────────────────────────────────────────────
   5. Cards
   ───────────────────────────────────────────── */
.cf-card {
    position: relative;
    background: var(--cf-surface);
    border: 1px solid var(--cf-border);
    border-radius: var(--cf-radius);
    box-shadow: var(--cf-shadow);
    transition: box-shadow var(--cf-dur) var(--cf-ease), transform var(--cf-dur) var(--cf-ease), border-color var(--cf-dur) var(--cf-ease);
}
.cf-card:hover {
    box-shadow: var(--cf-shadow-lg);
    transform: translateY(-4px);
    border-color: var(--cf-border-strong);
}

.cf-card-accent::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    border-radius: var(--cf-radius) var(--cf-radius) 0 0;
    background: var(--cf-accent-grad);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--cf-dur) var(--cf-ease-out);
}
.cf-card-accent:hover::before { transform: scaleX(1); }

.card {
    border-radius: var(--cf-radius);
    border-color: var(--cf-border);
    box-shadow: var(--cf-shadow);
}

.cf-icon-tile {
    width: 48px;
    height: 48px;
    border-radius: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    flex-shrink: 0;
    transition: transform var(--cf-dur) var(--cf-ease-spring);
}
.cf-card:hover .cf-icon-tile { transform: scale(1.1) rotate(-5deg); }

/* ─────────────────────────────────────────────
   6. Hero (dark, tech grid)
   ───────────────────────────────────────────── */
.cf-hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--cf-radius-xl);
    background:
        radial-gradient(120% 120% at 85% -10%, rgba(17,80,230,.40), transparent 55%),
        radial-gradient(100% 120% at 0% 110%, rgba(10,102,194,.32), transparent 50%),
        linear-gradient(160deg, #0F1420 0%, #141A2E 55%, #1B2440 100%);
    color: #fff;
    box-shadow: var(--cf-shadow-lg);
}
.cf-hero::before {
    content: "";
    position: absolute; inset: 0;
    background-image:
        linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
    background-size: 40px 40px;
    mask-image: radial-gradient(circle at 50% 35%, #000 35%, transparent 78%);
    -webkit-mask-image: radial-gradient(circle at 50% 35%, #000 35%, transparent 78%);
    pointer-events: none;
}
.cf-hero-blob {
    position: absolute;
    border-radius: 50%;
    filter: blur(10px);
    pointer-events: none;
    animation: cf-float 9s ease-in-out infinite;
}

@keyframes cf-float {
    0%, 100% { transform: translateY(0) scale(1); }
    50%      { transform: translateY(-22px) scale(1.05); }
}

.cf-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    background: rgba(255,255,255,.08);
    border: 1px solid rgba(255,255,255,.16);
    color: #d6dbf5;
    border-radius: 99px;
    padding: .4rem .9rem;
    font-size: .8rem;
    font-weight: 500;
    backdrop-filter: blur(6px);
}
.cf-eyebrow .cf-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: #34d399;
    animation: cf-pulse 2s infinite;
}
@keyframes cf-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(52,211,153,.55); }
    70%  { box-shadow: 0 0 0 8px rgba(52,211,153,0); }
    100% { box-shadow: 0 0 0 0 rgba(52,211,153,0); }
}

/* ─────────────────────────────────────────────
   7. Difficulty badges
   ───────────────────────────────────────────── */
.cf-diff {
    font-family: var(--cf-font-mono);
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .2px;
    border-radius: 99px;
    padding: .28rem .6rem;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    white-space: nowrap;
}
.cf-diff i { font-size: .5rem; }
.cf-diff-easy { background: var(--cf-success-light); color: #047857; }
.cf-diff-med  { background: var(--cf-warning-light); color: #b45309; }
.cf-diff-hard { background: var(--cf-danger-light);  color: #be123c; }

/* ─────────────────────────────────────────────
   8. Catalogue / topic cards
   ───────────────────────────────────────────── */
.cf-topic { position: relative; display: block; color: inherit; overflow: hidden; }
.cf-topic h5 { color: var(--cf-text); transition: color var(--cf-dur) var(--cf-ease); }
.cf-topic:hover h5 { color: var(--cf-primary); }
.cf-topic-meta {
    display: flex;
    align-items: center;
    gap: .4rem;
    color: var(--cf-text-faint);
    font-size: .76rem;
    font-family: var(--cf-font-mono);
}
.cf-topic-go {
    position: absolute;
    bottom: 1.15rem; right: 1.15rem;
    width: 30px; height: 30px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--cf-primary-light);
    color: var(--cf-primary);
    opacity: 0;
    transform: translateX(-8px);
    transition: opacity var(--cf-dur) var(--cf-ease), transform var(--cf-dur) var(--cf-ease);
}
.cf-topic:hover .cf-topic-go { opacity: 1; transform: translateX(0); }

/* ─────────────────────────────────────────────
   9. Stat tiles
   ───────────────────────────────────────────── */
.cf-stat { display: flex; flex-direction: column; gap: .2rem; }
.cf-stat-value {
    font-size: 2rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -1px;
    font-family: var(--cf-font-mono);
}
.cf-stat-label { font-size: .8rem; color: var(--cf-text-muted); font-weight: 500; }

/* Section eyebrow heading */
.cf-section-label {
    font-size: .78rem;
    font-weight: 700;
    color: var(--cf-text-muted);
    letter-spacing: 1.2px;
    text-transform: uppercase;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

/* ─────────────────────────────────────────────
   10. Forms
   ───────────────────────────────────────────── */
.form-control, .form-select {
    border-radius: var(--cf-radius-sm);
    border-color: var(--cf-border-strong);
    padding: .6rem .85rem;
    transition: border-color var(--cf-dur) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease);
}
/* Selects need extra right padding so option text never runs under the
   native dropdown arrow — the shared rule above sets a flat padding that's
   too tight on the right for a <select>. */
.form-select { padding-right: 2.5rem; }
.form-select-sm { padding: .375rem 2.2rem .375rem .75rem; font-size: .875rem; }
.form-control:focus, .form-select:focus {
    border-color: var(--cf-primary);
    box-shadow: 0 0 0 4px rgba(17,80,230,.15);
}
.input-group-text {
    border-radius: var(--cf-radius-sm);
    border-color: var(--cf-border-strong);
    color: var(--cf-text-muted);
}
.cf-input-icon { position: relative; }
.cf-input-icon > i {
    position: absolute;
    left: .9rem; top: 50%;
    transform: translateY(-50%);
    color: var(--cf-text-faint);
    pointer-events: none;
    transition: color var(--cf-dur) var(--cf-ease);
    z-index: 3;
}
.cf-input-icon .form-control { padding-left: 2.5rem; }
.cf-input-icon:focus-within > i { color: var(--cf-primary); }
.cf-input-icon:has(.cf-pw-toggle) .form-control { padding-right: 2.5rem; }
.cf-pw-toggle {
    position: absolute;
    right: .9rem; top: 50%;
    transform: translateY(-50%);
    display: flex; align-items: center;
    background: none; border: none; padding: 0;
    color: var(--cf-text-faint);
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease);
    z-index: 3;
}
.cf-pw-toggle:hover, .cf-pw-toggle:focus-visible { color: var(--cf-primary); }

/* Clear (×) button inside a filter-search input (_macros.html: filter_search) */
.cf-input-icon:has(.cf-filter-clear) .form-control { padding-right: 2.5rem; }
.cf-filter-clear {
    position: absolute;
    right: .9rem; top: 50%;
    transform: translateY(-50%);
    display: flex; align-items: center;
    background: none; border: none; padding: 0;
    color: var(--cf-text-faint);
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease);
    z-index: 3;
}
.cf-filter-clear:hover, .cf-filter-clear:focus-visible { color: var(--cf-danger); }

/* ─────────────────────────────────────────────
   11. Alerts
   ───────────────────────────────────────────── */
.alert {
    border-radius: var(--cf-radius-sm);
    border: 1px solid transparent;
    font-size: .9rem;
    box-shadow: var(--cf-shadow);
    animation: cf-rise .4s var(--cf-ease-out) both;
}
.alert-success { background: var(--cf-success-light); color: #166534; border-color: #bbf7d0; }
.alert-danger  { background: var(--cf-danger-light);  color: #9f1239; border-color: #fecdd3; }
.alert-warning { background: var(--cf-warning-light); color: #92400e; border-color: #fde68a; }
.alert-info    { background: #eff6ff; color: #1e40af; border-color: #bfdbfe; }

/* ─────────────────────────────────────────────
   12. Footer
   ───────────────────────────────────────────── */
.cf-footer {
    background: var(--cf-footer-bg);
    color: var(--cf-footer-text);
    border-top: 1px solid var(--cf-footer-border);
    margin-top: 4rem;
}
.cf-footer a { color: var(--cf-footer-link); transition: color var(--cf-dur) var(--cf-ease); }
.cf-footer a:hover { color: var(--cf-footer-link-hover); }
/* Footer brand — a touch larger. Light footer → full-colour logo; dark footer
   inverts to white via the [data-bs-theme="dark"] .cf-brand-logo rule above. */
.cf-footer .cf-brand-logo { height: 40px; }

.cf-footer-head {
    color: var(--cf-footer-head);
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    margin-bottom: 1rem;
}
.cf-footer-links { list-style: none; padding: 0; margin: 0; }
.cf-footer-links li { margin-bottom: .55rem; font-size: .9rem; }
.cf-footer-links li span { color: var(--cf-footer-text); }

.cf-footer-social { display: flex; gap: .55rem; }
.cf-footer-social a {
    width: 38px; height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    font-size: 1.05rem;
    color: var(--cf-footer-chip-text);
    background: var(--cf-footer-chip-bg);
    border: 1px solid var(--cf-footer-chip-border);
    transition: color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                border-color var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-footer-social a:hover {
    color: #fff;
    background: var(--cf-primary);
    border-color: var(--cf-primary);
    transform: translateY(-2px);
}
.cf-footer-bottom {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--cf-footer-border);
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1.5rem;
    align-items: center;
    justify-content: space-between;
}

/* ─────────────────────────────────────────────
   13. Motion utilities — reveal / stagger
   ───────────────────────────────────────────── */
@keyframes cf-rise {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: translateY(0); }
}

.cf-reveal { animation: cf-rise var(--cf-dur-slow) var(--cf-ease-out) both; }
.cf-reveal[style*="--i"] { animation-delay: calc(var(--i) * 80ms); }

/* Hidden state only applies when JS is active (progressive enhancement) */
.js .reveal {
    opacity: 0;
    transform: translateY(26px);
    transition: opacity .7s var(--cf-ease-out), transform .7s var(--cf-ease-out);
    transition-delay: calc(var(--i, 0) * 80ms);
    will-change: opacity, transform;
}
.js .reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ─────────────────────────────────────────────
   14. Legacy component upgrades
   (shared classes from main.css used across
    catalogue / profile / leaderboard / classrooms
    / discussions / problem — restyled to match)
   ───────────────────────────────────────────── */

/* Semos blue activity-calendar heat scale */
:root {
    --cal-empty: #ECEEF2;
    --cal-1:     #C3D4FF;
    --cal-2:     #5A8CFF;
    --cal-3:     #1150E6;
}
[data-bs-theme="dark"] {
    --cal-empty: #232B40;
    --cal-1:     rgba(90,140,255,.28);
    --cal-2:     rgba(90,140,255,.60);
    --cal-3:     #5A8CFF;
}

/* Tables */
.table { color: var(--cf-text); border-color: var(--cf-border); margin-bottom: 0; }
.table > :not(caption) > * > * { padding: .85rem 1rem; }
.table thead th {
    background: var(--cf-surface-2);
    color: var(--cf-text-muted);
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    border-bottom: 1px solid var(--cf-border);
}
.table-light, .table-light > th, .table-light > td { background: var(--cf-surface-2) !important; }
.table-hover > tbody > tr { transition: background-color var(--cf-dur) var(--cf-ease); }
.table-hover > tbody > tr:hover > * { background-color: var(--cf-primary-light); }
.table-warning, .table-warning > td, .table-warning > th {
    background-color: #E4ECFF !important;
    box-shadow: inset 3px 0 0 var(--cf-primary);
}
.card-header { background: var(--cf-surface); border-bottom: 1px solid var(--cf-border); font-weight: 600; }

/* Category pill sidebar */
.category-pill {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .85rem;
    border-radius: var(--cf-radius-sm);
    color: var(--cf-text-muted);
    font-size: .9rem;
    font-weight: 500;
    margin-bottom: .25rem;
    transition: background var(--cf-dur) var(--cf-ease), color var(--cf-dur) var(--cf-ease), transform var(--cf-dur) var(--cf-ease);
}
.category-pill:hover { background: var(--cf-primary-light); color: var(--cf-primary); transform: translateX(3px); }
.category-pill.active { background: var(--cf-accent-grad); color: #fff; box-shadow: var(--cf-shadow-glow); }

/* Problem rows / links */
.problem-row { transition: background-color var(--cf-dur) var(--cf-ease); }
.problem-row:hover { background-color: var(--cf-primary-light); }
.problem-title-link { color: var(--cf-text); transition: color var(--cf-dur) var(--cf-ease); }
.problem-title-link:hover { color: var(--cf-primary); text-decoration: none; }

/* Language badge */
.lang-badge {
    background: var(--cf-primary-light);
    color: var(--cf-primary-dark);
    border: 1px solid #C3D4FF;
    font-family: var(--cf-font-mono);
    font-weight: 600;
    font-size: .72rem;
}

/* Difficulty badges (5-level scale) → soft pills */
.badge-diff-easy, .badge-diff-intermediate, .badge-diff-medium,
.badge-diff-hard, .badge-diff-extreme,
.badge-easy, .badge-medium, .badge-hard {
    font-family: var(--cf-font-mono);
    font-weight: 600;
    font-size: .72rem;
    border-radius: 99px;
    padding: .3em .65em;
}
.badge-diff-easy         { background: var(--cf-success-light) !important; color: #047857 !important; }
.badge-diff-intermediate { background: #ecfeff !important;                 color: #0e7490 !important; }
.badge-diff-medium       { background: var(--cf-warning-light) !important; color: #b45309 !important; }
.badge-diff-hard         { background: var(--cf-danger-light) !important;  color: #be123c !important; }
.badge-diff-extreme      { background: #E7F1FB !important;                 color: #0A5AAC !important; }
.badge-easy   { background: var(--cf-success-light) !important; color: #047857 !important; }
.badge-medium { background: var(--cf-warning-light) !important; color: #b45309 !important; }
.badge-hard   { background: var(--cf-danger-light) !important;  color: #be123c !important; }

/* Empty states */
.empty-state { padding: 3rem 1.5rem; text-align: center; color: var(--cf-text-muted); }
.empty-state .fs-4, .empty-state .fs-5 { color: var(--cf-text); }

/* Uploaded profile pictures: fill whatever sized avatar box they're given */
.cf-pic {
    object-fit: cover;
    background: var(--cf-surface-2);
    padding: 0 !important;
    border: none;
}

/* Profile header / avatars */
.profile-header { border: 1px solid var(--cf-border); border-left: 4px solid var(--cf-primary); overflow: hidden; }
.profile-avatar {
    width: 124px; height: 124px; border-radius: 30px;
    background: var(--cf-accent-grad);
    color: #fff; font-size: 3rem; font-weight: 800;
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    box-shadow: var(--cf-shadow-glow);
}
.avatar-initials {
    width: 28px; height: 28px; border-radius: 50%;
    background: var(--cf-accent-grad); color: #fff;
    font-size: 12px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
    margin-right: 6px;
}

/* ── Avatar lightbox — click a profile picture to enlarge it over a blurred
      page; clicking anywhere (or Esc) closes it. ── */
.js-avatar-zoom { cursor: zoom-in; }

.cf-avatar-lightbox {
    position: fixed; inset: 0; z-index: 2000;
    display: flex; align-items: center; justify-content: center;
    background: rgba(8, 11, 24, .45);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    cursor: zoom-out;
    animation: cfLightboxFade .22s ease;
}
.cf-avatar-lightbox.is-closing { opacity: 0; transition: opacity .18s ease; }

.cf-avatar-lightbox .cf-avatar-lightbox-pic {
    width: min(340px, 78vw); height: min(340px, 78vw);
    border-radius: 32px;
    object-fit: cover;
    box-shadow: 0 24px 80px rgba(0, 0, 0, .55);
    border: 4px solid rgba(255, 255, 255, .85);
    animation: cfLightboxZoom .22s ease;
}
.cf-avatar-lightbox .cf-avatar-lightbox-initials {
    width: min(340px, 78vw); height: min(340px, 78vw);
    border-radius: 32px;
    background: var(--cf-accent-grad);
    color: #fff; font-size: clamp(6rem, 30vw, 9rem); font-weight: 800;
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 24px 80px rgba(0, 0, 0, .55);
    border: 4px solid rgba(255, 255, 255, .85);
    animation: cfLightboxZoom .22s ease;
}
.cf-avatar-lightbox .cf-avatar-lightbox-name {
    position: absolute; bottom: 9vh; left: 0; right: 0;
    text-align: center; color: #fff; font-weight: 700; font-size: 1.05rem;
    text-shadow: 0 2px 12px rgba(0, 0, 0, .6);
}

@keyframes cfLightboxFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cfLightboxZoom { from { transform: scale(.72); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* Role badges */
.role-badge { font-size: .8rem; padding: .4em .8em; border-radius: 99px; font-weight: 600; }
.role-badge.role-admin   { background: var(--cf-danger-light);  color: #be123c; }
.role-badge.role-teacher { background: var(--cf-primary-light); color: var(--cf-primary-dark); }
.role-badge.role-student { background: var(--cf-success-light); color: #047857; }

/* Stat boxes / numbers */
.stat-box {
    background: var(--cf-surface-2);
    border: 1px solid var(--cf-border);
    border-radius: var(--cf-radius);
    padding: 1.1rem .5rem;
    transition: transform var(--cf-dur) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease);
}
.stat-box:hover { transform: translateY(-3px); box-shadow: var(--cf-shadow-md); }
.stat-number { font-family: var(--cf-font-mono); font-size: 1.9rem; font-weight: 800; line-height: 1; letter-spacing: -.5px; }
.stat-label  { font-size: .75rem; color: var(--cf-text-muted); margin-top: .4rem; font-weight: 500; }

/* Donut numbers */
.donut-number { font-family: var(--cf-font-mono); font-weight: 800; color: var(--cf-text); }

/* Rank pill / medals */
.rank-pill {
    background: #f3c14b;
    color: #5a3e00; border-radius: 99px; padding: .35em .85em; font-weight: 700;
}
.medal { font-size: 1.5rem; }

/* All-time rank link on the profile header — a quiet, tappable pill, not the
   gold .rank-pill "medal" used for counts elsewhere. Flat surface + hairline,
   theme-aware via tokens, so it reads as a subtle link rather than a trophy. */
.rank-link {
    background: var(--cf-surface-2);
    color: var(--cf-text-muted);
    border: 1px solid var(--cf-border);
    border-radius: 99px;
    padding: .4em .9em;
    font-weight: 600;
    transition: border-color .15s ease, color .15s ease;
}
.rank-link:hover,
.rank-link:focus-visible {
    border-color: var(--cf-primary);
    color: var(--cf-text);
}

/* ── "Your position" context block ── */
.cf-lb-position { margin-top: 1.25rem; }
.cf-lb-position-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: .75rem; flex-wrap: wrap;
    padding: 1rem 1.25rem .85rem;
    border-bottom: 1px solid var(--cf-border);
}
/* Distinct accent for the current user's row (both themes via --cf tokens). */
.cf-lb-you,
.table-hover > tbody > tr.cf-lb-you:hover > * {
    --bs-table-bg-state: var(--cf-primary-light);
    background-color: var(--cf-primary-light) !important;
    box-shadow: inset 3px 0 0 0 var(--cf-primary);
}
/* Gap ("…") and unranked rows: informational, so no click affordance/hover. */
.cf-lb-gap td {
    padding: .3rem 0; color: var(--cf-text-faint);
    font-size: 1.15rem; letter-spacing: .15em;
}
.cf-lb-unranked td { padding: .95rem 1rem; font-style: italic; }
.cf-lb-gap, .cf-lb-unranked { cursor: default; }
.table-hover > tbody > tr.cf-lb-gap:hover > *,
.table-hover > tbody > tr.cf-lb-unranked:hover > * {
    --bs-table-bg-state: transparent;
    background-color: transparent;
}

/* ── Champions podium — the top-3 "arena" ────────────────────────────
   A self-contained dark stage, deliberately dark in BOTH themes (like a
   stadium screen) so the spotlight glows and metallic pedestals read the
   same everywhere. All CSS, no images: each pedestal is an elliptical
   metallic cap + a side-shaded barrel + a floor shadow, which together
   sell the cylinder. */
.cf-podium-stage {
    position: relative;
    max-width: 780px;
    margin: 0 auto;
    padding: 44px 28px 30px;
    border-radius: 20px;
    border: 1px solid rgba(120, 160, 255, .14);
    overflow: hidden;
    background:
        radial-gradient(460px 280px at 50% 24%, rgba(255, 193, 79, .14), transparent 70%),
        radial-gradient(340px 220px at 20% 52%, rgba(61, 139, 224, .13), transparent 72%),
        radial-gradient(340px 220px at 80% 52%, rgba(61, 139, 224, .13), transparent 72%),
        linear-gradient(180deg, #0a1226 0%, #0a0f1e 55%, #070b16 100%);
    box-shadow: 0 24px 60px -28px rgba(4, 10, 30, .9);
}
/* Star-dust specks: the void reads as depth rather than emptiness. */
.cf-podium-stage::before {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    background-image:
        radial-gradient(circle, rgba(255, 255, 255, .5) 1px, transparent 1.6px),
        radial-gradient(circle, rgba(255, 255, 255, .35) 1px, transparent 1.6px);
    background-size: 210px 170px, 140px 120px;
    background-position: 30px 40px, 95px 90px;
    opacity: .13;
}
/* Spotlight cone falling on the champion. */
.cf-podium-stage::after {
    content: '';
    position: absolute;
    left: 50%; top: -8%;
    width: 320px; height: 72%;
    transform: translateX(-50%);
    pointer-events: none;
    background: linear-gradient(180deg, rgba(255, 214, 130, .17), rgba(255, 214, 130, 0) 78%);
    clip-path: polygon(38% 0, 62% 0, 100% 100%, 0 100%);
}

.cf-podium-row {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 18px;
}

.cf-podium-place {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 178px;
    text-decoration: none;
    transition: transform .35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.cf-podium-place:hover { transform: translateY(-5px); }

/* The floating competitor card above each pedestal. */
.cf-podium-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 16px;
    animation: cf-podium-float 3.2s ease-in-out infinite alternate;
}
.cf-podium-second .cf-podium-card { animation-delay: .55s; }
.cf-podium-third  .cf-podium-card { animation-delay: 1.1s; }
@keyframes cf-podium-float { from { transform: translateY(0); } to { transform: translateY(-7px); } }

.cf-podium-ava { position: relative; }
.cf-podium-crown {
    position: absolute; top: -22px; left: 50%; transform: translateX(-50%);
    font-size: 1.5rem;
    filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .5));
    z-index: 1;
}
/* Works for both the <img> avatar and the <span> initials fallback. */
.cf-podium-avatar {
    display: flex; align-items: center; justify-content: center;
    width: 62px; height: 62px; border-radius: 50%;
    object-fit: cover;
    background: linear-gradient(135deg, #3D8BE0, #0A66C2);
    color: #fff; font-weight: 800; font-size: 1.3rem;
    border: 3px solid #e8eef7;
    box-shadow: 0 0 0 3px rgba(150, 175, 210, .35), 0 10px 26px rgba(4, 16, 44, .65);
}
.cf-podium-first .cf-podium-avatar {
    width: 78px; height: 78px; font-size: 1.6rem;
    border-color: #ffe9a6;
    box-shadow: 0 0 0 3px rgba(247, 201, 72, .5), 0 0 30px rgba(247, 201, 72, .35),
                0 12px 30px rgba(4, 16, 44, .7);
}
.cf-podium-third .cf-podium-avatar {
    border-color: #f0c9a0;
    box-shadow: 0 0 0 3px rgba(233, 165, 102, .4), 0 10px 26px rgba(4, 16, 44, .65);
}
.cf-podium-name {
    margin-top: 10px;
    font-weight: 800; font-size: .92rem; color: #f2f6ff;
    max-width: 156px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    text-shadow: 0 2px 8px rgba(0, 0, 0, .55);
}
.cf-podium-pts {
    margin-top: 5px;
    font-weight: 800; font-size: .74rem; letter-spacing: .02em;
    padding: .22em .8em; border-radius: 999px;
    color: #ffe9b0; background: rgba(255, 193, 79, .13);
    border: 1px solid rgba(255, 193, 79, .35);
}
.cf-podium-second .cf-podium-pts,
.cf-podium-third  .cf-podium-pts {
    color: #cfe1ff; background: rgba(122, 168, 255, .12);
    border-color: rgba(122, 168, 255, .3);
}

/* ── The cylinder ── */
.cf-podium-cyl { position: relative; width: 100%; }
/* Elliptical metallic cap; overlaps the barrel to read as its top face. */
.cf-podium-cap {
    position: relative;
    z-index: 2;
    height: 44px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: -22px;
}
.cf-podium-medal { font-size: 1.4rem; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .35)); }
.cf-podium-barrel {
    position: relative;
    border-radius: 0 0 50% 50% / 0 0 22px 22px;
    display: flex; align-items: flex-start; justify-content: center;
    padding-top: 34px;
    overflow: hidden;
}
/* Side shading wraps the barrel so it reads round, not flat. */
.cf-podium-barrel::before {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(90deg, rgba(0, 0, 0, .42), transparent 22%,
                                transparent 78%, rgba(0, 0, 0, .42));
}
/* Floor ellipse under the pedestal. */
.cf-podium-cyl::after {
    content: '';
    position: absolute; left: 50%; bottom: -12px;
    width: 130%; height: 26px;
    transform: translateX(-50%);
    background: radial-gradient(50% 50% at 50% 50%, rgba(0, 0, 0, .55), transparent 72%);
    z-index: -1;
}
.cf-podium-rank {
    position: relative; z-index: 1;
    font-weight: 900; font-size: 1.5rem; color: #fff;
    letter-spacing: .02em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, .45);
}

/* Heights: the champion towers. */
.cf-podium-first  .cf-podium-barrel { height: 168px; }
.cf-podium-second .cf-podium-barrel { height: 120px; }
.cf-podium-third  .cf-podium-barrel { height: 96px; }

/* Colourways: gold / silver / bronze caps on brand-blue barrels. */
.cf-podium-first .cf-podium-cap {
    background: radial-gradient(120% 160% at 50% 0%, #ffe9a6 0%, #f7c948 48%, #d99a1f 100%);
    box-shadow: 0 0 0 1px rgba(255, 222, 130, .8), 0 6px 22px rgba(247, 201, 72, .45);
}
.cf-podium-first .cf-podium-barrel {
    background: linear-gradient(180deg, #2f7bea 0%, #0f4fb4 52%, #093674 100%);
    box-shadow: 0 18px 44px -16px rgba(21, 91, 205, .55);
}
.cf-podium-second .cf-podium-cap {
    background: radial-gradient(120% 160% at 50% 0%, #ffffff 0%, #d9e2ef 46%, #9fadc4 100%);
    box-shadow: 0 0 0 1px rgba(233, 240, 250, .75), 0 6px 18px rgba(190, 205, 228, .35);
}
.cf-podium-second .cf-podium-barrel {
    background: linear-gradient(180deg, #1f61c8 0%, #0d47a1 55%, #082f6b 100%);
    box-shadow: 0 16px 38px -16px rgba(18, 76, 175, .5);
}
.cf-podium-third .cf-podium-cap {
    background: radial-gradient(120% 160% at 50% 0%, #ffd9ae 0%, #e9a566 48%, #b56a2c 100%);
    box-shadow: 0 0 0 1px rgba(240, 190, 140, .7), 0 6px 18px rgba(214, 141, 74, .4);
}
.cf-podium-third .cf-podium-barrel {
    background: linear-gradient(180deg, #1a56b4 0%, #0b3d8d 55%, #072a5f 100%);
    box-shadow: 0 14px 34px -16px rgba(15, 66, 152, .5);
}

/* Caption under the podiums — the arena tagline. */
.cf-podium-caption { position: relative; z-index: 1; text-align: center; margin-top: 28px; }
.cf-podium-tag {
    font-weight: 900; font-size: .95rem; letter-spacing: .12em; text-transform: uppercase;
    color: #86b4ff;
    text-shadow: 0 0 18px rgba(96, 150, 255, .45);
}
.cf-podium-sub { margin-top: 5px; font-size: .82rem; font-weight: 600; color: rgba(226, 236, 255, .55); }

@media (max-width: 575.98px) {
    .cf-podium-stage { padding: 32px 12px 22px; }
    .cf-podium-row { gap: 10px; }
    .cf-podium-place { width: 31%; }
    .cf-podium-first  .cf-podium-barrel { height: 128px; }
    .cf-podium-second .cf-podium-barrel { height: 92px; }
    .cf-podium-third  .cf-podium-barrel { height: 74px; }
    .cf-podium-name { font-size: .8rem; max-width: 100px; }
    .cf-podium-tag { font-size: .76rem; }
}
@media (prefers-reduced-motion: reduce) {
    .cf-podium-card { animation: none; }
    .cf-podium-place, .cf-podium-place:hover { transition: none; transform: none; }
}

/* ── Leaderboard range toggle (Weekly / Monthly / All-time) ── */
.cf-range-tabs {
    display: inline-flex;
    gap: .25rem;
    padding: .3rem;
    border-radius: var(--cf-radius);
    background: var(--cf-surface-2);
    border: 1.5px solid var(--cf-border);
}
.cf-range-tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    min-width: 108px;
    padding: .5rem 1.1rem;
    border: none;
    border-radius: var(--cf-radius-sm);
    background: transparent;
    color: var(--cf-text-muted);
    font-family: var(--cf-font);
    font-size: .92rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                box-shadow var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-range-tab:hover:not(.is-active) {
    color: var(--cf-primary);
    background: var(--cf-primary-light);
}
.cf-range-tab:active:not(.is-active) { transform: scale(.97); }
.cf-range-tab.is-active {
    background: var(--cf-accent-grad);
    color: #fff;
    box-shadow: var(--cf-shadow-glow);
    animation: cf-tab-pop var(--cf-dur) var(--cf-ease-out);
}
@keyframes cf-tab-pop {
    0%   { transform: scale(.94); }
    60%  { transform: scale(1.03); }
    100% { transform: scale(1); }
}
@media (max-width: 575.98px) {
    .cf-range-tabs { display: flex; width: 100%; }
    .cf-range-tab { flex: 1; min-width: 0; padding: .5rem .35rem; font-size: .84rem; }
    .cf-range-tab i { display: none; }
}

/* Points cell — subtle monospace emphasis in the ranking table */
.cf-pts { color: var(--cf-primary); font-weight: 800; }
.cf-pts-unit { font-size: .72em; color: var(--cf-text-muted); font-weight: 600; margin-left: .15rem; }

/* Sort toggle (Sort by: Points / Solved) — lighter than the range tabs */
.cf-sort-label {
    font-size: .82rem;
    font-weight: 600;
    color: var(--cf-text-muted);
    display: inline-flex;
    align-items: center;
}
.cf-sort-toggle {
    display: inline-flex;
    gap: .2rem;
    padding: .2rem;
    border-radius: var(--cf-radius-sm);
    background: var(--cf-surface-2);
    border: 1.5px solid var(--cf-border);
}
.cf-sort-btn {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .35rem .85rem;
    border-radius: var(--cf-radius-xs);
    background: transparent;
    color: var(--cf-text-muted);
    font-family: var(--cf-font);
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                box-shadow var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-sort-btn:hover:not(.is-active) { color: var(--cf-primary); background: var(--cf-primary-light); }
.cf-sort-btn:active:not(.is-active) { transform: scale(.96); }
.cf-sort-btn.is-active {
    background: var(--cf-surface);
    color: var(--cf-primary);
    box-shadow: 0 2px 8px -2px rgba(15, 23, 42, .18);
}
.cf-sort-btn i { font-size: .92em; }

/* Sortable column headers (Points / Solved) */
.cf-sort-th {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    color: inherit;
    font: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease);
}
.cf-sort-th:hover { color: var(--cf-primary); }
.cf-sort-th.is-active { color: var(--cf-primary); font-weight: 700; }
.cf-sort-th i { font-size: .68em; }

/* Social stats (Followers / Following / Friends) */
.cf-social-stat {
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--cf-radius-sm);
    padding: .4rem .9rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.1;
    cursor: pointer;
    transition: background var(--cf-dur) var(--cf-ease), border-color var(--cf-dur) var(--cf-ease), transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-social-stat:hover {
    background: var(--cf-primary-light);
    border-color: var(--cf-border);
    transform: translateY(-1px);
}
.cf-social-num { font-weight: 800; font-size: 1.25rem; color: var(--cf-text); }
.cf-social-lbl { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--cf-text-muted); }
.cf-social-rowlink:hover { background: var(--cf-surface-2); border-radius: var(--cf-radius-xs); }
.min-w-0 { min-width: 0; }

/* "Friends ✓" button hints at the destructive unfriend action on hover */
.cf-friends-btn:hover {
    border-color: var(--cf-danger) !important;
    color: var(--cf-danger) !important;
    background: var(--cf-danger-light) !important;
}
.cf-friends-btn:hover .cf-friends-label::after { content: " · Unfriend"; }

/* Badge pinned next to the username */
.cf-pinned-badge {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .8rem;
    font-weight: 700;
    padding: .2rem .7rem;
    border-radius: 99px;
    color: #0A4F98;
    background: linear-gradient(135deg, #DCE9F7, #C3DCF2);
    border: 1px solid #8FC0F0;
    box-shadow: 0 2px 8px -2px rgba(10,102,194,.35);
    white-space: nowrap;
}
.cf-pinned-badge-ico { font-size: 1rem; line-height: 1; }

/* Badges section */
.cf-badge-group-label {
    font-weight: 700;
    font-size: .85rem;
    color: var(--cf-text);
    margin-bottom: .75rem;
}
.cf-badge-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .85rem;
}
/* Profile panel: every earned badge on ONE row that scrolls sideways.
   Groups sit next to each other, each with its label above its cards. */
.cf-badge-strip {
    display: flex;
    align-items: stretch;
    gap: 1.5rem;
    overflow-x: auto;
    padding-bottom: .4rem;
    scrollbar-width: thin;
    scrollbar-color: var(--cf-border-strong) transparent;
}
.cf-badge-strip::-webkit-scrollbar { height: 8px; }
.cf-badge-strip::-webkit-scrollbar-track { background: transparent; }
.cf-badge-strip::-webkit-scrollbar-thumb { background: var(--cf-border-strong); border-radius: 99px; }
.cf-badge-strip-group { flex: 0 0 auto; display: flex; flex-direction: column; }
.cf-badge-strip-row { display: flex; gap: .85rem; flex-grow: 1; }
.cf-badge-strip .cf-badge {
    width: 158px;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
}
.cf-badge-strip .cf-badge form { margin-top: auto !important; }
.cf-badge {
    position: relative;
    text-align: center;
    border: 1px solid var(--cf-border);
    border-radius: var(--cf-radius);
    padding: 1rem .75rem;
    background: var(--cf-surface);
    transition: transform var(--cf-dur-fast) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease);
}
.cf-badge.is-earned {
    background: linear-gradient(160deg, #ffffff, #E7F1FB);
    border-color: #C3DCF2;
    box-shadow: var(--cf-shadow-xs);
}
.cf-badge.is-earned:hover { transform: translateY(-2px); box-shadow: var(--cf-shadow-md); }
.cf-badge.is-locked { opacity: .65; filter: grayscale(.7); }
.cf-badge.is-pinned { border-color: var(--cf-violet); box-shadow: 0 0 0 2px rgba(10,102,194,.25); }
.cf-badge-ico { font-size: 2rem; line-height: 1; margin-bottom: .35rem; }
.cf-badge.is-locked .cf-badge-ico { filter: grayscale(1); }
.cf-badge-name { font-weight: 700; font-size: .85rem; }
.cf-badge-desc { font-size: .72rem; color: var(--cf-text-muted); margin-top: .15rem; }
.cf-badge-prog {
    margin-top: .4rem;
    font-family: var(--cf-font-mono);
    font-size: .72rem;
    font-weight: 700;
    color: var(--cf-primary);
}
.cf-badge-pinflag {
    position: absolute;
    top: .4rem;
    right: .5rem;
    color: var(--cf-violet);
    font-size: .85rem;
}

/* Nav tabs / pills */
.nav-tabs { border-bottom: 1px solid var(--cf-border); }
.nav-tabs .nav-link {
    border: none; color: var(--cf-text-muted); font-weight: 600; font-size: .9rem;
    padding: .6rem 1rem; border-radius: 0; border-bottom: 2px solid transparent;
    transition: color var(--cf-dur) var(--cf-ease), border-color var(--cf-dur) var(--cf-ease);
}
.nav-tabs .nav-link:hover { color: var(--cf-primary); border-bottom-color: var(--cf-border-strong); }
.nav-tabs .nav-link.active { color: var(--cf-primary); background: transparent; border-bottom-color: var(--cf-primary); }
.nav-pills .nav-link {
    color: var(--cf-text-muted); font-weight: 600; font-size: .88rem;
    border-radius: 99px; padding: .45rem 1rem;
    transition: background var(--cf-dur) var(--cf-ease), color var(--cf-dur) var(--cf-ease);
}
.nav-pills .nav-link:hover { background: var(--cf-primary-light); color: var(--cf-primary); }
.nav-pills .nav-link.active { background: var(--cf-accent-grad); color: #fff; box-shadow: var(--cf-shadow-glow); }

/* List groups */
.list-group-item-action { transition: background var(--cf-dur) var(--cf-ease); }
.list-group-item-action:hover { background: var(--cf-primary-light); }

/* Thread badges */
.thread-badge { font-weight: 600; border-radius: 99px; padding: .3em .7em; font-size: .72rem; }
.thread-public     { background: var(--cf-primary-light) !important; color: var(--cf-primary-dark) !important; }
.thread-classroom  { background: var(--cf-success-light) !important;  color: #047857 !important; }
.thread-one_on_one { background: #E7F1FB !important;                  color: #0A5AAC !important; }
.reply-card { border-left: 3px solid var(--cf-primary-light); }

/* Thread vote widget (up / score / down) */
.cf-vote {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .1rem;
    flex-shrink: 0;
    width: 42px;
}
.cf-vote form { margin: 0; line-height: 0; }
.cf-vote-btn {
    border: none;
    background: transparent;
    color: var(--cf-text-faint);
    width: 30px; height: 26px;
    border-radius: 8px;
    cursor: pointer;
    font-size: 1.05rem;
    display: flex; align-items: center; justify-content: center;
    transition: background var(--cf-dur-fast) var(--cf-ease), color var(--cf-dur-fast) var(--cf-ease), transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-vote-btn:hover { background: var(--cf-surface-2); color: var(--cf-text); transform: translateY(-1px); }
.cf-vote-btn:active { transform: scale(.9); }
.cf-vote-btn.up-active { color: var(--cf-success); }
.cf-vote-btn.up-active:hover { color: var(--cf-success); }
.cf-vote-btn.down-active { color: var(--cf-danger); }
.cf-vote-btn.down-active:hover { color: var(--cf-danger); }
.cf-vote-score {
    font-family: var(--cf-font-mono);
    font-weight: 700;
    font-size: .95rem;
    line-height: 1;
    color: var(--cf-text);
}
.cf-vote-score.pos { color: var(--cf-success); }
.cf-vote-score.neg { color: var(--cf-danger); }

/* Settings: vertical category nav */
.settings-nav .nav-link {
    color: var(--cf-text-muted);
    border-radius: var(--cf-radius-sm);
    margin-bottom: .15rem;
}
.settings-nav .nav-link:hover { background: var(--cf-primary-light); color: var(--cf-primary); }
.settings-nav .nav-link.active { background: var(--cf-accent-grad); color: #fff; }

/* Classroom join codes */
.code-label {
    font-size: .65rem; font-weight: 700; letter-spacing: .08em;
    color: var(--cf-text-muted); text-transform: uppercase; margin-bottom: .2rem;
}
.code-value {
    font-family: var(--cf-font-mono); font-size: 1.25rem; font-weight: 700; letter-spacing: .18em;
    color: var(--cf-primary-dark); background: var(--cf-primary-light);
    border: 1.5px solid #C3D4FF; border-radius: var(--cf-radius-sm); padding: .25em .65em;
}
.classroom-code-hero {
    font-family: var(--cf-font-mono); font-size: 2rem; font-weight: 800; letter-spacing: .22em;
    color: var(--cf-primary-dark); background: var(--cf-primary-light);
    border: 2px solid #C3D4FF; border-radius: var(--cf-radius); padding: .4em .7em; display: inline-block;
}

/* Solved badge */
.solved-badge { background: var(--cf-success); color: #fff; border-radius: 99px; padding: .35em .8em; font-weight: 600; }

/* Calendar cells */
.cal-cell { transition: transform .1s var(--cf-ease); }
.cal-cell:hover { transform: scale(1.4); opacity: 1; }

/* Search focus ring (override legacy id rule) */
#search-input:focus {
    box-shadow: 0 0 0 4px rgba(17,80,230,.15);
    border-color: var(--cf-primary);
}

/* Selectable choice cards (radio).
   The label has to fill its grid column, otherwise the box's `height: 100%`
   below resolves against an auto-height parent and every card is only as tall
   as its own caption — cards side by side then come out uneven as soon as one
   caption wraps and its neighbour doesn't (which the longer translations do). */
.cf-choice { cursor: pointer; display: block; height: 100%; margin: 0; }
.cf-choice input { position: absolute; opacity: 0; pointer-events: none; }
.cf-choice-box {
    height: 100%;
    border: 1.5px solid var(--cf-border-strong);
    border-radius: var(--cf-radius);
    padding: 1rem 1.1rem;
    transition: border-color var(--cf-dur) var(--cf-ease), background var(--cf-dur) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease), transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-choice:hover .cf-choice-box { border-color: var(--cf-primary); transform: translateY(-2px); }
.cf-choice input:checked + .cf-choice-box {
    border-color: var(--cf-primary);
    background: var(--cf-primary-light);
    box-shadow: 0 0 0 3px rgba(17,80,230,.15);
}
.cf-choice input:focus-visible + .cf-choice-box { box-shadow: 0 0 0 3px rgba(17,80,230,.35); }
.cf-choice-check { color: var(--cf-primary); opacity: 0; transition: opacity var(--cf-dur) var(--cf-ease); }
.cf-choice input:checked + .cf-choice-box .cf-choice-check { opacity: 1; }

/* Language cards (Settings → Design).
   A <button>, not a radio: picking a language submits immediately, so `.is-active`
   plays the part `input:checked` plays for the theme cards above. Kept visually in
   step with .cf-choice-box so the two blocks read as one control group. */
.cf-lang-card {
    display: flex;
    align-items: center;
    gap: .85rem;
    width: 100%;
    height: 100%;
    padding: .9rem 1rem;
    text-align: left;
    cursor: pointer;
    background: transparent;
    color: inherit;
    border: 1.5px solid var(--cf-border-strong);
    border-radius: var(--cf-radius);
    transition: border-color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                box-shadow var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-lang-card:hover { border-color: var(--cf-primary); transform: translateY(-2px); }
.cf-lang-card:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(17,80,230,.35);
}
.cf-lang-card.is-active {
    border-color: var(--cf-primary);
    background: var(--cf-primary-light);
    box-shadow: 0 0 0 3px rgba(17,80,230,.15);
}
/* The active card is already where you are — no lift, no pointer. */
.cf-lang-card.is-active:hover { transform: none; }
.cf-lang-card.is-active { cursor: default; }

.cf-lang-flag {
    font-size: 1.6rem;
    line-height: 1;
    flex-shrink: 0;
}
.cf-lang-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.cf-lang-name {
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cf-lang-code {
    font-size: .72rem;
    letter-spacing: .06em;
    color: var(--cf-text-muted);
}
.cf-lang-card.is-active .cf-lang-code { color: var(--cf-primary); }

.cf-lang-check {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 1.05rem;
    color: var(--cf-primary);
    opacity: 0;
    transition: opacity var(--cf-dur) var(--cf-ease);
}
.cf-lang-card.is-active .cf-lang-check { opacity: 1; }

/* Icon tile used as a button (classroom detail: change icon) */
.cf-icon-tile-btn { border: none; padding: 0; cursor: pointer; position: relative; }
.cf-icon-tile-btn::after {
    content: "\F4CB"; /* bi-pencil-fill */
    font-family: "bootstrap-icons";
    position: absolute; right: -4px; bottom: -4px;
    width: 18px; height: 18px; font-size: .6rem;
    display: flex; align-items: center; justify-content: center;
    background: var(--cf-primary); color: #fff; border-radius: 50%;
    box-shadow: var(--cf-shadow-xs); border: 2px solid var(--cf-surface);
}
.cf-icon-tile-btn:hover { filter: brightness(.97); }

/* Emoji icon picker (classroom create / edit) */
.cf-icon-grid { display: flex; flex-wrap: wrap; gap: .5rem; }
.cf-icon-pick { cursor: pointer; margin: 0; }
.cf-icon-pick input { position: absolute; opacity: 0; pointer-events: none; }
.cf-icon-pick span {
    display: flex; align-items: center; justify-content: center;
    width: 46px; height: 46px; font-size: 1.4rem;
    border: 1.5px solid var(--cf-border-strong);
    border-radius: 12px;
    background: var(--cf-surface);
    transition: border-color var(--cf-dur) var(--cf-ease), background var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease), box-shadow var(--cf-dur) var(--cf-ease);
}
.cf-icon-pick:hover span { border-color: var(--cf-primary); transform: translateY(-2px); }
.cf-icon-pick input:checked + span {
    border-color: var(--cf-primary);
    background: var(--cf-primary-light);
    box-shadow: 0 0 0 3px rgba(17,80,230,.15);
}
.cf-icon-pick input:focus-visible + span { box-shadow: 0 0 0 3px rgba(17,80,230,.35); }

/* Visibility badges */
.cf-vis {
    font-size: .7rem; font-weight: 600; border-radius: 99px;
    padding: .25rem .6rem; display: inline-flex; align-items: center; gap: .3rem;
}
.cf-vis-public  { background: var(--cf-success-light); color: #047857; }
.cf-vis-private { background: var(--cf-warning-light); color: #b45309; }

/* Classroom stat list (sidebar) */
.cf-stat-list { display: flex; flex-direction: column; gap: .5rem; }
.cf-stat-row {
    display: flex; align-items: center; gap: .7rem;
    padding: .55rem .65rem;
    border-radius: var(--cf-radius-sm);
    background: var(--cf-surface-2);
    border: 1px solid var(--cf-border);
    transition: transform var(--cf-dur) var(--cf-ease),
                box-shadow var(--cf-dur) var(--cf-ease),
                border-color var(--cf-dur) var(--cf-ease);
}
.cf-stat-row:hover {
    transform: translateX(3px);
    box-shadow: var(--cf-shadow-md);
    border-color: var(--cf-border-strong);
}
.cf-stat-ico {
    width: 34px; height: 34px; border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem; flex-shrink: 0;
    transition: transform var(--cf-dur) var(--cf-ease-spring);
}
.cf-stat-row:hover .cf-stat-ico { transform: scale(1.12) rotate(-6deg); }
.cf-stat-row-label { font-size: .85rem; color: var(--cf-text-muted); font-weight: 500; }
.cf-stat-row-value {
    margin-left: auto;
    font-family: var(--cf-font-mono);
    font-size: 1.2rem; font-weight: 800;
    line-height: 1; letter-spacing: -.5px;
    color: var(--cf-text);
}

/* ─────────────────────────────────────────────
   16. Search — navbar trigger, per-page bar,
       command-palette modal
   ───────────────────────────────────────────── */

/* ── Navbar master-search trigger (magnifier + ⌘K hint) ── */
.cf-nav-search {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--cf-nav-text);
    background: var(--cf-nav-hover-bg);
    border: 1px solid var(--cf-nav-border);
    border-radius: var(--cf-radius-xs);
    padding: .45rem .5rem;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                border-color var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-nav-search:hover {
    color: var(--cf-primary);
    background: var(--cf-primary-light);
    border-color: var(--cf-primary);
    transform: translateY(-1px);
}
.cf-nav-search:active { transform: translateY(0) scale(.97); }

/* ── Navbar notification bell ── */
.cf-nav-bell {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--cf-nav-text) !important;
    background: var(--cf-nav-hover-bg);
    border: 1px solid var(--cf-nav-border);
    border-radius: var(--cf-radius-xs);
    padding: .45rem .5rem;
    font-size: 1rem;
    line-height: 1;
    transition: color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                border-color var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-nav-bell:hover,
.cf-nav-bell.active {
    color: var(--cf-primary) !important;
    background: var(--cf-primary-light);
    border-color: var(--cf-primary);
    transform: translateY(-1px);
}
.cf-nav-bell-badge {
    position: absolute;
    top: -6px; right: -6px;
    min-width: 18px; height: 18px;
    padding: 0 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--cf-danger);
    color: #fff;
    font-size: .66rem;
    font-weight: 700;
    line-height: 1;
    border-radius: 99px;
    box-shadow: 0 0 0 2px var(--cf-nav-bg-scroll);
    animation: cf-bell-pop var(--cf-dur) var(--cf-ease-spring) both;
}
@keyframes cf-bell-pop { from { transform: scale(0); } to { transform: scale(1); } }
/* On the collapsed mobile menu the bell sits inline with a text label.
   Matches the navbar's xl collapse breakpoint (hamburger below 1200px). */
@media (max-width: 1199.98px) {
    .cf-nav-bell { width: auto; gap: .4rem; }
    .cf-nav-bell-badge { position: static; box-shadow: none; margin-left: .25rem; }
}

/* ── Activity feed / notifications ── */
.cf-feed-list { padding: 0; }
.cf-feed-item {
    display: flex;
    align-items: flex-start;
    gap: .85rem;
    padding: .8rem 1rem;
    border-bottom: 1px solid var(--cf-border);
    color: inherit;
    text-decoration: none;
    transition: background var(--cf-dur-fast) var(--cf-ease);
}
.cf-feed-item:last-child { border-bottom: 0; }
.cf-feed-item:hover { background: var(--cf-surface-2); }
.cf-feed-item.is-new { background: var(--cf-primary-light); }
.cf-feed-item.is-new:hover { background: color-mix(in srgb, var(--cf-primary-light) 82%, var(--cf-primary)); }

.cf-feed-ico {
    flex-shrink: 0;
    width: 38px; height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    font-size: 1rem;
    background: var(--cf-primary-light);
    color: var(--cf-primary);
}
.cf-feed-follow .cf-feed-ico,
.cf-feed-friend_request .cf-feed-ico,
.cf-feed-friend_accept .cf-feed-ico { background: var(--cf-primary-light); color: var(--cf-primary); }

/* Social notifications show the actor's profile picture instead of a type icon.
   Works for both an uploaded image and the initials-span fallback. */
.cf-feed-avatar {
    flex-shrink: 0;
    width: 38px; height: 38px;
    border-radius: 50%;
    object-fit: cover;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--cf-accent-grad);
    color: #fff;
    font-weight: 700;
    font-size: 1rem;
}
.cf-feed-assignment .cf-feed-ico   { background: var(--cf-warning-light); color: #b45309; }
.cf-feed-thread_new .cf-feed-ico,
.cf-feed-thread_reply .cf-feed-ico { background: var(--cf-success-light); color: var(--cf-success); }

.cf-feed-body { min-width: 0; flex: 1; }
.cf-feed-text {
    display: block;
    color: var(--cf-text);
    line-height: 1.35;
    font-size: .92rem;
}
.cf-feed-time {
    display: block;
    color: var(--cf-text-muted);
    font-size: .76rem;
    margin-top: .15rem;
    font-family: var(--cf-font-mono);
}
.cf-feed-dot {
    flex-shrink: 0;
    align-self: center;
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--cf-primary);
    box-shadow: 0 0 0 3px var(--cf-primary-light);
}
.cf-feed-archived { opacity: .72; }

/* ── Per-page search bar (in normal flow — scrolls away with the page) ── */
.cf-page-search {
    position: static;
    background: rgba(246,247,251,.82);
    backdrop-filter: saturate(160%) blur(12px);
    -webkit-backdrop-filter: saturate(160%) blur(12px);
    border-bottom: 1px solid var(--cf-border);
    padding: .8rem 0;
    animation: cf-rise var(--cf-dur) var(--cf-ease-out) both;
}
.cf-page-search-inner {
    position: relative;
    display: flex;
    align-items: center;
    background: var(--cf-surface);
    border: 1.5px solid var(--cf-border-strong);
    border-radius: var(--cf-radius);
    box-shadow: var(--cf-shadow-sm, var(--cf-shadow));
    transition: border-color var(--cf-dur) var(--cf-ease),
                box-shadow var(--cf-dur) var(--cf-ease);
}
.cf-page-search-inner:focus-within {
    border-color: var(--cf-primary);
    box-shadow: 0 0 0 4px rgba(17,80,230,.15);
}
.cf-page-search-ico {
    position: absolute;
    left: 1rem;
    color: var(--cf-text-faint);
    font-size: 1.05rem;
    pointer-events: none;
    transition: color var(--cf-dur) var(--cf-ease);
}
.cf-page-search-inner:focus-within .cf-page-search-ico { color: var(--cf-primary); }
.cf-page-search-input {
    flex: 1;
    border: none;
    outline: none;
    background: transparent;
    color: var(--cf-text);
    font-family: var(--cf-font);
    font-size: 1rem;
    padding: .75rem 2.6rem;
    border-radius: var(--cf-radius);
}
.cf-page-search-input::placeholder { color: var(--cf-text-faint); }
.cf-page-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.cf-page-search-clear {
    position: absolute;
    right: .55rem;
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    border: none;
    background: var(--cf-surface-2);
    color: var(--cf-text-muted);
    border-radius: 50%;
    font-size: .8rem;
    cursor: pointer;
    opacity: 0;
    transform: scale(.6);
    pointer-events: none;
    transition: opacity var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur) var(--cf-ease-spring),
                background var(--cf-dur) var(--cf-ease),
                color var(--cf-dur) var(--cf-ease);
}
.cf-page-search.is-filled .cf-page-search-clear {
    opacity: 1;
    transform: scale(1);
    pointer-events: auto;
}
.cf-page-search-clear:hover {
    background: var(--cf-danger-light);
    color: var(--cf-danger);
}

/* Filterable item hide/show animation */
.cf-search-item {
    transition: opacity var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur) var(--cf-ease);
}
.cf-search-item.cf-search-hidden {
    opacity: 0;
    transform: translateY(-6px) scale(.98);
    /* Collapse out of flow once faded so the list closes up smoothly */
    display: none;
}

/* Per-page empty state */
.cf-page-search-empty {
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--cf-text-muted);
    animation: cf-rise var(--cf-dur) var(--cf-ease-out) both;
}
.cf-page-search-empty .fs-5 { color: var(--cf-text); }
.cf-pse-term { color: var(--cf-primary); font-weight: 700; }

/* ── Pagination control (shared partial) ── */
.cf-pagination {
    display: flex;
    justify-content: center;
    margin-top: 2rem;
}
.cf-pagination-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    list-style: none;
    padding: 0;
    margin: 0;
}
.cf-page-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    height: 40px;
    padding: 0 .7rem;
    border: 1.5px solid var(--cf-border-strong);
    border-radius: var(--cf-radius-sm);
    background: var(--cf-surface);
    color: var(--cf-text);
    font-size: .9rem;
    font-weight: 600;
    font-family: var(--cf-font);
    text-decoration: none;
    cursor: pointer;
    transition: color var(--cf-dur) var(--cf-ease),
                background var(--cf-dur) var(--cf-ease),
                border-color var(--cf-dur) var(--cf-ease),
                box-shadow var(--cf-dur) var(--cf-ease),
                transform var(--cf-dur-fast) var(--cf-ease);
}
.cf-page-btn:hover:not(.is-active):not(.is-disabled) {
    color: var(--cf-primary);
    border-color: var(--cf-primary);
    background: var(--cf-primary-light);
    transform: translateY(-2px);
    box-shadow: var(--cf-shadow-sm, var(--cf-shadow));
}
.cf-page-btn:active:not(.is-active):not(.is-disabled) { transform: translateY(0) scale(.96); }
.cf-page-btn.is-active {
    background: var(--cf-accent-grad);
    border-color: transparent;
    color: #fff;
    box-shadow: var(--cf-shadow-glow);
    cursor: default;
}
.cf-page-btn.is-disabled {
    opacity: .45;
    pointer-events: none;
    cursor: default;
}
.cf-page-arrow { font-weight: 700; }
.cf-page-ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 40px;
    color: var(--cf-text-faint);
    font-weight: 700;
    user-select: none;
}
@media (max-width: 575.98px) {
    .cf-pagination-list { gap: .3rem; }
    .cf-page-btn { min-width: 36px; height: 36px; padding: 0 .5rem; font-size: .85rem; }
    .cf-page-ellipsis { min-width: 20px; height: 36px; }
}

/* ── Command palette (master search modal) ── */
.cf-cmdk {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: clamp(1rem, 12vh, 9rem) 1rem 1rem;
}
.cf-cmdk[hidden] { display: none; }
.cf-cmdk-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(11,16,32,.55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    opacity: 0;
    transition: opacity var(--cf-dur) var(--cf-ease);
}
.cf-cmdk.is-open .cf-cmdk-backdrop { opacity: 1; }
.cf-cmdk-panel {
    position: relative;
    width: 100%;
    max-width: 640px;
    background: var(--cf-surface);
    border: 1px solid var(--cf-border);
    border-radius: var(--cf-radius-lg);
    box-shadow: var(--cf-shadow-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-height: min(70vh, 620px);
    opacity: 0;
    transform: translateY(-14px) scale(.97);
    transition: opacity var(--cf-dur) var(--cf-ease-out),
                transform var(--cf-dur) var(--cf-ease-spring);
}
.cf-cmdk.is-open .cf-cmdk-panel { opacity: 1; transform: translateY(0) scale(1); }
.cf-cmdk-header {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: 1rem 1.15rem;
    border-bottom: 1px solid var(--cf-border);
}
.cf-cmdk-ico { color: var(--cf-primary); font-size: 1.2rem; flex-shrink: 0; }
.cf-cmdk-input {
    flex: 1;
    border: none;
    outline: none;
    background: transparent;
    color: var(--cf-text);
    font-family: var(--cf-font);
    font-size: 1.1rem;
    font-weight: 500;
}
.cf-cmdk-input::placeholder { color: var(--cf-text-faint); font-weight: 400; }
.cf-cmdk-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.cf-cmdk-esc {
    font-family: var(--cf-font-mono);
    font-size: .68rem;
    font-weight: 600;
    color: var(--cf-text-muted);
    background: var(--cf-surface-2);
    border: 1px solid var(--cf-border);
    border-radius: 6px;
    padding: .15rem .45rem;
    flex-shrink: 0;
}
.cf-cmdk-body {
    overflow-y: auto;
    padding: .5rem;
    flex: 1;
}
.cf-cmdk-group-label {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--cf-text-muted);
    padding: .7rem .75rem .35rem;
}
.cf-cmdk-item {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .6rem .75rem;
    border-radius: var(--cf-radius-sm);
    color: var(--cf-text);
    cursor: pointer;
    scroll-margin: .5rem;
    transition: background var(--cf-dur-fast) var(--cf-ease);
}
.cf-cmdk-item:hover,
.cf-cmdk-item.is-active {
    background: var(--cf-primary-light);
    color: var(--cf-text);
}
.cf-cmdk-item.is-active { box-shadow: inset 0 0 0 1.5px rgba(17,80,230,.35); }
.cf-cmdk-item-ico {
    width: 34px; height: 34px;
    flex-shrink: 0;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1rem;
    background: var(--cf-surface-2);
    border: 1px solid var(--cf-border);
}
.cf-cmdk-item.is-active .cf-cmdk-item-ico,
.cf-cmdk-item:hover .cf-cmdk-item-ico {
    background: #fff;
    border-color: #C3D4FF;
    color: var(--cf-primary);
}
.cf-cmdk-item-body { min-width: 0; flex: 1; }
.cf-cmdk-item-title {
    font-weight: 600;
    font-size: .92rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cf-cmdk-item-sub {
    font-size: .76rem;
    color: var(--cf-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cf-cmdk-item-arrow {
    color: var(--cf-text-faint);
    font-size: .8rem;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity var(--cf-dur) var(--cf-ease), transform var(--cf-dur) var(--cf-ease);
}
.cf-cmdk-item.is-active .cf-cmdk-item-arrow,
.cf-cmdk-item:hover .cf-cmdk-item-arrow { opacity: 1; transform: translateX(0); }
.cf-cmdk-state {
    padding: 2.75rem 1.5rem;
    text-align: center;
    color: var(--cf-text-muted);
}
.cf-cmdk-state-ico { font-size: 2rem; display: block; margin-bottom: .5rem; }
.cf-cmdk-hint b { color: var(--cf-text); }
.cf-cmdk-spinner {
    width: 26px; height: 26px;
    margin: 0 auto .6rem;
    border: 3px solid var(--cf-border);
    border-top-color: var(--cf-primary);
    border-radius: 50%;
    animation: cf-spin .7s linear infinite;
}
@keyframes cf-spin { to { transform: rotate(360deg); } }
.cf-cmdk-footer {
    display: flex;
    gap: 1.1rem;
    padding: .6rem 1.15rem;
    border-top: 1px solid var(--cf-border);
    background: var(--cf-surface-2);
    font-size: .72rem;
    color: var(--cf-text-muted);
}
.cf-cmdk-footer kbd {
    font-family: var(--cf-font-mono);
    font-size: .66rem;
    background: var(--cf-surface);
    border: 1px solid var(--cf-border);
    border-radius: 5px;
    padding: .05rem .3rem;
    margin: 0 .1rem;
    color: var(--cf-text-muted);
}
.cf-cmdk-mark { background: rgba(17,80,230,.18); color: inherit; border-radius: 3px; padding: 0 .1em; }

/* ── Responsive: full-screen master search on mobile ── */
@media (max-width: 575.98px) {
    .cf-cmdk { padding: 0; }
    .cf-cmdk-panel {
        max-width: none;
        height: 100dvh;
        max-height: 100dvh;
        border-radius: 0;
        border: none;
    }
}

/* ─────────────────────────────────────────────
   17. Reduced motion
   ───────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-delay: 0ms !important;
        transition-duration: .001ms !important;
        transition-delay: 0ms !important;
    }
    .reveal { opacity: 1 !important; transform: none !important; }
    .cf-hero-blob { animation: none !important; }
}

/* ─────────────────────────────────────────────
   16. Dark mode
   Bootstrap components switch via data-bs-theme="dark";
   here we re-map the custom --cf-* tokens and patch the
   few components that use hardcoded light colours.
   ───────────────────────────────────────────── */
[data-bs-theme="dark"] {
    --cf-primary:        #5A8CFF;   /* lightened Semos blue for contrast on navy */
    --cf-primary-dark:   #93B4FF;   /* used as text on tints → lightened */
    --cf-primary-light:  rgba(90,140,255,.16);

    --cf-secondary:      #4C9AEA;
    --cf-secondary-dark: #7CB6F0;
    --cf-secondary-light:rgba(76,154,234,.16);
    --cf-violet:         var(--cf-secondary);

    /* Bootstrap primary + links, dark-theme values */
    --bs-primary:              #5A8CFF;
    --bs-primary-rgb:          90, 140, 255;
    --bs-primary-text-emphasis:#BBD0FF;
    --bs-primary-bg-subtle:    #16224A;
    --bs-primary-border-subtle:#2A3C6E;
    --bs-link-color:           #7CB6F0;
    --bs-link-color-rgb:       124, 182, 240;
    --bs-link-hover-color:     #A9CFF5;
    --bs-link-hover-color-rgb: 169, 207, 245;

    --cf-success:        #34d399;
    --cf-success-light:  rgba(52,211,153,.16);
    --cf-warning:        #fbbf24;
    --cf-warning-light:  rgba(251,191,36,.16);
    --cf-danger:         #fb7185;
    --cf-danger-light:   rgba(251,113,133,.16);
    --cf-info:           #60a5fa;

    --cf-bg:             #0F1420;
    --cf-surface:        #171D2B;
    --cf-surface-2:      #202840;
    --cf-text:           #E8EBF2;
    --cf-text-muted:     #9AA3B7;
    --cf-text-faint:     #6B7492;
    --cf-border:         #2A3350;
    --cf-border-strong:  #3A466B;

    /* Dark navbar (glass) */
    --cf-nav-bg:         rgba(15,20,32,.72);
    --cf-nav-bg-scroll:  rgba(15,20,32,.94);
    --cf-nav-border:     rgba(255,255,255,.09);
    --cf-nav-shadow:     0 8px 30px -10px rgba(0,0,0,.55);
    --cf-nav-text:       #9AA3B7;
    --cf-nav-text-hover: #ffffff;
    --cf-nav-hover-bg:   rgba(255,255,255,.06);
    --cf-nav-brand:      #ffffff;

    /* Dark footer (deep navy) */
    --cf-footer-bg:          #0F1420;
    --cf-footer-border:      rgba(255,255,255,.09);
    --cf-footer-text:        #9AA3B7;
    --cf-footer-head:        #ffffff;
    --cf-footer-link:        #9AA3B7;
    --cf-footer-link-hover:  #ffffff;
    --cf-footer-chip-bg:     rgba(255,255,255,.06);
    --cf-footer-chip-border: rgba(255,255,255,.09);
    --cf-footer-chip-text:   #9AA3B7;

    --cf-card-shadow:    0 1px 3px rgba(0,0,0,.45);
    --cf-shadow-xs:      0 1px 2px rgba(0,0,0,.4);
    --cf-shadow:         0 1px 3px rgba(0,0,0,.45), 0 1px 2px rgba(0,0,0,.3);
    --cf-shadow-md:      0 8px 24px -6px rgba(0,0,0,.55);
    --cf-shadow-lg:      0 20px 48px -12px rgba(0,0,0,.65);
    --cf-shadow-glow:    0 8px 28px -6px rgba(90,140,255,.4);

    color-scheme: dark;
}

/* Body glow tuned for dark */
[data-bs-theme="dark"] body {
    background-image:
        radial-gradient(900px 500px at 100% -5%, rgba(10,102,194,.14), transparent 60%),
        radial-gradient(800px 500px at -10% 0%, rgba(17,80,230,.12), transparent 55%);
}

/* Utility helpers that ship a fixed light colour */
[data-bs-theme="dark"] .bg-white { background-color: var(--cf-surface) !important; color: var(--cf-text); }
[data-bs-theme="dark"] .text-dark { color: var(--cf-text) !important; }

/* .bg-light / .bg-warning never re-theme (they stay literally light), so any
   element pairing them with .text-dark must keep dark text — otherwise the
   generic .text-dark rule above makes it light-on-light and unreadable
   (e.g. the @username pill on the profile header). Higher specificity wins. */
[data-bs-theme="dark"] .bg-light.text-dark,
[data-bs-theme="dark"] .bg-warning.text-dark { color: #1f2937 !important; }

/* Tag/utility badges built on .bg-light (e.g. catalogue problem tags) keep a
   fixed light bg → re-tint to a dark surface so they're not white-on-dark. */
[data-bs-theme="dark"] .badge.bg-light {
    background-color: var(--cf-surface-2) !important;
    color: var(--cf-text-muted) !important;
    border-color: var(--cf-border) !important;
}

/* .table-light headers (catalogue "Type/Language/Difficulty" row) stay light
   in dark Bootstrap → map the table vars onto dark surfaces. */
[data-bs-theme="dark"] .table-light,
[data-bs-theme="dark"] .table-light > th,
[data-bs-theme="dark"] .table-light > td {
    --bs-table-bg: var(--cf-surface-2);
    --bs-table-color: var(--cf-text-muted);
    --bs-table-border-color: var(--cf-border);
    background-color: var(--cf-surface-2);
    color: var(--cf-text-muted);
}

/* Alerts */
[data-bs-theme="dark"] .alert-success { background: rgba(52,211,153,.14);  color: #6ee7b7; border-color: rgba(52,211,153,.32); }
[data-bs-theme="dark"] .alert-danger  { background: rgba(251,113,133,.14); color: #fda4af; border-color: rgba(251,113,133,.32); }
[data-bs-theme="dark"] .alert-warning { background: rgba(251,191,36,.14);  color: #fcd34d; border-color: rgba(251,191,36,.32); }
[data-bs-theme="dark"] .alert-info    { background: rgba(96,165,250,.14);  color: #93c5fd; border-color: rgba(96,165,250,.32); }

/* Difficulty badges — keep tinted bg, lift text contrast */
[data-bs-theme="dark"] .badge-diff-easy,
[data-bs-theme="dark"] .badge-easy         { color: #6ee7b7 !important; }
[data-bs-theme="dark"] .badge-diff-intermediate { background: rgba(103,232,249,.15) !important; color: #67e8f9 !important; }
[data-bs-theme="dark"] .badge-diff-medium,
[data-bs-theme="dark"] .badge-medium       { color: #fcd34d !important; }
[data-bs-theme="dark"] .badge-diff-hard,
[data-bs-theme="dark"] .badge-hard         { color: #fda4af !important; }
[data-bs-theme="dark"] .badge-diff-extreme { background: rgba(61,139,224,.16) !important; color: #8FC0F0 !important; }

/* Role badges */
[data-bs-theme="dark"] .role-badge.role-admin   { color: #fda4af; }
[data-bs-theme="dark"] .role-badge.role-teacher { color: #8FC0F0; }
[data-bs-theme="dark"] .role-badge.role-student { color: #6ee7b7; }

/* Visibility badges */
[data-bs-theme="dark"] .cf-vis-public  { color: #6ee7b7; }
[data-bs-theme="dark"] .cf-vis-private { color: #fcd34d; }

/* Thread badges */
[data-bs-theme="dark"] .thread-classroom  { color: #6ee7b7 !important; }
[data-bs-theme="dark"] .thread-one_on_one { background: rgba(61,139,224,.18) !important; color: #8FC0F0 !important; }

/* Language badge & classroom codes have hardcoded light borders */
[data-bs-theme="dark"] .lang-badge,
[data-bs-theme="dark"] .code-value,
[data-bs-theme="dark"] .classroom-code-hero { border-color: rgba(90,140,255,.35); }

/* Highlighted table row (leaderboard "you") — Bootstrap's .table-warning forces
   a fixed dark text colour, so re-map the table vars to keep the name readable. */
[data-bs-theme="dark"] .table-warning,
[data-bs-theme="dark"] .table-warning > td,
[data-bs-theme="dark"] .table-warning > th {
    --bs-table-color: var(--cf-text);
    --bs-table-color-state: var(--cf-text);
    background-color: rgba(90,140,255,.14) !important;
    color: var(--cf-text) !important;
}

/* Plain .btn-primary hover stays saturated (not the light token) */
[data-bs-theme="dark"] .btn-primary:hover,
[data-bs-theme="dark"] .btn-primary:focus { background: #1150E6; }

/* Per-page search band ships a fixed light frosted bg → re-tint for dark */
[data-bs-theme="dark"] .cf-page-search {
    background: rgba(11,16,32,.82);
    border-bottom-color: var(--cf-border);
}
/* Focus ring uses a hardcoded indigo glow → lift for the lighter dark accent */
[data-bs-theme="dark"] .cf-page-search-inner:focus-within {
    box-shadow: 0 0 0 4px rgba(90,140,255,.22);
}

/* Command-palette active/hover icon is hardcoded #fff → tint for dark */
[data-bs-theme="dark"] .cf-cmdk-item.is-active .cf-cmdk-item-ico,
[data-bs-theme="dark"] .cf-cmdk-item:hover .cf-cmdk-item-ico {
    background: var(--cf-surface);
    border-color: rgba(90,140,255,.45);
    color: var(--cf-primary);
}

/* Hint boxes ship a fixed light-yellow bg → amber tint on dark */
[data-bs-theme="dark"] .hint-item .hint-body {
    background: rgba(251,191,36,.10);
    border-color: rgba(251,191,36,.30);
    color: var(--cf-text);
}

/* Profile badges — earned cards & the pinned pill ship fixed light gradients,
   so re-tint them onto dark violet surfaces for dark mode. */
[data-bs-theme="dark"] .cf-badge.is-earned {
    background: linear-gradient(160deg, var(--cf-surface), rgba(90,140,255,.10));
    border-color: rgba(90,140,255,.30);
}
[data-bs-theme="dark"] .cf-pinned-badge {
    color: #8FC0F0;
    background: linear-gradient(135deg, rgba(10,102,194,.22), rgba(10,102,194,.22));
    border-color: rgba(61,139,224,.45);
}

/* ─────────────────────────────────────────────
   18. Responsive & device adaptation
   Phones → tablets → laptops → ultrawide → projectors.
   Base type is already fluid (html font-size clamp above); these
   rules add container caps, comfortable touch sizing, and overflow-
   safe tables/tabs on top of Bootstrap's responsive grid. Nothing
   here overrides colours, so light/dark modes are unaffected.
   ───────────────────────────────────────────── */

/* ── Ultrawide: let the capped container use more of the screen ──
   Bootstrap caps .container at 1320px (≥1400px). On 1920px / 2560px /
   4K monitors that wastes space, so widen the cap progressively while
   keeping content centred and readable. Card grids add a 4th column at
   xxl (col-xxl-*) in the templates to fill the extra width. */
@media (min-width: 1600px) { .container { max-width: 1440px; } }
@media (min-width: 1920px) { .container { max-width: 1600px; } }
@media (min-width: 2560px) { .container { max-width: 1800px; } }

/* Scale the page rhythm up a touch on very large screens/projectors */
@media (min-width: 1920px) {
    main.container { padding-top: 2.75rem; padding-bottom: 2.75rem; }
    .cf-footer { margin-top: 5rem; }
}

/* Keep a wrapped table's scroll area inside the card's rounded corners */
.cf-card > .table-responsive { border-radius: inherit; }

/* ── Tabs stay on one scrollable line on narrow screens instead of
   wrapping into a messy stack (problem page, classroom detail). ── */
@media (max-width: 575.98px) {
    .nav-tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
    }
    .nav-tabs::-webkit-scrollbar { height: 0; }
    .nav-tabs .nav-item { flex-shrink: 0; }
    .nav-tabs .nav-link { white-space: nowrap; }
}

/* ── Collapsed navbar (below the xl breakpoint): scroll if the open
   menu is taller than the viewport (e.g. landscape phones / tablets
   showing every nav item). ── */
@media (max-width: 1199.98px) {
    #navMenu {
        max-height: calc(100dvh - 64px);
        overflow-y: auto;
    }
}

/* ── Profile header avatar scales down on phones so the name and
   action buttons keep room; capped at the original 124px. ── */
@media (max-width: 575.98px) {
    .profile-avatar {
        width: clamp(76px, 22vw, 124px);
        height: clamp(76px, 22vw, 124px);
        font-size: 2rem;
    }
    .profile-header .card-body.d-flex { gap: 1rem !important; }
}

/* ── Touch devices: guarantee comfortable ≥44px tap targets (Apple
   HIG / Material). Scoped to coarse pointers so the mouse/desktop look
   is untouched. ── */
@media (hover: none) and (pointer: coarse) {
    .btn,
    .cf-nav-link,
    .cf-nav-search,
    .cf-nav-bell,
    .cf-user-trigger,
    .cf-user-item,
    .cf-range-tab,
    .cf-sort-btn,
    .cf-page-btn,
    .category-pill,
    .nav-tabs .nav-link,
    .nav-pills .nav-link,
    .page-link {
        min-height: 44px;
    }
    .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    /* Icon-only utility buttons get a real hit area */
    .cf-vote-btn { width: 40px; height: 40px; }
    .cf-page-search-clear { width: 40px; height: 40px; }
}

/* ── Dark mode: profile progress ring, difficulty rows & skills ── */
[data-bs-theme="dark"] .cf-ring-track { stroke: rgba(255, 255, 255, .08); }
[data-bs-theme="dark"] .cf-ring-num,
[data-bs-theme="dark"] .cf-diff-count,
[data-bs-theme="dark"] .cf-stat-val { color: var(--cf-text, #e5e7eb); }
[data-bs-theme="dark"] .cf-diff-total { color: var(--cf-text-muted, #9ca3af); }
[data-bs-theme="dark"] .cf-stat-tile {
    background: rgba(255, 255, 255, .04);
    border-color: rgba(255, 255, 255, .09);
}
[data-bs-theme="dark"] .cf-bar { background: rgba(255, 255, 255, .09); }
[data-bs-theme="dark"] .cf-diff-row:hover,
[data-bs-theme="dark"] .cf-cat-row:hover { background: rgba(255, 255, 255, .06); }
[data-bs-theme="dark"] .cf-cat-scroll::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .18);
}
[data-bs-theme="dark"] .cf-skill-tier { color: var(--cf-text-muted, #9ca3af); }
[data-bs-theme="dark"] .cf-skill-chip {
    background: rgba(255, 255, 255, .07);
    color: var(--cf-text, #e5e7eb);
}

/* ─────────────────────────────────────────────
   19. Feedback & reward motion
   The reveal/hover vocabulary in §13 is ambient — it plays on every page,
   for everything. This section is the opposite: it only fires at the
   moments the app owes the user a reaction (a verdict, a score, a streak),
   so it is allowed to be louder. Keep it that way; if a rule here starts
   showing up on an idle page, it belongs in §13 instead.

   §17's reduced-motion block already flattens every animation-duration
   below via `*`, so nothing here needs its own media query. The two
   exceptions — where an element's *resting* state is invisible and only
   an animation reveals it — carry an explicit override at the end.
   ───────────────────────────────────────────── */

/* ── Shared keyframes ── */
@keyframes cf-pop {                       /* spring entrance for badges / icons */
    0%   { opacity: 0; transform: scale(.5); }
    60%  { opacity: 1; transform: scale(1.12); }
    100% { opacity: 1; transform: scale(1); }
}
@keyframes cf-drop-in {                   /* banners & flashes arriving from above */
    from { opacity: 0; transform: translateY(-12px) scale(.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes cf-shake {
    10%, 90% { transform: translateX(-2px); }
    20%, 80% { transform: translateX(3px); }
    30%, 50%, 70% { transform: translateX(-6px); }
    40%, 60% { transform: translateX(6px); }
}
@keyframes cf-glow-ok {                   /* one green breath around an Accepted verdict */
    0%   { box-shadow: 0 0 0 0 rgba(18, 161, 80, .40); }
    70%  { box-shadow: 0 0 0 12px rgba(18, 161, 80, 0); }
    100% { box-shadow: 0 0 0 0 rgba(18, 161, 80, 0); }
}
@keyframes cf-draw { to { stroke-dashoffset: 0; } }   /* SVG tick / cross "writes" itself */
@keyframes cf-shimmer { to { background-position: 200% 0; } }
@keyframes cf-flame {                     /* streak emoji flicker */
    0%, 100% { transform: scale(1) rotate(-2deg);   filter: brightness(1); }
    25%      { transform: scale(1.08) rotate(2deg); filter: brightness(1.15); }
    50%      { transform: scale(.96) rotate(-1deg); filter: brightness(.95); }
    75%      { transform: scale(1.05) rotate(1deg); filter: brightness(1.1); }
}
@keyframes cf-sweep-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Confetti canvas — sits above the page, never intercepts a click. */
.cf-confetti-canvas {
    position: fixed;
    inset: 0;
    z-index: 3000;
    pointer-events: none;
}

/* ─────────────────────────────────────────────
   19a. Problem page — the verdict moment
   ───────────────────────────────────────────── */

/* Indeterminate strip while the judge runs. Replaces "Submitting…" as the
   only signal that something is happening. */
.cf-judging {
    height: 3px;
    border-radius: 99px;
    margin: 0 0 .75rem;
    background: var(--cf-surface-2);
    overflow: hidden;
    position: relative;
}
.cf-judging::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent 0%, var(--cf-primary) 35%, var(--cf-primary) 65%, transparent 100%);
    background-size: 200% 100%;
    animation: cf-shimmer 1.1s linear infinite;
}
.cf-judging[hidden] { display: none; }

/* The banner itself. .is-ok / .is-bad carry the whole colour story so the
   JS only picks a class. */
.cf-verdict {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .7rem .9rem;
    border-radius: var(--cf-radius-sm);
    border: 1.5px solid transparent;
    font-weight: 700;
    animation: cf-drop-in var(--cf-dur) var(--cf-ease-spring) both;
}
.cf-verdict-ico { flex-shrink: 0; display: flex; }
.cf-verdict-text { min-width: 0; }
.cf-verdict-sub {
    display: block;
    font-weight: 500;
    font-size: .8rem;
    opacity: .85;
    margin-top: .1rem;
}
.cf-verdict.is-ok {
    background: var(--cf-success-light);
    border-color: color-mix(in srgb, var(--cf-success) 40%, transparent);
    color: var(--cf-success);
    /* Entrance first, then a single glow breath — no infinite pulsing. */
    animation: cf-drop-in var(--cf-dur) var(--cf-ease-spring) both,
               cf-glow-ok 1.1s var(--cf-ease-out) var(--cf-dur) 2;
}
.cf-verdict.is-bad {
    background: var(--cf-danger-light);
    border-color: color-mix(in srgb, var(--cf-danger) 40%, transparent);
    color: var(--cf-danger);
    animation: cf-drop-in var(--cf-dur) var(--cf-ease-spring) both,
               cf-shake .4s var(--cf-ease) var(--cf-dur) 1;
}
.cf-verdict.is-neutral {
    background: var(--cf-surface-2);
    border-color: var(--cf-border);
    color: var(--cf-text);
}

/* The pass/fail glyph draws itself in. Each <path> declares its own length in
   --len (a rough arc-length, in viewBox units); cf-draw runs the offset to 0.
   The cross's two strokes are separate paths so the second can trail the first. */
.cf-tick path {
    stroke-dasharray: var(--len, 40);
    stroke-dashoffset: var(--len, 40);
    animation: cf-draw .4s var(--cf-ease-out) .1s forwards;
}
.cf-tick path:nth-of-type(2) { animation-delay: .24s; }

/* One result row per test case. --i staggers them in as the list renders. */
.cf-test-row {
    padding: .1rem 0 .1rem .6rem;
    margin-bottom: .5rem;
    border-left: 3px solid var(--cf-border-strong);
    animation: cf-rise .35s var(--cf-ease-out) both;
    /* Cap the stagger: a 40-case problem must not take 4s to finish drawing. */
    animation-delay: calc(min(var(--i, 0), 12) * 45ms);
}
.cf-test-row.is-pass { border-left-color: var(--cf-success); }
.cf-test-row.is-fail { border-left-color: var(--cf-danger); }
.cf-test-head { display: flex; align-items: center; gap: .4rem; font-size: .875rem; font-weight: 600; }
.cf-test-row.is-pass .cf-test-verdict { color: var(--cf-success); }
.cf-test-row.is-fail .cf-test-verdict { color: var(--cf-danger); }
.cf-test-detail { font-size: .875rem; font-family: var(--cf-font-mono); margin-top: .25rem; }

/* Failed-case diff: expected/actual keep their line structure and the lines
   that differ get tinted (green = what was expected, red = what came out). */
.cf-diff-pre { white-space: pre-wrap; word-break: break-word; display: inline-block; vertical-align: top; margin-left: .35em; }
.cf-diff-ins { background: rgba(16, 185, 129, .16); border-radius: 3px; }
.cf-diff-del { background: rgba(239, 68, 68, .16);  border-radius: 3px; }

/* "✓ Solved" springing in the moment the problem is first cleared. */
.solved-badge.is-fresh { animation: cf-pop .5s var(--cf-ease-spring) both; }

/* ─────────────────────────────────────────────
   19b. Quiz — score ring & result badges
   ───────────────────────────────────────────── */
.cf-score-ring {
    position: relative;
    width: 132px;
    height: 132px;
    flex-shrink: 0;
}
.cf-score-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.cf-score-ring-track { fill: none; stroke: var(--cf-surface-2); stroke-width: 10; }
.cf-score-ring-fill {
    fill: none;
    stroke-width: 10;
    stroke-linecap: round;
    stroke: var(--cf-primary);
    /* --circ (full circumference) and --dash (the offset that leaves the score
       showing) are rendered inline by the template. */
    stroke-dasharray: var(--circ);
    stroke-dashoffset: var(--circ);
    animation: cf-ring-fill 1.1s var(--cf-ease-out) .15s forwards;
}
@keyframes cf-ring-fill { to { stroke-dashoffset: var(--dash); } }
.cf-score-ring.is-pass    .cf-score-ring-fill { stroke: var(--cf-success); }
.cf-score-ring.is-fail    .cf-score-ring-fill { stroke: var(--cf-danger); }
.cf-score-ring.is-pending .cf-score-ring-fill { stroke: var(--cf-warning); }

.cf-score-ring-body {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
.cf-score-num {
    font-family: var(--cf-font-mono);
    font-size: 2.1rem;
    font-weight: 800;
    letter-spacing: -1px;
    color: var(--cf-text);
}
.cf-score-den { font-size: .82rem; color: var(--cf-text-muted); margin-top: .25rem; }

/* Result badges (pass / fail / pending, and the per-question ones) pop in,
   staggered behind their card's own reveal. */
.cf-result-badge { animation: cf-pop .45s var(--cf-ease-spring) .35s both; }
.cf-qbadge       { animation: cf-pop .4s var(--cf-ease-spring) both;
                   animation-delay: calc(.25s + min(var(--i, 0), 10) * 80ms); }

/* ─────────────────────────────────────────────
   19c. Quiz take — choices & progress
   ───────────────────────────────────────────── */
/* A denser .cf-choice-box for answer options — the stock padding is tuned for
   the big settings cards. */
.cf-choice-sm .cf-choice-box {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .85rem;
}
.cf-choice-letter {
    font-weight: 700;
    min-width: 1.3rem;
    color: var(--cf-text-muted);
    transition: color var(--cf-dur) var(--cf-ease);
}
.cf-choice input:checked + .cf-choice-box .cf-choice-letter { color: var(--cf-primary); }
.cf-choice-check { margin-left: auto; }
/* Selecting an option is a small commitment — acknowledge it. */
.cf-choice input:checked + .cf-choice-box .cf-choice-check { animation: cf-pop .32s var(--cf-ease-spring) both; }

.cf-quiz-progress {
    position: sticky;
    top: 76px;
    z-index: 5;
    background: var(--cf-surface);
    border: 1px solid var(--cf-border);
    border-radius: var(--cf-radius);
    box-shadow: var(--cf-shadow-md);
    padding: .7rem .95rem;
    margin-top: 1.5rem;
}
.cf-quiz-progress-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    font-size: .85rem;
    font-weight: 600;
    color: var(--cf-text-muted);
    margin-bottom: .45rem;
}
.cf-quiz-progress-pct { font-family: var(--cf-font-mono); color: var(--cf-primary); }
.cf-quiz-progress-track {
    height: 6px;
    border-radius: 99px;
    background: var(--cf-surface-2);
    overflow: hidden;
}
.cf-quiz-progress-fill {
    height: 100%;
    width: 0;
    border-radius: 99px;
    background: var(--cf-accent-grad);
    transition: width var(--cf-dur) var(--cf-ease-out);
}
.cf-quiz-progress.is-complete .cf-quiz-progress-pct { color: var(--cf-success); }
.cf-quiz-progress.is-complete .cf-quiz-progress-fill { background: var(--cf-success); }

/* ─────────────────────────────────────────────
   19d. Dashboard — streak & feed
   ───────────────────────────────────────────── */
.cf-flame {
    display: inline-block;
    margin-left: .15rem;
    animation: cf-flame 1.6s ease-in-out infinite;
    transform-origin: 50% 90%;
}

/* Feed rows arrive one after another rather than the card landing as a slab.
   nth-child rather than an --i on each row: feed_item() is a shared macro and
   the delay is presentational, not the macro's business. */
.cf-feed-stagger > .cf-feed-item { animation: cf-rise .45s var(--cf-ease-out) both; }
.cf-feed-stagger > .cf-feed-item:nth-child(1) { animation-delay: .05s; }
.cf-feed-stagger > .cf-feed-item:nth-child(2) { animation-delay: .10s; }
.cf-feed-stagger > .cf-feed-item:nth-child(3) { animation-delay: .15s; }
.cf-feed-stagger > .cf-feed-item:nth-child(4) { animation-delay: .20s; }
.cf-feed-stagger > .cf-feed-item:nth-child(5) { animation-delay: .25s; }
.cf-feed-stagger > .cf-feed-item:nth-child(6) { animation-delay: .30s; }
.cf-feed-stagger > .cf-feed-item:nth-child(7) { animation-delay: .35s; }
.cf-feed-stagger > .cf-feed-item:nth-child(n+8) { animation-delay: .40s; }

/* ─────────────────────────────────────────────
   19e. Auth — aurora band & failed-login shake
   ───────────────────────────────────────────── */
/* A far quieter cousin of the intro page's aurora (see cf3d-aurora-drift):
   one slow blurred blob, no starfield, no conic churn. */
.cf-auth-band { position: relative; overflow: hidden; }
.cf-auth-band::after {
    content: "";
    position: absolute;
    inset: -60%;
    z-index: 0;
    background: conic-gradient(from 210deg at 50% 50%,
        rgba(30, 91, 255, .40), rgba(34, 211, 238, .16),
        rgba(45, 212, 191, .22), rgba(30, 91, 255, .40));
    filter: blur(46px);
    opacity: .45;
    pointer-events: none;
    animation: cf-auth-drift 26s ease-in-out infinite alternate;
}
@keyframes cf-auth-drift {
    0%   { transform: translate3d(0, 0, 0) rotate(0deg) scale(1); }
    100% { transform: translate3d(4%, 3%, 0) rotate(14deg) scale(1.1); }
}

.cf-shake-once { animation: cf-shake .45s var(--cf-ease) both; }

/* ─────────────────────────────────────────────
   19f. Catalogue & discussions
   ───────────────────────────────────────────── */
.problem-row {
    animation: cf-rise .4s var(--cf-ease-out) both;
    animation-delay: calc(min(var(--i, 0), 14) * 35ms);
}
/* Re-staggered by main.js after a client-side filter — restarting the same
   animation needs a different class name to retrigger it. */
.problem-row.cf-restagger {
    animation: cf-rise .3s var(--cf-ease-out) both;
    animation-delay: calc(min(var(--i, 0), 14) * 25ms);
}

/* Acceptance rate as a bar you can read at a glance, not just a number. */
.cf-acc {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    justify-content: flex-end;
}
.cf-acc-bar {
    width: 42px;
    height: 5px;
    border-radius: 99px;
    background: var(--cf-surface-2);
    border: 1px solid var(--cf-border);
    overflow: hidden;
    flex-shrink: 0;
}
.cf-acc-fill {
    display: block;
    height: 100%;
    border-radius: 99px;
    background: var(--cf-accent-grad);
    transform-origin: left;
    animation: cf-sweep-x .6s var(--cf-ease-out) .1s both;
}
.cf-acc-pct { min-width: 2.6rem; text-align: right; }

/* The active category pill's fill sweeps in from the left on load, so the
   selection reads as having *moved* there across the page change. */
.category-pill { position: relative; z-index: 0; overflow: hidden; }
.category-pill.active { background: transparent; }
.category-pill.active::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: var(--cf-accent-grad);
    transform-origin: left;
    animation: cf-sweep-x .42s var(--cf-ease-out) both;
}

/* Discussion rows: nudge on hover, and tint the reply count with it. */
.cf-thread-row {
    transition: background var(--cf-dur) var(--cf-ease), padding-left var(--cf-dur) var(--cf-ease);
}
.cf-thread-row:hover { padding-left: 1.75rem; }
.cf-thread-reply-badge {
    transition: background var(--cf-dur) var(--cf-ease),
                color var(--cf-dur) var(--cf-ease),
                border-color var(--cf-dur) var(--cf-ease);
}
.cf-thread-row:hover .cf-thread-reply-badge {
    background: var(--cf-primary-light) !important;
    color: var(--cf-primary) !important;
    border-color: var(--cf-primary) !important;
}

/* The reply you just posted — the server anchors to it, main.js flags it. */
@keyframes cf-flash-highlight {
    0%   { background: var(--cf-primary-light); border-color: var(--cf-primary); }
    100% { background: var(--cf-surface); border-color: var(--cf-border); }
}
.reply-card.is-fresh {
    animation: cf-rise .4s var(--cf-ease-out) both,
               cf-flash-highlight 2s var(--cf-ease-out) .3s both;
}

/* ─────────────────────────────────────────────
   19g. Cross-cutting
   ───────────────────────────────────────────── */
/* Every empty state on the site opens with a big emoji as its first child —
   one rule floats all of them. */
.empty-state > :first-child,
.cf-page-search-empty > :first-child {
    animation: cf-float 9s ease-in-out infinite;
}

/* Flash messages: drop in from the top, then run a hairline down to zero over
   the 4s main.js waits before dismissing them. */
.cf-flash {
    position: relative;
    overflow: hidden;
    animation: cf-drop-in var(--cf-dur) var(--cf-ease-out) both;
}
.cf-flash::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 100%;
    background: currentColor;
    opacity: .3;
    transform-origin: left;
    animation: cf-flash-timer 4s linear both;
}
@keyframes cf-flash-timer { to { transform: scaleX(0); } }
/* Hovering pauses the countdown; main.js keeps the element alive to match. */
.cf-flash:hover::after { animation-play-state: paused; }

/* ── View Transitions (Chromium today, progressive elsewhere) ──
   The app is server-rendered with full page loads; this cross-fades one
   document into the next so moving between tabs stops flashing white. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: cf-vt-out .16s var(--cf-ease) both; }
::view-transition-new(root) { animation: cf-vt-in .26s var(--cf-ease-out) both; }
@keyframes cf-vt-out { to   { opacity: 0; transform: translateY(-6px); } }
@keyframes cf-vt-in  { from { opacity: 0; transform: translateY(8px); } }

/* ── Reduced motion ──
   §17 already zeroes every duration/delay above, which is enough for anything
   whose resting state is visible. These two are not: their resting state is
   invisible and only the animation reveals them, so restore them by hand. */
@media (prefers-reduced-motion: reduce) {
    .cf-score-ring-fill { stroke-dashoffset: var(--dash); }
    .cf-tick path       { stroke-dashoffset: 0; }
    .cf-flash::after    { display: none; }
    .cf-judging::after  { animation: none; background: var(--cf-primary); }
    @view-transition { navigation: none; }
}
