/* ===== Levels page — "2b Trail" =====
   Values copied from the mock's own source (skunkworks "Cloodit - Levels
   Page Redesign.zip" → Cloodit Levels Refresh.dc.html, section 2b), with
   teacher/class-progress.css as the palette of record: where the mock and
   class-progress use different values for the same role, class-progress
   wins (dropdown panel #2B1C50 not #1B1336, its border/radius/hover, the
   postmark's .55/.75 gold, #8A7A5A for muted paper ink). Paper stays
   #FBF6EA — class-progress's own .class-postcard value. The burger menu
   itself is nav-menu.css; this file places the HUD and draws the trail.
   levels.css is NOT loaded here — module-summary.html still uses it. */

.levels-page {
    --paper: #FBF6EA;
    --paper-line: #E6DCC4;
    --paper-rule: #D8CDB2;
    --paper-muted: #8A7A5A;
    --paper-gold: #B7791F;
    --ink: #2B1C50;
    --purple: #7C2BF5;
    --gold: #FBBF24;
    --green-light: #A9E77A;
    --good-ink: #4E9E1E;
    --low-ink: #E06A24;
    --none-ink: #C9BEA3;
    --menu-bg: #2B1C50;
    --menu-ink: #E4D9FF;
    --menu-label: #8E7DB8;
    --menu-lavender: #B3A2D8;
    --glass: rgba(20,10,40,.62);
    --glass-hover: rgba(20,10,40,.78);
    --font-display: 'Baloo 2', cursive;
    --font-body: 'Nunito Sans', system-ui, sans-serif;
    --font-script: 'Caveat', cursive;
    --nav-gutter: 24px;
}

*, *::before, *::after { box-sizing: border-box; }

body.levels-page {
    margin: 0;
    font-family: var(--font-body);
    background: #2B1D4B;
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
}

.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ===== Anti-FOUC: hidden by default (fail closed), shown only once
   levels.js explicitly marks the page ready — its init is wrapped in
   try/finally so that always happens, even after an error. ===== */
.levels-container {
    opacity: 0;
    transition: opacity 0.25s ease;
}
html.levels-ready .levels-container { opacity: 1; }
html:not(.levels-ready) .biome-strip { display: none; }

/* Below the HUD, so the burger already works while the trail loads. */
#levelsLoading {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 10;
}
.loading-spinner {
    width: 36px;
    height: 36px;
    border: 3px solid rgba(255,255,255,.15);
    border-top-color: var(--gold);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
    margin: 0 auto 16px;
}
@keyframes spin { to { transform: rotate(360deg); } }
#levelsLoading p {
    margin: 0;
    color: var(--menu-ink);
    font-weight: 700;
    font-size: 0.95rem;
}
html.levels-ready #levelsLoading { display: none; }

/* ===== HUD ===== */
.hud-shade {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    height: 130px;
    pointer-events: none;
    z-index: 40;
    background: linear-gradient(180deg, rgba(11,16,32,.85) 0%, rgba(11,16,32,0) 100%);
}
.levels-page .top-nav {
    position: fixed;
    top: 20px;
    left: 0;
    right: 0;
    height: auto;
    z-index: 50;
}
.levels-page .nav-inner { row-gap: 10px; }
.levels-page .nav-logo-link img { height: 30px; display: block; }
.levels-page #menu-btn {
    position: relative;
    backdrop-filter: blur(8px);
}
/* New badge waiting: the Badges row pulses inside the menu, so flag the
   burger too (levels.js checkBadgePulse). */
.levels-page #menu-btn.has-news::after {
    content: '';
    position: absolute;
    top: -4px;
    right: -4px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--gold);
    border: 2px solid var(--menu-bg);
}
.hud-divider {
    order: 1;
    flex: none;
    width: 1px;
    height: 30px;
    background: rgba(255,255,255,.22);
}

/* Journey switcher — the mock's journey title + caret, with its dropdown
   dressed as class-progress's .class-switcher-panel. */
