@import './v2-topbar.css';

/* ── HUB PAGE BASE + CHAPTER COLOR TOKENS ───────────────────── */
/*
 * Chapter accent colors — consumed via --node-color / --node-dark
 * inline CSS variables injected per-node in hub.js (chapterStyle()).
 *
 * Color choices (light-theme accessible):
 *   ch1  Amber   — warm entry point
 *   ch2  Cyan    — matches --primary; strings feel crisp/precise
 *   ch3  Purple  — branching logic
 *   ch4  Emerald — collections and structure feel "organized"
 *   ch5  Rose    — algorithms feel demanding/energetic
 *   ch6  Teal    — advanced topics feel deep/expert
 *
 * Orb backgrounds use the *-dark shade so white icons clear 3:1 WCAG.
 * Card borders / pulse rings use the lighter shade.
 */
body[data-v2-hub] {
    background: var(--surface);
    min-height: 100%;
    overflow-x: hidden;         /* clip any wave translateX that exceeds path bounds */

    --hub-ch1-color: #77BB92;   --hub-ch1-dark: #4A9466;
    --hub-ch2-color: #360568;   --hub-ch2-dark: #220440;
    --hub-ch3-color: #05668D;   --hub-ch3-dark: #034E6A;
    --hub-ch4-color: #54A4B6;   --hub-ch4-dark: #2E7A8A;
    --hub-ch5-color: #89BBFE;   --hub-ch5-dark: #3B82F6;
    --hub-ch6-color: #EF626C;   --hub-ch6-dark: #BE123C;
}

/* XP counter pill — Phase 2 stub; hub.js populates this */
#hub-xp {
    display: flex;
    align-items: center;
    gap: 4px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 5px 12px;
    min-width: 72px;        /* prevent layout shift while hub.js renders */
    justify-content: center;
}

.hub-xp-icon  { font-size: 13px; }
.hub-xp-value { font-size: 13px; font-weight: 800; color: var(--text); }

/* ── MAIN SCROLL AREA ───────────────────────────────────────── */
#hub-main {
    padding-top: calc(var(--topbar-h) + 24px);
    padding-bottom: env(safe-area-inset-bottom, 40px);
    min-height: 100vh;
}

/* ── PATH LIST ──────────────────────────────────────────────── */
#hub-path {
    list-style: none;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    max-width: 480px;
    margin: 0 auto;
    --wave-amp: clamp(28px, 6vw, 110px);
    padding: 0 var(--wave-amp) 40px;  /* padding matches amplitude — see wave section */
}

/* ── CHAPTER HEADERS ────────────────────────────────────────── */
.hub-chapter {
    position: relative;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 36px 0 22px;
    margin-top: 0;
    border-bottom: 1px solid var(--border);
    margin-bottom: 0;
}

.hub-chapter::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 28px;
    width: 3px;
    background: var(--border);
    border-radius: 2px;
    pointer-events: none;
    z-index: -1;
}

.hub-chapter-icon {
    font-size: 22px;
    flex-shrink: 0;
    line-height: 1;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    /* Tinted surface: ~12% fill so the emoji renders without contrast clash,
       solid border at the same weight as the lesson orb (3px) to unify the
       visual language with the locked-node geometry.                        */
    background: var(--bg);
    border: 3px solid var(--node-color);
    display: grid;
    place-items: center;
}

@supports (color: color-mix(in srgb, red 1%, transparent)) {
    .hub-chapter-icon {
        background: color-mix(in srgb, var(--node-color) 12%, var(--bg));
    }
}

.hub-chapter-text  { display: flex; flex-direction: column; gap: 1px; }

