/* ===================================================================
 * Journey Map V3 — Stylesheet
 * Created: 2026-09-11
 * Spec: gameplay_v3_journeyline.md
 * Purpose: Styles for the interactive sine-wave journey map page.
 * =================================================================== */

/* --------------- Custom Properties (theming) --------------- */
:root {
    --jm-card-color: #4A90D9;
    --jm-card-color-30: rgba(74, 144, 217, 0.30);
    --jm-bg: #D6E4F0;
    --jm-text-primary: #1A1D1F;
    --jm-text-muted: #B0A8B8;
    --jm-locked-fill: #E8E3EE;
    --jm-bonus-green: #6AF79C;
    --jm-stage-size: 52px;
    --jm-ring-size: 66px;
    --jm-bonus-size: 52px;
    --jm-fade-height: 50px;
    --jm-header-height: 72px;
    --jm-top-fade-height: calc(var(--jm-header-height) + 44px);
}

/* --------------- Page Layout --------------- */
.jm-page {
    background-color: var(--jm-bg);
    min-height: 100vh;
    min-height: 100dvh;
    position: relative;
    overflow: hidden;
    font-family: "SF Pro Display", "SF Pro", -apple-system, BlinkMacSystemFont,
        "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* --------------- Header (compact pill card) --------------- */
.jm-header {
    position: absolute;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    display: flex;
    align-items: center;
    max-width: 280px;
    padding: 8px 16px;
    background: #FFFFFF;
    border-radius: 16px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10);
}

.jm-header__illustration {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    object-fit: cover;
    margin-right: 10px;
    flex-shrink: 0;
}