.journey-switch {
    order: 1;
    position: relative;
    min-width: 0;
    /* Pulls the button's hover pad back so the title text itself sits 16px
       after the divider, as in the mock. On the wrapper, not the button:
       a negative margin on the button would fight its max-width:100%. */
    margin-left: -12px;
}
.journey-switch-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: 100%;
    padding: 6px 10px 6px 12px;
    border: none;
    border-radius: 14px;
    background: none;
    cursor: pointer;
    color: #fff;
    transition: background .15s;
}
.journey-switch-btn:hover,
.journey-switch.is-open .journey-switch-btn { background: rgba(20,10,40,.45); }
.journey-switch-btn:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.journey-switch-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--font-display);
    font-size: 28px;
    font-weight: 800;
    line-height: 1.15;
    color: #fff;
    text-shadow: 0 2px 12px rgba(0,0,0,.4);
}
.journey-switch-caret {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: rgba(255,255,255,.14);
    border: 1px solid rgba(255,255,255,.22);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 16px;
    transition: transform .2s;
}
.journey-switch.is-open .journey-switch-caret { transform: rotate(180deg); }

.journey-panel {
    position: absolute;
    left: 0;
    top: calc(100% + 8px);
    width: min(340px, calc(100vw - 32px));
    background: var(--menu-bg);
    border: 1px solid rgba(255,255,255,.16);
    border-radius: 18px;
    padding: 8px;
    box-shadow: 0 20px 50px rgba(0,0,0,.55);
    display: flex;
    flex-direction: column;
    gap: 2px;
    z-index: 60;
}
.journey-panel[hidden] { display: none; }
.journey-panel-label {
    padding: 8px 12px 6px;
    font-size: 11px;
    letter-spacing: 1.5px;
    font-weight: 900;
    color: var(--menu-label);
}
.journey-panel-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: min(420px, 60vh);
    overflow-y: auto;
}
.journey-panel-note {
    padding: 10px 12px;
    color: var(--menu-lavender);
    font-size: 14px;
    font-weight: 700;
}
.journey-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 9px 10px;
    border: none;
    border-radius: 12px;
    background: transparent;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background .15s;
}
.journey-item:hover { background: rgba(124,43,245,.35); }
.journey-item.is-current { background: rgba(124,43,245,.22); cursor: default; }
.journey-item:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.journey-thumb {
    flex: none;
    width: 52px;
    height: 36px;
    border-radius: 9px;
    overflow: hidden;
    background: #3E2F6D;
}
.journey-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.journey-thumb.is-monogram {
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #7C2BF5, #2FB6A6);
    color: #fff;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 18px;
}
.journey-item-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.journey-item-name {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #fff;
    font-weight: 900;
    font-size: 14.5px;
    line-height: 1.3;
}
.journey-class-tag {
    flex: none;
    background: rgba(119,192,67,.16);
    border: 1px solid rgba(119,192,67,.55);
    color: var(--green-light);
    font-weight: 900;
    font-size: 10.5px;
    letter-spacing: 1px;
    padding: 1px 7px;
    border-radius: 999px;
    text-transform: uppercase;
}
.journey-item-meta {
    margin-top: 2px;
    font-size: 11px;
    font-weight: 900;
    color: var(--menu-lavender);
}
.journey-tick { flex: none; color: var(--green-light); font-weight: 900; font-size: 14px; min-width: 12px; }
.journey-panel-more {
    margin-top: 4px;
    padding: 10px 12px 6px;
    border-top: 1px solid rgba(255,255,255,.08);
    color: var(--green-light);
    font-weight: 900;
    font-size: 14px;
    text-decoration: none;
}
.journey-panel-more:hover { color: #C6F0A4; }

/* Right-hand pills: Resume (always) and a live sprint (only while live). */
.levels-page .nav-right { flex: none; }
.hud-pill {
    flex: none;
    display: flex;
    align-items: center;
    gap: 14px;
    white-space: nowrap;
    height: 40px;
    padding: 0 7px 0 18px;
    border-radius: 16px;
    background: var(--glass);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,.16);
    color: #fff;
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 800;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background .2s;
}
.hud-pill[hidden] { display: none; }
.hud-pill:hover { background: var(--glass-hover); }
.hud-pill:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.resume-pill-arrow {
    width: 26px;
    height: 26px;
    flex: none;
    border-radius: 50%;
    background: rgba(255,255,255,.12);
    border: 1.5px solid rgba(255,255,255,.55);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 11px;
}
.resume-pill.is-complete { padding: 0 18px; cursor: default; }
.resume-pill.is-complete:hover { background: var(--glass); }
.resume-pill.is-complete .resume-pill-arrow { display: none; }
/* Live sprint — class-progress's launch orange, pulsing. */
.sprint-pill {
    gap: 10px;
    padding: 0 18px 0 14px;
    background: linear-gradient(180deg, #F08A45, #E06A24);
    border-color: rgba(255,255,255,.3);
    box-shadow: 0 4px 0 rgba(0,0,0,.22);
    animation: sprintPillPulse 1.4s ease-in-out infinite;
}
.sprint-pill:hover { background: linear-gradient(180deg, #F59A5A, #E8762F); }
.sprint-pill-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 0 0 rgba(255,255,255,.7);
    animation: sprintDot 1.4s ease-out infinite;
}
@keyframes sprintPillPulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.05); }
}
@keyframes sprintDot {
    0%   { box-shadow: 0 0 0 0 rgba(255,255,255,.7); }
    100% { box-shadow: 0 0 0 10px rgba(255,255,255,0); }
}