.hub-chapter-num {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.hub-chapter-label {
    font-size: 19px;
    font-weight: 900;
    color: var(--text);
    line-height: 1.2;
}

/* ── LESSON NODE ────────────────────────────────────────────── */
.hub-node { position: relative; }

/* Full-width button wraps the entire node row */
.hub-node-btn {
    width: 100%;
    display: flex;
    align-items: stretch;
    gap: 14px;
    padding: 0;
    background: transparent;
    border: none;
    text-align: left;
    cursor: pointer;
    border-radius: var(--radius-sm);
    /* Focus ring for keyboard navigation */
    outline-offset: 3px;
}

.hub-node-btn:focus-visible {
    outline: 3px solid var(--node-color, var(--primary));
}

.hub-node--locked .hub-node-btn { cursor: not-allowed; }

/* ── SPINE (connector line + orb) ───────────────────────────── */
.hub-node-spine {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
    width: 56px;
}

.hub-node-line {
    width: 3px;
    flex: 1;
    min-height: 14px;
    background: var(--border);
    border-radius: 2px;
    transition: background 0.3s;
}

.hub-node-line--hidden { visibility: hidden; }

/* Completed and unlocked segments carry the chapter colour on connector lines */
.hub-node--completed .hub-node-line,
.hub-node--unlocked  .hub-node-line { background: var(--node-color); opacity: 0.45; }

/* ── ORB ────────────────────────────────────────────────────── */
.hub-node-orb {
    width: 52px;
    height: 52px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    flex-shrink: 0;
    border: 3px solid transparent;
    position: relative;
    transition: transform 0.15s, filter 0.15s;
}

.hub-node--completed .hub-node-orb {
    background: var(--node-dark);
    border-color: var(--node-dark);
}

.hub-node--available .hub-node-orb {
    background: var(--node-dark);
    border-color: var(--node-dark);
}

.hub-node--locked .hub-node-orb {
    background: var(--border);
    border-color: var(--border-dark);
}

/* Unlocked: sequentially accessible challenge not yet verified in Supabase.
   Chapter-coloured orb (same tint as completed) at reduced opacity — visually
   distinct from ✓ (done) and ⚡ (current), clearly not locked. */
.hub-node--unlocked .hub-node-orb {
    background: var(--node-dark);
    border-color: var(--node-dark);
    opacity: 0.65;
}

.hub-node-orb-icon {
    font-size: 22px;
    font-weight: 900;
    color: var(--text-inverse);
    line-height: 1;
    /* Ensure lock emoji renders at consistent size */
    font-style: normal;
}

/* ── LESSON ORB — larger, prominent, outer color ring ───────── */
/* Lessons are landmark milestones: 64 × 64 px orb with a 5 px  */
/* chapter-colored ring separates them from challenge nodes.     */
.hub-node--lesson .hub-node-orb {
    width: 64px;
    height: 64px;
}

.hub-node--lesson .hub-node-orb-icon { font-size: 28px; }

/* Outer ring: available and completed lesson nodes get a solid   */
/* chapter-color halo using box-shadow (no layout impact).       */
.hub-node--lesson.hub-node--available .hub-node-orb,
.hub-node--lesson.hub-node--completed .hub-node-orb {
    box-shadow: 0 0 0 5px var(--node-color);
}

/* Pulse ring inset adjusted for 64 px orb diameter             */
.hub-node--lesson.hub-node--available .hub-node-orb::after {
    inset: -12px;
}

/* ── CHALLENGE ORB — smaller, lightweight ────────────────────── */
/* Challenges are practice steps: 40 × 40 px orb signals lower  */
/* visual weight than the surrounding lesson landmarks.          */
.hub-node--challenge .hub-node-orb {
    width: 40px;
    height: 40px;
}

.hub-node--challenge .hub-node-orb-icon { font-size: 17px; }

/* Pulsing ring on the active (available) node */
.hub-node--available .hub-node-orb::after {
    content: '';
    position: absolute;
    inset: -7px;
    border-radius: 50%;
    border: 3px solid var(--node-color);
    animation: hub-pulse 2.2s ease-in-out infinite;
    pointer-events: none;
}

@keyframes hub-pulse {
    0%, 100% { opacity: 0.65; transform: scale(1); }
    50%       { opacity: 0;    transform: scale(1.3); }
}

/* Hover / press states for interactive nodes */
.hub-node--available .hub-node-btn:hover .hub-node-orb,
.hub-node--completed .hub-node-btn:hover .hub-node-orb,
.hub-node--unlocked  .hub-node-btn:hover .hub-node-orb {
    transform: scale(1.1);
    filter: brightness(1.06);
}

.hub-node--available .hub-node-btn:active .hub-node-orb,
.hub-node--completed .hub-node-btn:active .hub-node-orb,
.hub-node--unlocked  .hub-node-btn:active .hub-node-orb {
    transform: scale(0.95);
    filter: brightness(0.92);
}

/* ── INFO CARD ───────────────────────────────────────────────── */
.hub-node-card {
    flex: 1;
    min-width: 0;               /* prevent flex blowout when node is translated */
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    padding: 12px 14px;
    margin: 8px 0;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg);
    transition: border-color 0.15s, box-shadow 0.15s;
}

/* Available card gets chapter accent border */
.hub-node--available .hub-node-card {
    border-color: var(--node-color);
    box-shadow: none;
}