.jm-header__title {
    font-size: 16px;
    font-weight: 700;
    color: var(--jm-text-primary);
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jm-header__icon {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    margin-left: 8px;
}

/* --------------- Scroll Container --------------- */
.jm-scroll-container {
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    overflow-x: hidden;
    position: relative;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.jm-scroll-container::-webkit-scrollbar {
    display: none;
}

/* --------------- Timeline Canvas (positioned children) --------------- */
.jm-timeline {
    position: relative;
    width: 100%;
    /* Height is set dynamically by JS based on total items */
}

/* --------------- Stage Marker (common) --------------- */
.jm-stage {
    position: absolute;
    width: var(--jm-stage-size);
    height: var(--jm-stage-size);
    z-index: 5;
    transform: translate(-50%, -50%);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.jm-stage svg {
    width: 100%;
    height: 100%;
    display: block;
}

.jm-stage__number {
    position: absolute;
    top: calc(38% + 2px);
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 20px;
    font-weight: 600;
    pointer-events: none;
    z-index: 2;
    line-height: 1;
    user-select: none;
}

/* --------------- Stage States --------------- */

/* Completed: card-color tint, white number */
.jm-stage--completed .jm-stage__number {
    color: #FFFFFF;
}

/* Next: white fill, colored border, dark number */
.jm-stage--next {
    z-index: 6;
}

.jm-stage--next .jm-stage__number {
    color: #FFFFFF;
}

/* Locked: gray, muted number, not tappable */
.jm-stage--locked {
    cursor: default;
}

.jm-stage--locked .jm-stage__number {
    color: var(--jm-text-muted);
}

/* Skipped: same as completed but 50% opacity */
.jm-stage--skipped {
    opacity: 0.5;
}

.jm-stage--skipped .jm-stage__number {
    color: #FFFFFF;
}

/* --------------- Pointer feedback (accessible stages only) -------- */
.jm-stage:not(.jm-stage--locked) {
    transition: transform 140ms ease-out;
}

@media (hover: hover) and (pointer: fine) {
    .jm-stage:not(.jm-stage--locked):hover {
        transform: translate(-50%, -50%) scale(1.1);
    }
}

.jm-stage:not(.jm-stage--locked):active {
    transform: translate(-50%, calc(-50% + 2px)) scale(0.97);
    transition-duration: 70ms;
}

@media (prefers-reduced-motion: reduce) {
    .jm-stage:not(.jm-stage--locked) {
        transition: none;
    }
}

/* --------------- Outer Ring (Next stage) --------------- */
.jm-ring {
    position: absolute;
    width: var(--jm-ring-size);
    height: calc(var(--jm-ring-size) - 6px);
    border-radius: 50%;
    border: 3px solid #B0B8C1;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(1);
    pointer-events: none;
    z-index: -1;
}

/* --------------- Animations --------------- */

/* Outer-ring pulse: scale 1.0 → 1.15 → 1.0 */
@keyframes jm-ring-pulse {
    0%, 100% { transform: translate(-50%, -50%) scale(1.0); }
    50%      { transform: translate(-50%, -50%) scale(1.15); }
}

.jm-ring-pulse {
    animation: jm-ring-pulse 1.5s ease-in-out infinite;
}

/* Start bubble bounce: translateY 0 → -6px → 0 (must include translateX centering) */
@keyframes jm-start-bounce {
    0%, 100% { transform: translateX(-50%) translateY(0); }
    50%      { transform: translateX(-50%) translateY(-6px); }
}

.jm-start-bounce {
    animation: jm-start-bounce 1s ease-in-out infinite;
}

/* Character idle bob: translateY 0 → -4px → 0 */
@keyframes jm-char-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
}

.jm-char-bob {
    animation: jm-char-bob 3s ease-in-out infinite;
}

/* Lottie fade-out after playback */
@keyframes jm-lottie-fade {
    0%   { opacity: 1; }
    100% { opacity: 0; }
}

.jm-lottie-fade {
    animation: jm-lottie-fade 500ms ease-out forwards;
}

/* Just-earned bonus sparkles: grow, fade, and repeat out of phase. */
@keyframes jm-bonus-star-cycle {
    0% {
        opacity: 0.6;
        transform: translate(-50%, -50%) scale(0.5);
    }
    55% {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
    }
    100% {
        opacity: 0;
        transform: translate(-50%, -50%) scale(1);
    }
}

/* Reduced motion: disable all journey-map animations */
@media (prefers-reduced-motion: reduce) {
    .jm-ring-pulse,
    .jm-start-bounce,
    .jm-char-bob {
        animation: none !important;
    }

    .jm-lottie-fade {
        animation: none !important;
        opacity: 0;
    }

    .jm-bonus-star {
        animation: none !important;
        opacity: 1 !important;
        transform: translate(-50%, -50%) scale(1) !important;
    }
}

/* --------------- Start Bubble --------------- */
.jm-start-bubble {
    position: absolute;
    z-index: 8;
    display: flex;
    flex-direction: column;
    align-items: center;
    pointer-events: none;
    /* Positioned by JS relative to the next-stage marker */
}

.jm-start-bubble__pill {
    background: #FFFFFF;
    color: var(--jm-text-primary);
    font-size: 14px;
    font-weight: 600;
    padding: 4px 14px;
    border-radius: 12px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.10);
    white-space: nowrap;
    line-height: 1.3;
}

.jm-start-bubble__pointer {
    width: 0;
    height: 0;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-top: 6px solid #FFFFFF;
}

/* --------------- MP Label --------------- */
.jm-mp-label {
    position: absolute;
    z-index: 7;
    font-size: 14px;
    font-weight: 600;
    color: #9EA5AD;
    white-space: nowrap;
    pointer-events: none;
}

/* --------------- Edge Fades --------------- */
/* Fades sit outside the scroll container so they stay visually pinned.
   The .jm-page wrapper provides the positioning context. */
.jm-fade-top,
.jm-fade-bottom {
    position: absolute;
    left: 0;
    right: 0;
    height: var(--jm-fade-height);
    pointer-events: none;
    z-index: 15;
    opacity: 1;
    transition: opacity 200ms ease;
}

.jm-fade-top {
    top: 0;
    height: var(--jm-top-fade-height);
    background: linear-gradient(
        to bottom,
        var(--jm-bg) 0,
        var(--jm-bg) var(--jm-header-height),
        transparent 100%
    );
}

.jm-fade-bottom {
    bottom: 0;
    background: linear-gradient(to top, var(--jm-bg), transparent);
}

.jm-fade-top--hidden,
.jm-fade-bottom--hidden {
    opacity: 0;
}

/* --------------- Signpost (level demarcation) --------------- */
.jm-signpost {
    position: absolute;
    z-index: 4;
    transform: translate(-50%, -50%);
    width: 80px;
    pointer-events: none;
}

.jm-signpost svg {
    width: 100%;
    height: auto;
    display: block;
}

/* Tint the signpost label fill via custom property */
.jm-signpost .signpost-fill {
    fill: var(--jm-card-color);
}

.jm-signpost .signpost-text {
    fill: #FFFFFF;
    font-family: "SF Pro Display", "SF Pro", -apple-system, BlinkMacSystemFont,
        "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-weight: 700;
    font-size: 16px;
}

/* Dashed level demarcation line spanning container width — behind signpost SVG */
.jm-signpost__line {
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 0;
    border-top: 2px dashed #9EA5AD;
    z-index: -1;
    pointer-events: none;
}

/* --------------- Bonus (End-of-Level) Marker --------------- */
.jm-bonus-marker {
    position: absolute;
    width: var(--jm-bonus-size);
    height: var(--jm-bonus-size);
    z-index: 5;
    transform: translate(-50%, -50%);
    pointer-events: none;
    display: flex;
    align-items: center;
    justify-content: center;
}

.jm-bonus-marker svg {
    width: 100%;
    height: 100%;
    display: block;
}

.jm-bonus-marker__icon {
    position: absolute;
    top: calc(50% - 2px);
    left: 50%;
    transform: translate(-50%, -50%);
    width: 22px;
    height: 22px;
    pointer-events: none;
}

.jm-bonus-marker__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* Pending (not yet completed): green — native SVG color */
.jm-bonus-marker--pending {
    /* Native green color from SVG; no filter needed */
}

/* Collected (level completed): state hook only. An earned bonus stays in its
   native green (2026-09-23); bonus_marker_style decides the look. */
.jm-bonus-marker--collected {
    /* no filter: see .jm-bonus-marker--gray / .jm-element--future */
}

/* bonus_marker_style "gray" (2026-09-21): also used for an unfinished level
   behind the next stage, matching the locked stages beside it. */
.jm-bonus-marker--gray {
    filter: grayscale(1);
}

/* Keep the newly collected marker colored while its celebration plays. */
.jm-bonus-marker--celebrating {
    filter: none !important;
    opacity: 1 !important;
}

.jm-bonus-stars {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.jm-bonus-star {
    position: absolute;
    width: 16px;
    height: 16px;
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
    animation: jm-bonus-star-cycle 1.8s ease-out infinite;
}

.jm-bonus-star--1 {
    top: calc(50% - 31px);
}

.jm-bonus-star--2 {
    top: calc(50% - 20px);
    animation-delay: 300ms;
}

.jm-bonus-star--3 {
    top: calc(50% - 40px);
    animation-delay: 600ms;
}

.jm-bonus-stars--right .jm-bonus-star--1 {
    left: calc(50% + 25px);
}

.jm-bonus-stars--right .jm-bonus-star--2 {
    left: calc(50% + 39px);
}

.jm-bonus-stars--right .jm-bonus-star--3 {
    left: calc(50% + 53px);
}

.jm-bonus-stars--left .jm-bonus-star--1 {
    left: calc(50% - 25px);
}

.jm-bonus-stars--left .jm-bonus-star--2 {
    left: calc(50% - 39px);
}

.jm-bonus-stars--left .jm-bonus-star--3 {
    left: calc(50% - 53px);
}

/* Bonus MP label near the marker */
.jm-bonus-mp-label {
    position: absolute;
    z-index: 7;
    font-size: 14px;
    font-weight: 600;
    color: #9EA5AD;
    white-space: nowrap;
    pointer-events: none;
}

/* --------------- Decorations (characters, fire, etc.) --------------- */
.jm-decoration {
    position: absolute;
    z-index: 3;
    pointer-events: none;
    user-select: none;
    transform: translate(-50%, -50%);
}

.jm-decoration img,
.jm-decoration svg {
    height: 80px;
    width: auto;
    display: block;
}

.jm-decoration.jm-decoration--flipped img,
.jm-decoration.jm-decoration--flipped svg {
    transform: scaleX(-1);
}

.jm-decoration--grayscale {
    filter: grayscale(1);
    opacity: 0.7;
}

.jm-decoration--celebration-suppressed {
    visibility: hidden;
}

/* Future/locked elements below the next stage → grayscale */
.jm-element--future {
    filter: grayscale(1);
    opacity: 0.65;
}

/* --------------- Lottie Overlay --------------- */
.jm-lottie-overlay {
    position: absolute;
    z-index: 10;
    pointer-events: none;
    transform: translate(-50%, -50%);
}

.jm-lottie-overlay--flipped > svg {
    transform: scaleX(-1);
}

.jm-level-completion-mp {
    position: absolute;
    z-index: 10;
    color: var(--jm-card-color);
    font-size: 16px;
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
    transform: translate(-50%, -50%);
}

/* --------------- Responsive Adjustments --------------- */

/* Narrow phones */
@media (max-width: 359px) {
    :root {
        --jm-stage-size: 48px;
        --jm-ring-size: 60px;
    }
}

/* Tablets & desktop: allow wider layout, sizes stay consistent */
@media (min-width: 768px) {
    .jm-scroll-container {
        max-width: 600px;
        margin: 0 auto;
    }
}