/* progress-utils.js's opt-in "your teacher has a new class journey" banner
   (maybeShowJourneySwitchBanner) — a paper note pinned under the HUD. */
.journey-switch-banner {
    position: fixed;
    top: 84px;
    left: 50%;
    transform: translateX(-50%) rotate(-1deg);
    z-index: 45;
    width: min(560px, calc(100vw - 32px));
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    background: var(--paper);
    border: 1px solid var(--paper-line);
    border-radius: 8px;
    padding: 12px 14px 12px 18px;
    box-shadow: 0 20px 44px rgba(0,0,0,.45);
}
.journey-switch-banner-text {
    flex: 1 1 auto;
    color: var(--ink);
    font-size: 15px;
    font-weight: 700;
}
.journey-switch-banner-btn {
    flex: none;
    background: var(--purple);
    color: #fff;
    border: none;
    border-radius: 12px;
    padding: 8px 18px;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 800;
    cursor: pointer;
    box-shadow: 0 4px 0 rgba(0,0,0,.2);
}
.journey-switch-banner-btn:hover { background: #8F45FF; }
.journey-switch-banner-dismiss {
    flex: none;
    background: none;
    border: none;
    color: var(--paper-muted);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px;
}
.journey-switch-banner-dismiss:hover { color: var(--ink); }

/* ===== Chapters ===== */
.chapter {
    --sky: #96C4D8;
    position: relative;
    isolation: isolate;
    min-height: 660px;
    overflow: clip;
    background-color: var(--sky);
    background-image: linear-gradient(180deg, rgba(11,16,32,.35) 0, rgba(11,16,32,0) 120px);
}
.chapter[data-biome="reef"]    { --sky: #81C4D7; }
.chapter[data-biome="deepsea"] { --sky: #002C59; }
.chapter[data-biome="space"]   { --sky: #000; }
/* Room for the fixed biome strip under the last cards. */
.chapter:last-of-type { padding-bottom: 170px; }

/* Sticky decorative layer: stays in view through a long chapter. */
.chapter-sky {
    position: sticky;
    top: 0;
    height: 100vh;
    margin-bottom: -100vh;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}
.chapter-sky img { position: absolute; display: block; height: auto; }
/* Mock 2b placements (lines 46-53), lefts as % of its 1120px frame. */
.sky-sun          { left: 73.2%; top: 170px; width: clamp(110px, 17vw, 190px); }
.cloud-c1a        { left: 50%;   top: 120px; width: clamp(80px, 11.6vw, 130px); opacity: .95; }
.cloud-c6a        { left: 83%;   top: 420px; width: clamp(74px, 10.7vw, 120px); opacity: .95; }
.cloud-c2a        { left: 57.1%; top: 360px; width: clamp(60px, 8.6vw, 96px);   opacity: .9; }
.cloud-c5a        { left: 64.3%; top: 540px; width: clamp(92px, 13.4vw, 150px); opacity: .95; }
.cloud-c1b        { left: 88.4%; top: 90px;  width: clamp(50px, 7.1vw, 80px);   opacity: .85; }
.cloud-c6b        { left: 33.9%; top: 560px; width: clamp(52px, 7.5vw, 84px);   opacity: .85; }
.cloud-c2b        { left: 3.6%;  top: 600px; width: clamp(68px, 9.8vw, 110px);  opacity: .9; }
/* Sea and space skies — the badges page's .reef/.deepsea/.space headers. */
.sky-fish         { top: 50%; width: 50%; transform: translateY(-50%); opacity: .9; }
.fish-right       { right: -10%; }
.fish-left        { left: -10%; }
.sky-planets      { left: 0; top: 60%; width: clamp(140px, 16%, 240px); transform: translateY(-60%); opacity: .95; }

.chapter-inner {
    position: relative;
    z-index: 1;
    max-width: 1180px;
    margin: 0 auto;
    padding: 104px clamp(16px, 3vw, 30px) 40px;
}
.chapter-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px 16px;
}
.chapter-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 44px;
    font-weight: 800;
    line-height: 1.1;
    color: #fff;
    white-space: nowrap;
    text-shadow: 0 3px 0 rgba(18,32,63,.35), 0 6px 18px rgba(18,32,63,.25);
}

/* Wavy dashed "% journeyed" line — scales down with the viewport; both
   copies share --path-w so the gold one lines up exactly under its clip. */
.journey-path {
    --path-w: min(324px, calc(100vw - 48px));
    flex: none;
    position: relative;
    width: var(--path-w);
    height: calc(var(--path-w) * 44 / 324);
}
.journey-path svg {
    position: absolute;
    left: 0;
    width: var(--path-w);
    height: calc(var(--path-w) * 44 / 324);
    overflow: visible;
}
.journey-path path {
    fill: none;
    stroke-width: 5;
    stroke-linecap: round;
    stroke-dasharray: 7 9;
}
.journey-path-track { top: 0; filter: drop-shadow(0 2px 0 rgba(18,32,63,.25)); }
.journey-path-track path { stroke: #fff; }
.journey-path-fill {
    position: absolute;
    left: 0;
    top: -6px;
    bottom: -6px;
    overflow: hidden;
}
.journey-path-gold { top: 6px; filter: drop-shadow(0 0 4px rgba(251,191,36,.9)); }
.journey-path-gold path { stroke: var(--gold); }

.chapter-badges {
    margin-left: auto;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 14px;
}
.befriended {
    flex: none;
    font-family: var(--font-script);
    font-size: 22px;
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
    text-shadow: 0 2px 6px rgba(18,32,63,.35);
}
.chapter-badge-row { display: flex; align-items: center; gap: 6px; }
.chapter-badge,
.chapter-badge-more {
    width: 40px;
    height: 40px;
    flex: none;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid #fff;
    box-shadow: 0 3px 8px rgba(11,16,32,.3);
    padding: 0;
    cursor: pointer;
    transition: transform .15s;
}
.chapter-badge { background: #fff; }
.chapter-badge img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.06); display: block; }
.chapter-badge:hover,
.chapter-badge-more:hover { transform: translateY(-2px) scale(1.06); }
.chapter-badge:focus-visible,
.chapter-badge-more:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.chapter-badge-more {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--glass);
    color: #fff;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 800;
    text-decoration: none;
}

/* ===== Modules ===== */
.modules {
    margin-top: 30px;
    display: flex;
    flex-direction: column;
    gap: 88px;
}
.module { display: flex; flex-direction: column; gap: 26px; }

.module-box {
    width: 560px;
    max-width: 100%;
    border-radius: 16px;
    border: 1px solid var(--box-line);
    background: var(--box-bg);
    box-shadow: 0 10px 22px rgba(11,16,32,.16);
    overflow: hidden;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px;
    padding: 9px 9px 9px 16px;
}
/* Tint by the module's average accuracy over its completed levels. */
.tint-good { --box-bg: #E9F5DC; --box-line: #CFE6B8; --meta-ink: var(--good-ink); }
.tint-low  { --box-bg: #FDE9D6; --box-line: #F5CBA7; --meta-ink: var(--low-ink); }
.tint-none { --box-bg: var(--paper); --box-line: var(--paper-line); --meta-ink: var(--paper-muted); }
.module-head { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.module-label {
    font-size: 11px;
    font-weight: 900;
    letter-spacing: 1.5px;
    color: var(--paper-gold);
    white-space: nowrap;
}
.module-title {
    margin: 0 0 -4px;
    font-family: var(--font-display);
    font-weight: 800;
    color: var(--ink);
    font-size: 24px;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.module-locked {
    padding-right: 8px;
    font-size: 11.5px;
    letter-spacing: 1.5px;
    font-weight: 900;
    color: var(--paper-muted);
    white-space: nowrap;
}

/* ===== Tickets on the zig-zag =====
   --step (0…1, per slot, set by levels.js) is the card's position across
   the free width beside it: the mock's 0/130/260/360px offsets exactly at
   full width, shrinking proportionally as the column narrows. */
.tickets {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 4px 0 0 4px;
    max-width: 664px;
}
.ticket {
    --w: min(360px, 100%);
    --card: var(--paper);
    --pm: rgba(183,121,31,.55);
    --pm-ink: rgba(183,121,31,.75);
    position: relative;
    width: var(--w);
    margin-left: calc(var(--step, 0) * (100% - var(--w)));
    transform: rotate(var(--tilt, 0deg));
    background: var(--card);
    border-radius: 6px;
    padding: 10px 12px;
    box-shadow: 0 12px 24px rgba(11,16,32,.24), 0 2px 0 rgba(0,0,0,.06);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 1px 50px;
    gap: 12px;
    align-items: center;
    color: var(--ink);
    text-decoration: none;
    cursor: pointer;
    transition: transform .18s ease;
    scroll-margin-top: 140px;
}
.ticket:hover { transform: rotate(0deg) translateY(-3px); }
.ticket:focus-visible { outline: 3px solid var(--gold); outline-offset: 4px; }
.ticket.is-mastered { --card: #E9F5DC; }
.ticket.is-needs    { --card: #FDE9D6; }
.ticket.is-locked   { --card: #E9E2D2; --pm: rgba(138,122,90,.35); --pm-ink: rgba(138,122,90,.35); opacity: .82; }
.ticket.is-locked:hover { transform: rotate(var(--tilt, 0deg)); }
.ticket.is-current  { --pm: rgba(124,43,245,.8); --pm-ink: rgba(124,43,245,.8); outline: 3px solid var(--purple); outline-offset: 4px; }

.ticket-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
.ticket-num {
    flex: none;
    min-width: 38px;
    font-family: var(--font-display);
    font-size: 34px;
    font-weight: 800;
    line-height: 1;
    color: var(--ink);
}
.ticket-main { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.ticket-name {
    font-family: var(--font-script);
    font-size: 23px;
    font-weight: 700;
    line-height: 1;
    color: var(--paper-gold);
    white-space: nowrap;
}
.ticket.is-locked .ticket-name { color: var(--paper-muted); }
.ticket-stars { display: flex; gap: 3px; }
.ticket-star, .ticket-stars { flex: none; }
.ticket-star {
    width: 17px;
    height: 16px;
    background: #E3D9C0;
    clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.ticket-star.on {
    background: linear-gradient(180deg, #FDE68A, #FBBF24);
    filter: drop-shadow(0 0 3px rgba(251,191,36,.7));
}
.ticket-acc {
    padding-right: 2px;
    text-align: right;
    font-family: var(--font-display);
    font-size: 34px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--none-ink);
}
.ticket.is-mastered .ticket-acc { color: var(--good-ink); }
.ticket.is-needs .ticket-acc    { color: var(--low-ink); }
.ticket-rule {
    align-self: stretch;
    background: repeating-linear-gradient(180deg, var(--paper-rule) 0 4px, transparent 4px 7px);
}
.ticket-stamp {
    position: relative;
    width: 44px;
    height: 52px;
    padding: 3px;
    background: #fff;
    border: 2px dashed var(--paper-rule);
    border-radius: 3px;
}
.stamp-art {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: var(--gem);
}
.stamp-art::before,
.stamp-art::after { content: ''; position: absolute; inset: 0; }
.stamp-art::before { background: rgba(255,255,255,.3); clip-path: polygon(0 0, 100% 0, 0 70%); }
.stamp-art::after  { background: rgba(0,0,0,.14); clip-path: polygon(100% 30%, 100% 100%, 20% 100%); }
.gem-blue   { --gem: linear-gradient(135deg, #7FD2F5, #2E9BF0 52%, #1E6FD0); }
.gem-lime   { --gem: linear-gradient(135deg, #C8F27A, #A9E77A 52%, #6FB520); }
.gem-amber  { --gem: linear-gradient(135deg, #FFE066, #FFC61E 52%, #E8A100); }
.gem-red    { --gem: linear-gradient(135deg, #FF7A72, #E8342F 52%, #BE1C18); }
.gem-purple { --gem: linear-gradient(135deg, #A97BEE, #7B3FD4 52%, #5A24AC); }
.gem-teal   { --gem: linear-gradient(135deg, #6FE4D6, #21C1B0 52%, #11907F); }
.gem-locked { --gem: rgba(15,16,32,.55); }
.postmark {
    position: absolute;
    left: -22px;
    bottom: -12px;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 2px solid var(--pm);
    display: flex;
    align-items: center;
    justify-content: center;
    transform: rotate(-14deg);
    font-size: 7.5px;
    font-weight: 900;
    letter-spacing: 1px;
    color: var(--pm-ink);
    pointer-events: none;
}

/* Locked tap — a small paper note (levels.js attachLockedTooltips). */
.lock-tooltip {
    position: absolute;
    left: 50%;
    bottom: calc(100% + 10px);
    transform: translateX(-50%) rotate(-1.5deg);
    z-index: 5;
    max-width: min(280px, 80vw);
    padding: 8px 12px;
    border-radius: 6px;
    background: var(--paper);
    border: 1px solid var(--paper-line);
    box-shadow: 0 10px 22px rgba(11,16,32,.3);
    color: var(--ink);
    font-size: 13px;
    font-weight: 800;
    line-height: 1.3;
    text-align: center;
    animation: noteIn .18s ease-out;
}
@keyframes noteIn {
    from { opacity: 0; transform: translateX(-50%) translateY(4px) rotate(-1.5deg); }
    to   { opacity: 1; transform: translateX(-50%) rotate(-1.5deg); }
}

/* "74% | Module summary →" chip after a module's cards. */
.summary-chip {
    margin: 6px 0 0 4px;
    width: fit-content;
    max-width: 100%;
    display: flex;
    align-items: stretch;
    height: 52px;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid var(--box-line);
    background: #fff;
    box-shadow: 0 12px 24px rgba(11,16,32,.24);
    text-decoration: none;
    transform: rotate(-1deg);
    transition: transform .18s ease;
}
.summary-chip:hover { transform: rotate(0deg) translateY(-3px); }
.summary-chip:focus-visible { outline: 3px solid var(--gold); outline-offset: 4px; }
.summary-chip-meta {
    display: flex;
    align-items: center;
    padding: 0 18px;
    font-family: var(--font-display);
    font-size: 28px;
    font-weight: 800;
    line-height: 1;
    color: var(--meta-ink);
    white-space: nowrap;
}
.summary-chip-link {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 18px;
    background: var(--box-bg);
    border-left: 1px solid var(--box-line);
    color: var(--ink);
    font-weight: 900;
    font-size: 15px;
    white-space: nowrap;
}
.summary-chip-arrow { color: var(--paper-muted); }

/* ===== No journey (levels.js renderNoJourney) =====
   The desert sky with a paper postcard in the middle — corner-launcher's
   popover paper and tilt, class-progress's purple/green buttons. */
.chapter-empty {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 120px 16px 170px;
}
.chapter-empty .chapter-sky { margin-bottom: 0; position: absolute; inset: 0; height: auto; }
.no-journey-card {
    position: relative;
    z-index: 1;
    width: min(420px, 100%);
    padding: 26px 26px 24px;
    border-radius: 8px;
    background: var(--paper);
    color: var(--ink);
    text-align: center;
    box-shadow: 0 20px 44px rgba(11,16,32,.35);
    transform: rotate(-1deg);
}
.no-journey-kicker {
    font-family: var(--font-script);
    font-size: 22px;
    font-weight: 700;
    color: var(--paper-gold);
    line-height: 1;
}
.no-journey-title {
    margin: 6px 0 14px;
    font-family: var(--font-display);
    font-size: 28px;
    font-weight: 800;
    line-height: 1.15;
}
.no-journey-text {
    margin: 0 0 10px;
    font-size: 15px;
    font-weight: 700;
    color: var(--paper-muted);
}
.no-journey-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 200px;
    padding: 12px 22px;
    border-radius: 14px;
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 800;
    text-decoration: none;
    box-shadow: 0 4px 0 rgba(0,0,0,.2);
    transition: transform .15s, background .15s;
}
.no-journey-btn:hover { transform: translateY(-2px); }
.no-journey-btn:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }
.no-journey-btn.is-primary { background: var(--purple); color: #fff; }
.no-journey-btn.is-primary:hover { background: #8F45FF; }
.no-journey-btn.is-secondary { background: #77C043; color: #16330a; }
.no-journey-btn.is-secondary:hover { background: #88D152; }
.no-journey-join {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 2px dashed var(--paper-rule);
}
.no-journey-join[hidden] { display: none; }

/* ===== Biome strip ===== */
.biome-strip {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: 60px;
    pointer-events: none;
    z-index: 30;
}
.biome-strip-layer {
    position: absolute;
    inset: 0;
    background-repeat: repeat-x;
    background-position: bottom center;
    background-size: auto 60px;
    opacity: 0;
    transition: opacity .6s ease;
}
.biome-strip-layer.is-active { opacity: 1; }

/* ===== Badge Info Modal — a postcard, like corner-launcher's popovers ===== */
.badge-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(24,14,48,.7);
    animation: fadeIn .2s ease;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.badge-modal {
    position: relative;
    width: min(340px, 100%);
    padding: 28px 24px 24px;
    border-radius: 8px;
    background: var(--paper);
    color: var(--ink);
    text-align: center;
    box-shadow: 0 20px 44px rgba(0,0,0,.5);
    transform: rotate(-1deg);
    animation: modalPop .25s ease;
}
@keyframes modalPop {
    from { transform: rotate(-1deg) scale(.92); opacity: 0; }
    to   { transform: rotate(-1deg) scale(1); opacity: 1; }
}
.badge-modal-close {
    position: absolute;
    top: 8px;
    right: 10px;
    border: none;
    background: none;
    font-size: 26px;
    line-height: 1;
    color: var(--paper-muted);
    cursor: pointer;
}
.badge-modal-close:hover { color: var(--ink); }
.badge-modal-image {
    width: 120px;
    height: 120px;
    object-fit: cover;
    border-radius: 50%;
    border: 3px solid #fff;
    box-shadow: 0 6px 16px rgba(11,16,32,.25);
    display: block;
    margin: 0 auto 12px;
}
.badge-modal-name {
    margin: 0;
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 800;
    line-height: 1.15;
}
.badge-modal-title {
    margin: 2px 0 10px;
    font-family: var(--font-script);
    font-size: 22px;
    font-weight: 700;
    color: var(--paper-gold);
}
.badge-modal-desc {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.45;
}

/* Warp-suck animation when a student joins a live sprint */
.sprint-warp .levels-container,
.sprint-warp nav.top-nav {
    animation: warpSuck 0.5s ease-in forwards;
    pointer-events: none;
}
@keyframes warpSuck {
    0%   { transform: scale(1);    opacity: 1; }
    55%  { transform: scale(0.88); opacity: 0.7; }
    100% { transform: scale(2.6) translateY(-28vh); opacity: 0; }
}

/* ===== Responsive ===== */
@media (max-width: 900px) {
    .chapter-badges { margin-left: 0; }
}

@media (max-width: 720px) {
    .journey-switch-title { font-size: 22px; }
    .chapter-title { font-size: 36px; }
    .hud-pill { font-size: 17px; height: 38px; }
}

/* Phones: the journey title drops under the burger/logo/pills row, and the
   zig-zag straightens into one full-width column (tilt halved). */
@media (max-width: 560px) {
    .levels-page { --nav-gutter: 16px; }
    .levels-page .top-nav { top: 12px; }
    .levels-page .nav-inner { flex-wrap: wrap; }
    .hud-divider { display: none; }
    .journey-switch { order: 4; flex: 1 0 100%; margin-left: -6px; }
    .journey-switch-btn { padding: 4px 8px 4px 6px; }
    .journey-switch-title { font-size: 21px; }
    .journey-switch-caret { width: 26px; height: 26px; font-size: 14px; }
    .hud-shade { height: 170px; }
    .hud-pill { font-size: 15px; height: 36px; gap: 10px; padding-left: 14px; }
    .resume-pill-arrow { width: 22px; height: 22px; font-size: 10px; }
    .sprint-pill { padding: 0 12px; }
    .journey-switch-banner { top: 120px; }

    .chapter-inner { padding-top: 150px; }
    /* Keep the sun clear of the title and progress line on a phone. */
    .sky-sun { left: auto; right: -34px; top: 300px; width: 110px; }
    .chapter-title { font-size: 32px; white-space: normal; }
    .befriended { font-size: 20px; }
    .modules { gap: 56px; }
    .module-title { font-size: 20px; }

    .ticket {
        --step: 0 !important;
        --w: 100%;
        transform: rotate(calc(var(--tilt, 0deg) * .5));
        grid-template-columns: minmax(0, 1fr) auto 1px 46px;
        gap: 10px;
        scroll-margin-top: 180px;
    }
    .ticket.is-locked:hover { transform: rotate(calc(var(--tilt, 0deg) * .5)); }
    .ticket-num { font-size: 28px; min-width: 30px; }
    .ticket-name { font-size: 21px; }
    .ticket-acc { font-size: 26px; }
    .ticket-star { width: 14px; height: 13px; }
    .summary-chip-meta { font-size: 24px; padding: 0 14px; }
    .summary-chip-link { padding: 0 14px; font-size: 14px; }
}

@media (max-width: 360px) {
    .levels-page .nav-logo-link img { height: 24px; }
    .ticket-stars { gap: 2px; }
    .ticket-star { width: 12px; height: 11px; }
}

@media (prefers-reduced-motion: reduce) {
    .ticket, .summary-chip, .chapter-badge, .chapter-badge-more,
    .journey-switch-caret, .biome-strip-layer, .levels-container { transition: none; }
    .sprint-pill, .sprint-pill-dot, .lock-tooltip, .badge-modal, .badge-modal-overlay { animation: none; }
}