@supports (color: color-mix(in srgb, red 1%, transparent)) {
    .hub-node--available .hub-node-card {
        box-shadow: 0 2px 12px color-mix(in srgb, var(--node-color) 20%, transparent);
    }
}

/* Completed card gets a lighter chapter accent */
.hub-node--completed .hub-node-card {
    border-color: var(--node-color);
    opacity: 0.9;
}

/* Unlocked card: chapter accent border, slightly faded vs confirmed-completed */
.hub-node--unlocked .hub-node-card {
    border-color: var(--node-color);
    opacity: 0.75;
}

/* Locked card is dimmed */
.hub-node--locked .hub-node-card {
    background: var(--surface);
    border-color: var(--border);
    opacity: 0.55;
}

.hub-node-num {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    line-height: 1;
}

.hub-node-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.25;
}

.hub-node--locked .hub-node-title { color: var(--text-muted); }

/* Tags row: category + difficulty badge */
.hub-node-tags {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.hub-node-cat {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
}

/* CTA label at the bottom of the card */
.hub-node-cta {
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.02em;
    margin-top: 2px;
}

.hub-node--available .hub-node-cta { color: var(--node-dark); }
.hub-node--completed .hub-node-cta { color: var(--node-dark); }
.hub-node--unlocked  .hub-node-cta { color: var(--node-dark); }
.hub-node--locked    .hub-node-cta { display: none; }

/* ── RESPONSIVE: hub on tablet ──────────────────────────────── */
/* NOTE: #hub-path padding is intentionally NOT zeroed here.     */
/* The 28 px horizontal padding equals the wave amplitude and    */
/* must remain on all breakpoints to guarantee zero overflow.    */
@media (min-width: 768px) {
    .hub-chapter-label { font-size: 21px; }
    .hub-node-title    { font-size: 16px; }
}

/* ── WINDING PATH WAVE ───────────────────────────────────────── */
/*
 * THE ORBS WEAVE. translateX is applied to the whole <li> so every
 * element inside — spine, orb, connector lines, and info card — moves
 * together. This is the "true sine-wave path" where orb positions form
 * the visible gamified trail.
 *
 * ZERO-OVERFLOW GUARANTEE (mathematical):
 *   On any screen of width W, #hub-path has padding P = 28 px each side.
 *   Each <li> fills the content width: W − 2P.
 *   At max right offset +P:  right edge = P + (W−2P) + P = W  ← exact edge
 *   At max left  offset −P:  left  edge = P − P         = 0  ← exact edge
 *   Amplitude is therefore HARD-CAPPED to equal the padding (28 px).
 *   body[data-v2-hub] { overflow-x: hidden } clips any sub-pixel bleed.
 *
 * 6-STEP WAVE PATTERN (one full S-curve per 6 nodes):
 *   pos 1=0   pos 2=+amp   pos 3=+amp   pos 4=0   pos 5=−amp   pos 6=−amp
 *   Chapter headers always sit at pos 0 = translateX(0).
 *
 * BRIDGE CONNECTORS:
 *   When adjacent nodes have different offsets the connector line appears
 *   to "jump" horizontally. A ::before pseudo-element on each such node
 *   draws a 3 px-tall horizontal bar that bridges the gap between the
 *   bottom of the previous node's spine and the top of the current one.
 *
 *   Spine center is always 28 px from the <li> left edge (56 px spine ÷ 2).
 *   For a right-going transition → bridge: left calc(28px−amp) to 28 (width amp).
 *   For a left-going  transition → bridge: left 28 to 28+amp (width amp).
 *
 *   Bridges on pos 1 and 2 (right-going from prev −amp or 0 → 0 or +amp).
 *   Bridges on pos 4 and 5 (left-going from prev +amp or 0 → 0 or −amp).
 *   No bridge on pos 3 (prev +amp = same) or pos 6 (prev −amp = same).
 *
 * Wave position is tracked in JS (hub.js) via data-wave-pos (1–6 on nodes,
 * 0 on chapter headers). Chapter headers carry a bridge whose geometry
 * adapts via adjacent-sibling selectors to the preceding node's position.
 */

/* ── Step 1: whole-node translateX (orbs weave) ─────────────── */
#hub-path > li[data-wave-pos="0"] { transform: translateX(0);                          }
#hub-path > li[data-wave-pos="1"] { transform: translateX(0);                          }
#hub-path > li[data-wave-pos="2"] { transform: translateX(var(--wave-amp));             }
#hub-path > li[data-wave-pos="3"] { transform: translateX(var(--wave-amp));             }
#hub-path > li[data-wave-pos="4"] { transform: translateX(0);                          }
#hub-path > li[data-wave-pos="5"] { transform: translateX(calc(-1 * var(--wave-amp))); }
#hub-path > li[data-wave-pos="6"] { transform: translateX(calc(-1 * var(--wave-amp))); }

/* ── Step 2: horizontal bridge connectors ────────────────────── */
#hub-path > li[data-wave-pos="1"]::before,
#hub-path > li[data-wave-pos="2"]::before,
#hub-path > li[data-wave-pos="4"]::before,
#hub-path > li[data-wave-pos="5"]::before,
#hub-path > li[data-wave-pos="0"]::before {
    content: '';
    position: absolute;
    top: 0;
    height: 3px;
    background: var(--border);
    border-radius: 1px;
    z-index: 0;
    pointer-events: none;
}

/* Right-going: prev spine at −amp or 0 → current spine at 0 or +amp. */
#hub-path > li[data-wave-pos="1"]::before,
#hub-path > li[data-wave-pos="2"]::before {
    left: calc(28px - var(--wave-amp));
    width: var(--wave-amp);
}

/* Left-going: prev spine at +amp or 0 → current spine at 0 or −amp. */
#hub-path > li[data-wave-pos="4"]::before,
#hub-path > li[data-wave-pos="5"]::before {
    left: 28px;
    width: var(--wave-amp);
}

/* Chapter-header bridges — geometry adapts to the preceding node's wave pos. */
/* Prev at +amp (pos 2 or 3): left-going from 28+amp to 28. */
#hub-path > li[data-wave-pos="2"] + li[data-wave-pos="0"]::before,
#hub-path > li[data-wave-pos="3"] + li[data-wave-pos="0"]::before {
    left: 28px;
    width: var(--wave-amp);
}
/* Prev at −amp (pos 5 or 6): right-going from 28−amp to 28. */
#hub-path > li[data-wave-pos="5"] + li[data-wave-pos="0"]::before,
#hub-path > li[data-wave-pos="6"] + li[data-wave-pos="0"]::before {
    left: calc(28px - var(--wave-amp));
    width: var(--wave-amp);
}
/* Prev at 0 (pos 1 or 4): no horizontal gap — suppress bridge. */
#hub-path > li[data-wave-pos="1"] + li[data-wave-pos="0"]::before,
#hub-path > li[data-wave-pos="4"] + li[data-wave-pos="0"]::before { display: none; }

/* Suppress bridge on the very first list-item (nothing above it) */
#hub-path > li:first-child::before { display: none; }

/* Suppress bridge on the first node after any chapter header — the
   chapter header's ::after already draws the vertical connection. */
#hub-path > li[data-wave-pos="0"] + li::before { display: none; }

/* First chapter header has no predecessor — suppress its bridge and
   the upward spine stub (keep only the downward half of ::after). */
#hub-path > li[data-wave-pos="0"]:first-child::before { display: none; }
#hub-path > li[data-wave-pos="0"]:first-child::after  { top: 50%; }

/* ── LAST-ATTEMPTED RESUME HIGHLIGHT ──────────────────────── */
/*
 * Applied by highlightLastAttempted() in hub.js to the <li> whose
 * challenge_id has the most recent last_updated_at in student_progress.
 * Amber-gold pulsing glow on the card draws the eye without clashing
 * with chapter accent colors (blue/yellow palette only — no green/red).
 * Overrides the chapter border-color via cascade position (appears after
 * all hub-node--* card rules above).
 */
.hub-node--last-attempted .hub-node-card {
    border-color: #FBBF24;
    animation: hub-resume-glow 2.6s ease-in-out infinite;
}

@keyframes hub-resume-glow {
    0%, 100% {
        box-shadow: 0 0 0 2px rgba(251, 191, 36, 0.50),
                    0 4px 18px rgba(251, 191, 36, 0.25);
    }
    50% {
        box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.80),
                    0 4px 28px rgba(251, 191, 36, 0.45);
    }
}

/* ── CHAPTER SKIP BUTTON ────────────────────────────────────── */
.hub-chapter-skip-btn {
    background: none;
    border: none;
    padding: 0;
    margin-top: 5px;
    font-size: 13px;
    color: var(--text-muted);
    cursor: pointer;
    text-align: left;
    text-decoration: none;
    font-family: inherit;
    line-height: 1.4;
}
.hub-chapter-skip-btn:hover { text-decoration: underline; text-underline-offset: 2px; }
.hub-chapter-skip-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

