<template>
    <div class="growth-stage-timeline">
        <div class="growth-stage-timeline__scroll" ref="scrollRef">
            <div class="growth-stage-timeline__inner" :style="innerStyle">
                <!-- 轨道：横线 + 节点 + 拖动手柄 -->
                <div class="growth-stage-timeline__track" ref="trackRef">
                    <div class="growth-stage-timeline__track-line" aria-hidden="true"></div>
                    <div
                        class="growth-stage-timeline__track-grid"
                        :style="{ gridTemplateColumns: gridCols }"
                    >
                        <div
                            v-for="(_, i) in normalizedStages"
                            :key="'dot-' + i"
                            class="growth-stage-timeline__dot-wrap"
                        >
                            <span class="growth-stage-timeline__dot"></span>
                        </div>
                    </div>

                    <div
                        ref="handleRef"
                        class="growth-stage-timeline__handle"
                        :style="handleStyle"
                        @pointerdown.stop.prevent="onHandlePointerDown"
                    >
                        <div class="growth-stage-timeline__handle-core">
                            <div
                                v-if="showHandleTooltip"
                                class="growth-stage-timeline__tooltip-wrap"
                            >
                                <div
                                    ref="tooltipBubbleRef"
                                    class="growth-stage-timeline__tooltip"
                                    :style="tooltipBubbleStyle"
                                >
                                    {{ displayTooltipText }}
                                </div>
                                <div
                                    class="growth-stage-timeline__tooltip-caret"
                                    aria-hidden="true"
                                ></div>
                            </div>
                            <div
                                class="growth-stage-timeline__handle-body"
                                :class="{
                                    'growth-stage-timeline__handle-body--wide':
                                        activeLabelIsShort,
                                }"
                            >
                                <span class="growth-stage-timeline__handle-bar"></span>
                                <span class="growth-stage-timeline__handle-bar"></span>
                                <span class="growth-stage-timeline__handle-bar"></span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 阶段文案 + 绿色标签 -->
                <div
                    class="growth-stage-timeline__labels"
                    :style="{ gridTemplateColumns: gridCols }"
                >
                    <div
                        v-for="(stage, i) in normalizedStages"
                        :key="'lb-' + i"
                        class="growth-stage-timeline__label-col"
                        :class="{
                            'growth-stage-timeline__label-col--wide':
                                isShortStageLabel(stage.label),
                        }"
                    >
                        <div
                            class="growth-stage-timeline__label-text"
                            :class="{
                                'growth-stage-timeline__label-text--active':
                                    i === activeIndex,
                            }"
                        >
                            {{ stage.label }}
                        </div>
                        <div
                            v-if="stage.tags && stage.tags.length"
                            class="growth-stage-timeline__tags"
                        >
                            <span
                                v-for="(tag, ti) in stage.tags"
                                :key="ti"
                                class="growth-stage-timeline__tag"
                            >{{ tag }}</span>
                        </div>
                    </div>
                </div>

                <!-- 生育期卡片：与上方阶段列同网格对齐，随横向滚动联动 -->
                <div
                    class="growth-stage-timeline__bg"
                    :style="{ gridTemplateColumns: gridCols }"
                >
                    <div
                        v-for="(run, ri) in periodRuns"
                        :key="'bg-run-' + ri"
                        class="growth-stage-timeline__bg-cell growth-stage-timeline__bg-cell--period"
                        :class="{
                            'growth-stage-timeline__bg-cell--active':
                                ri === activePeriodRunIndex,
                        }"
                        :style="{ gridColumn: `span ${run.span}` }"
                    >
                        <div class="growth-stage-timeline__period-title">
                            {{ run.periodTitle }}
                        </div>
                        <div class="growth-stage-timeline__period-sub">
                            {{ run.periodSubtitle }}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import {
    computed,
    ref,
    watch,
    onMounted,
    onBeforeUnmount,
    nextTick,
} from "vue";
import { useI18n } from "@/i18n";

/**
 * @typedef {Object} GrowthStageItem
 * @property {string} label 节点文案，如「60%展开」
 * @property {string[]} [tags] 绿色标签，如 ['最佳给肥点']
 * @property {string} periodTitle 生育期大标题
 * @property {string} periodSubtitle 生育期描述小字
 * @property {string} [phenophase_code] 物候期编码，由接口/父组件写入
 */

const props = defineProps({
    /** @type {import('vue').PropType<GrowthStageItem[]>} */
    stages: {
        type: Array,
        default: () => [],
    },
    /** 当前选中的阶段索引（与 v-model 同步）；不传时为中间一档 */
    modelValue: {
        type: Number,
        default: undefined,
    },
    tooltipText: {
        type: String,
        default: "此为预估进程，请左右移动进行校准!",
    },
    /** 每列最小宽度（px），列数多时可横向滚动 */
    minColWidth: {
        type: Number,
        default: 72,
    },
});

const emit = defineEmits(["update:modelValue", "change", "scrollSettled", "locale-change"]);

const { t, locale } = useI18n();

const DEFAULT_TOOLTIP_ZH = "此为预估进程，请左右移动进行校准!";

const displayTooltipText = computed(() => {
    if (!props.tooltipText || props.tooltipText === DEFAULT_TOOLTIP_ZH) {
        return t("growthStageTimeline.tooltipHint");
    }
    return t(props.tooltipText);
});

watch(locale, () => {
    emit("locale-change");
});

const scrollRef = ref(null);
const trackRef = ref(null);
const handleRef = ref(null);
const tooltipBubbleRef = ref(null);

/** 气泡相对手柄水平中心的额外偏移（px），用于避免贴边时被 overflow 裁切 */
const tooltipShiftPx = ref(0);

const TOOLTIP_EDGE_MARGIN_PX = 8;

/** 本次进入页面内展示；拖动手柄产生位移后关闭，下次路由/页面再进入会重新挂载并再次显示 */
const showHandleTooltip = ref(true);

const normalizedStages = computed(() =>
    Array.isArray(props.stages) ? props.stages : []
);

const colCount = computed(() =>
    Math.max(1, normalizedStages.value.length)
);

/** time_discribe 文案过短（<3 字）时，该列占 3 个普通点宽度，便于下方标签展示 */
const SHORT_LABEL_MAX_LEN = 3;
const SHORT_LABEL_COL_WEIGHT = 3;

function isShortStageLabel(label) {
    return String(label ?? "").length < SHORT_LABEL_MAX_LEN;
}

function getStageColumnWeight(stage) {
    return isShortStageLabel(stage?.label) ? SHORT_LABEL_COL_WEIGHT : 1;
}

const columnWeights = computed(() =>
    normalizedStages.value.map((stage) => getStageColumnWeight(stage))
);

const totalColumnWeight = computed(() =>
    Math.max(
        1,
        columnWeights.value.reduce((sum, weight) => sum + weight, 0)
    )
);

const gridCols = computed(() => {
    const stages = normalizedStages.value;
    if (!stages.length) {
        return `minmax(${props.minColWidth}px, 1fr)`;
    }
    return stages
        .map((stage) => {
            const weight = getStageColumnWeight(stage);
            return `minmax(${weight * props.minColWidth}px, ${weight}fr)`;
        })
        .join(" ");
});

/** 左右留白：手柄 translate(-50%) 与气泡在首尾否则会溢出滚动宽度，且气泡换行会拉高整列导致视觉上“掉下去” */
const INNER_EDGE_PAD_PX = 12;

const innerStyle = computed(() => {
    const minContentWidth = columnWeights.value.reduce(
        (sum, weight) => sum + weight * props.minColWidth,
        0
    );
    return {
        boxSizing: "border-box",
        minWidth: `${minContentWidth + INNER_EDGE_PAD_PX * 2}px`,
        paddingLeft: `${INNER_EDGE_PAD_PX}px`,
        paddingRight: `${INNER_EDGE_PAD_PX}px`,
    };
});

function periodKey(stage) {
    const s = stage || {};
    return `${s.periodTitle || ""}\0${s.periodSubtitle || ""}`;
}

/** 连续相同生育期合并为一段，用于背景区 grid-column span */
const periodRuns = computed(() => {
    const list = normalizedStages.value;
    if (!list.length) {
        return [
            {
                span: 1,
                periodTitle: "",
                periodSubtitle: "",
            },
        ];
    }
    const runs = [];
    let i = 0;
    while (i < list.length) {
        const key = periodKey(list[i]);
        let span = 1;
        let j = i + 1;
        while (j < list.length && periodKey(list[j]) === key) {
            span++;
            j++;
        }
        runs.push({
            span,
            periodTitle: list[i].periodTitle ?? "",
            periodSubtitle: list[i].periodSubtitle ?? "",
        });
        i = j;
    }
    return runs;
});

/** 生育期卡片列宽与上方阶段列对齐：每段占 span 列，fr 比例与阶段网格一致 */
const periodGridCols = computed(() => {
    const runs = periodRuns.value;
    if (!runs.length) {
        return `minmax(${props.minColWidth}px, 1fr)`;
    }
    return runs
        .map(
            (run) =>
                `minmax(${run.span * props.minColWidth}px, ${run.span}fr)`
        )
        .join(" ");
});

function clampStageIndex(v) {
    const last = Math.max(0, colCount.value - 1);
    return Math.min(Math.max(0, v), last);
}

/** 项数为 n 时默认选中索引 floor((n-1)/2)，偶数个时偏左中间 */
function middleStageIndex() {
    const n = colCount.value;
    return Math.max(0, Math.floor((n - 1) / 2));
}

const activeIndex = ref(0);

const activeLabelIsShort = computed(() =>
    isShortStageLabel(normalizedStages.value[activeIndex.value]?.label)
);

watch(
    [colCount, () => props.modelValue],
    () => {
        const mv = props.modelValue;
        const hasParentIndex = mv !== undefined && mv !== null;
        const next = hasParentIndex
            ? clampStageIndex(mv)
            : middleStageIndex();
        activeIndex.value = next;
        // 仅在没有父级索引时回写默认档，避免覆盖父组件按物候编码算好的下标
        if (!hasParentIndex) {
            nextTick(() => {
                emit("update:modelValue", next);
            });
        }
    },
    { immediate: true }
);

/** 手柄水平位置：0~1，对应轨道宽度 */
const handleRatio = ref(0);

function stageIndexToPeriodRunIndex(stageIdx) {
    let start = 0;
    for (let ri = 0; ri < periodRuns.value.length; ri++) {
        const span = periodRuns.value[ri].span;
        if (stageIdx >= start && stageIdx < start + span) {
            return ri;
        }
        start += span;
    }
    return 0;
}

/** 视口中心（手柄）所在生育期段索引，随滚动/拖动实时高亮 */
const activePeriodRunIndex = computed(() =>
    stageIndexToPeriodRunIndex(ratioToIndex(handleRatio.value))
);

function indexToRatio(idx) {
    const weights = columnWeights.value;
    const total = totalColumnWeight.value;
    if (weights.length <= 1) return 0.5;
    let start = 0;
    for (let i = 0; i < idx; i++) {
        start += weights[i] ?? 1;
    }
    const center = start + (weights[idx] ?? 1) / 2;
    return center / total;
}

function ratioToIndex(r) {
    const weights = columnWeights.value;
    const total = totalColumnWeight.value;
    const n = weights.length;
    if (n <= 1) return 0;
    const target = Math.min(Math.max(0, r), 1) * total;
    let acc = 0;
    let bestIdx = 0;
    let bestDist = Infinity;
    for (let i = 0; i < n; i++) {
        const center = acc + (weights[i] ?? 1) / 2;
        const dist = Math.abs(target - center);
        if (dist < bestDist) {
            bestDist = dist;
            bestIdx = i;
        }
        acc += weights[i] ?? 1;
    }
    return bestIdx;
}

/** 禁止在轨道上横向拖滚：仅在手柄拖动时由脚本更新 scrollLeft */
let scrollAreaTouchStartX = 0;
let scrollAreaTouchStartY = 0;

function onScrollAreaTouchStart(e) {
    if (!e.touches?.length) return;
    scrollAreaTouchStartX = e.touches[0].clientX;
    scrollAreaTouchStartY = e.touches[0].clientY;
}

function onScrollAreaTouchMove(e) {
    if (!e.touches?.length) return;
    const dx = e.touches[0].clientX - scrollAreaTouchStartX;
    const dy = e.touches[0].clientY - scrollAreaTouchStartY;
    if (Math.abs(dx) > Math.abs(dy)) {
        e.preventDefault();
    }
}

function getScrollLayout() {
    const scrollEl = scrollRef.value;
    if (!scrollEl) return null;
    const inner = scrollEl.querySelector(".growth-stage-timeline__inner");
    if (!inner) return null;
    const w = inner.offsetWidth;
    const cw = scrollEl.clientWidth;
    const maxScroll = Math.max(0, scrollEl.scrollWidth - cw);
    const pad = INNER_EDGE_PAD_PX;
    const contentW = Math.max(0, w - pad * 2);
    return { scrollEl, cw, maxScroll, pad, contentW };
}

/** 滚动缓动系数，越小滚动越慢（0~1） */
const SCROLL_LERP = 0.08;

let scrollTargetLeft = null;
let scrollAnimRafId = null;

function getPeriodRunBounds(runIdx) {
    let stageStart = 0;
    for (let ri = 0; ri < runIdx; ri++) {
        stageStart += periodRuns.value[ri].span;
    }
    const span = periodRuns.value[runIdx]?.span ?? 1;
    const weights = columnWeights.value;
    const total = totalColumnWeight.value;
    if (!weights.length) {
        return { startRatio: 0, endRatio: 1, centerRatio: 0.5 };
    }
    let weightStart = 0;
    for (let i = 0; i < stageStart; i++) {
        weightStart += weights[i] ?? 1;
    }
    let weightSpan = 0;
    for (let i = stageStart; i < stageStart + span; i++) {
        weightSpan += weights[i] ?? 1;
    }
    return {
        startRatio: weightStart / total,
        endRatio: (weightStart + weightSpan) / total,
        centerRatio: (weightStart + weightSpan / 2) / total,
    };
}

function ratioToScrollLeft(ratio, stageIdx = null) {
    const m = getScrollLayout();
    if (!m) return null;
    const { cw, maxScroll, pad, contentW } = m;
    const r = Math.min(Math.max(0, ratio), 1);
    const handleCenterX = pad + r * contentW;

    const idx =
        stageIdx != null
            ? clampStageIndex(stageIdx)
            : ratioToIndex(ratio);
    const runIdx = stageIndexToPeriodRunIndex(idx);
    const { startRatio, endRatio } = getPeriodRunBounds(runIdx);
    const periodLeft = pad + startRatio * contentW;
    const periodRight = pad + endRatio * contentW;
    const periodWidth = periodRight - periodLeft;

    let left = handleCenterX - cw / 2;
    if (periodWidth <= cw) {
        if (periodLeft < left) left = periodLeft;
        if (periodRight > left + cw) left = periodRight - cw;
    } else {
        left = Math.max(periodLeft, Math.min(left, periodRight - cw));
    }

    return Math.max(0, Math.min(left, maxScroll));
}

function cancelScrollAnimation() {
    if (scrollAnimRafId != null) {
        cancelAnimationFrame(scrollAnimRafId);
        scrollAnimRafId = null;
    }
}

function runScrollAnimation() {
    const scrollEl = scrollRef.value;
    if (!scrollEl || scrollTargetLeft == null) {
        scrollAnimRafId = null;
        return;
    }
    const current = scrollEl.scrollLeft;
    const diff = scrollTargetLeft - current;
    if (Math.abs(diff) < 0.5) {
        scrollEl.scrollLeft = scrollTargetLeft;
        scrollTargetLeft = null;
        scrollAnimRafId = null;
        return;
    }
    scrollEl.scrollLeft = current + diff * SCROLL_LERP;
    scrollAnimRafId = requestAnimationFrame(runScrollAnimation);
}

function applyScrollToRatio(ratio, immediate = false, stageIdx = null) {
    const left = ratioToScrollLeft(ratio, stageIdx);
    if (left == null) return;
    const scrollEl = scrollRef.value;
    if (!scrollEl) return;

    scrollTargetLeft = left;
    if (immediate) {
        cancelScrollAnimation();
        scrollEl.scrollLeft = left;
        scrollTargetLeft = null;
        return;
    }
    if (scrollAnimRafId == null) {
        scrollAnimRafId = requestAnimationFrame(runScrollAnimation);
    }
}

/** 将轨道上的比例位置（0~1，与手柄 left 一致）滚到视口水平中央 */
function scrollToCenterRatio(ratio, behavior = "smooth", stageIdx = null) {
    applyScrollToRatio(ratio, behavior === "auto", stageIdx);
}

function syncScrollToRatio(ratio, immediate = false) {
    applyScrollToRatio(ratio, immediate, ratioToIndex(ratio));
}

function onTimelineWheel(e) {
    if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {
        e.preventDefault();
    }
}

watch(
    [activeIndex, colCount],
    () => {
        handleRatio.value = indexToRatio(activeIndex.value);
        nextTick(() => {
            scrollToCenterRatio(
                indexToRatio(activeIndex.value),
                "smooth",
                activeIndex.value
            );
            clampTooltipToScrollArea();
        });
    },
    { immediate: true }
);

watch(showHandleTooltip, (v) => {
    if (v) clampTooltipToScrollArea();
});

watch(
    () => handleRatio.value,
    () => {
        if (showHandleTooltip.value) clampTooltipToScrollArea();
    }
);

let resizeObserver = null;

const handleStyle = computed(() => ({
    left: `${handleRatio.value * 100}%`,
}));

const tooltipBubbleStyle = computed(() => ({
    transform: `translateX(${tooltipShiftPx.value}px)`,
}));

/**
 * 以滚动可视区为边界，将气泡水平平移最小距离使其完整可见；箭头留在手柄中心（见模板结构）。
 */
function clampTooltipToScrollArea() {
    if (!showHandleTooltip.value) return;
    const scrollEl = scrollRef.value;
    const bubbleEl = tooltipBubbleRef.value;
    if (!scrollEl || !bubbleEl) return;

    tooltipShiftPx.value = 0;
    nextTick(() => {
        requestAnimationFrame(() => {
            const b = scrollEl.getBoundingClientRect();
            const t = bubbleEl.getBoundingClientRect();
            const pad = TOOLTIP_EDGE_MARGIN_PX;
            const sLow = b.left + pad - t.left;
            const sHigh = b.right - pad - t.right;
            let s = 0;
            if (sLow <= sHigh) {
                if (sLow <= 0 && sHigh >= 0) s = 0;
                else if (sLow > 0) s = sLow;
                else s = sHigh;
            } else {
                s = (sLow + sHigh) / 2;
            }
            tooltipShiftPx.value = s;
        });
    });
}

let dragging = false;
let activePointerId = null;
/** 本次按下后是否发生过 pointermove（视为“移动过”） */
let movedDuringHandleDrag = false;

function getTrackRect() {
    return trackRef.value?.getBoundingClientRect() || null;
}

function clientXToRatio(clientX) {
    const rect = getTrackRect();
    if (!rect || rect.width <= 0) return handleRatio.value;
    const x = clientX - rect.left;
    const r = x / rect.width;
    return Math.min(Math.max(0, r), 1);
}

function onHandlePointerDown(e) {
    if (!trackRef.value) return;
    dragging = true;
    movedDuringHandleDrag = false;
    activePointerId = e.pointerId;
    try {
        handleRef.value?.setPointerCapture(e.pointerId);
    } catch (_) {
        /* ignore */
    }
    handleRatio.value = clientXToRatio(e.clientX);
    syncScrollToRatio(handleRatio.value);
    document.body.style.userSelect = "none";
}

function onPointerMove(e) {
    if (!dragging || e.pointerId !== activePointerId) return;
    movedDuringHandleDrag = true;
    handleRatio.value = clientXToRatio(e.clientX);
    syncScrollToRatio(handleRatio.value);
    if (showHandleTooltip.value) clampTooltipToScrollArea();
}

function onPointerUp(e) {
    if (!dragging || e.pointerId !== activePointerId) return;
    dragging = false;
    activePointerId = null;
    document.body.style.userSelect = "";
    try {
        handleRef.value?.releasePointerCapture(e.pointerId);
    } catch (_) {
        /* ignore */
    }
    const nextIdx = ratioToIndex(handleRatio.value);
    activeIndex.value = nextIdx;
    handleRatio.value = indexToRatio(nextIdx);
    syncScrollToRatio(handleRatio.value);
    if (movedDuringHandleDrag) {
        showHandleTooltip.value = false;
    }
    movedDuringHandleDrag = false;
    emit("update:modelValue", nextIdx);
    armScrollSettledAfterHandle();
}

/** 手柄松开后待「横向滚动结束」再向父组件派发 change / scrollSettled */
let pendingScrollSettled = false;
let scrollSettledFallbackTimer = null;
let scrollSettledDebounceTimer = null;

function clearScrollSettledTimers() {
    if (scrollSettledFallbackTimer != null) {
        clearTimeout(scrollSettledFallbackTimer);
        scrollSettledFallbackTimer = null;
    }
    if (scrollSettledDebounceTimer != null) {
        clearTimeout(scrollSettledDebounceTimer);
        scrollSettledDebounceTimer = null;
    }
}

function emitScrollSettledIfPending() {
    if (!pendingScrollSettled) return;
    pendingScrollSettled = false;
    clearScrollSettledTimers();
    const idx = activeIndex.value;
    const stage = normalizedStages.value[idx];
    const phenophaseCode = stage?.phenophase_code;
    emit("change", idx, stage, phenophaseCode);
    emit("scrollSettled", idx, stage, phenophaseCode);
}

function armScrollSettledAfterHandle() {
    pendingScrollSettled = true;
    clearScrollSettledTimers();
    scrollSettledFallbackTimer = setTimeout(() => {
        scrollSettledFallbackTimer = null;
        emitScrollSettledIfPending();
    }, 200);
}

function onScrollAreaScroll() {
    if (showHandleTooltip.value) clampTooltipToScrollArea();
    if (!pendingScrollSettled) return;
    if (scrollSettledDebounceTimer != null) {
        clearTimeout(scrollSettledDebounceTimer);
    }
    scrollSettledDebounceTimer = setTimeout(() => {
        scrollSettledDebounceTimer = null;
        emitScrollSettledIfPending();
    }, 80);
}

function onScrollAreaScrollEnd() {
    emitScrollSettledIfPending();
}

function onWindowResize() {
    if (showHandleTooltip.value) clampTooltipToScrollArea();
}

onMounted(() => {
    window.addEventListener("pointermove", onPointerMove);
    window.addEventListener("pointerup", onPointerUp);
    window.addEventListener("pointercancel", onPointerUp);
    window.addEventListener("resize", onWindowResize);
    const el = scrollRef.value;
    el?.addEventListener("scroll", onScrollAreaScroll, { passive: true });
    el?.addEventListener("scrollend", onScrollAreaScrollEnd, { passive: true });
    el?.addEventListener("wheel", onTimelineWheel, { passive: false });
    nextTick(() => clampTooltipToScrollArea());
    el?.addEventListener("touchstart", onScrollAreaTouchStart, {
        passive: true,
    });
    el?.addEventListener("touchmove", onScrollAreaTouchMove, {
        passive: false,
    });
    resizeObserver =
        typeof ResizeObserver !== "undefined"
            ? new ResizeObserver(() => {
                  nextTick(() => {
                      scrollToCenterRatio(
                          indexToRatio(activeIndex.value),
                          "auto",
                          activeIndex.value
                      );
                      clampTooltipToScrollArea();
                  });
              })
            : null;
    if (el && resizeObserver) {
        resizeObserver.observe(el);
    }
});

onBeforeUnmount(() => {
    window.removeEventListener("pointermove", onPointerMove);
    window.removeEventListener("pointerup", onPointerUp);
    window.removeEventListener("pointercancel", onPointerUp);
    window.removeEventListener("resize", onWindowResize);
    const el = scrollRef.value;
    el?.removeEventListener("scroll", onScrollAreaScroll);
    el?.removeEventListener("scrollend", onScrollAreaScrollEnd);
    el?.removeEventListener("wheel", onTimelineWheel);
    el?.removeEventListener("touchstart", onScrollAreaTouchStart);
    el?.removeEventListener("touchmove", onScrollAreaTouchMove);
    resizeObserver?.disconnect();
    resizeObserver = null;
    cancelScrollAnimation();
    clearScrollSettledTimers();
    pendingScrollSettled = false;
});
</script>

<style scoped lang="scss">
.growth-stage-timeline {
    width: 100%;
    overflow: hidden;
}

.growth-stage-timeline__scroll {
    overflow-x: hidden;
    overflow-y: visible;
    touch-action: pan-y;
    overscroll-behavior-x: none;
    -webkit-overflow-scrolling: touch;
}

.growth-stage-timeline__inner {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding-top: 36px;
    padding-bottom: 8px;
    width: 100%;
}

.growth-stage-timeline__bg {
    display: grid;
    align-items: stretch;
    width: 100%;
    margin-top: 8px;
    gap: 0;
}

.growth-stage-timeline__bg-cell {
    background: #f5f5f5;
    padding: 12px 8px;
    text-align: left;
    box-sizing: border-box;
    border: none;
    border-top: 1px solid #d9d9d9;
    border-radius: 8px;
    min-width: 0;
    margin: 0 2px;
    transition: background-color 0.2s, border-color 0.2s;

    &:first-child {
        margin-left: 0;
    }

    &:last-child {
        margin-right: 0;
    }

    &--period {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: flex-start;
        gap: 3px;
    }

    &--active {
        background: #e6f4ff;
        border-top-width: 3px;
        border-top-color: #1890ff;

        .growth-stage-timeline__period-title {
            color: #1d2129;
            font-weight: 600;
        }

        .growth-stage-timeline__period-sub {
            color: #666;
        }
    }

    &:not(&--active) {
        .growth-stage-timeline__period-title {
            color: #8c8c8c;
            font-weight: 500;
        }

        .growth-stage-timeline__period-sub {
            color: #bfbfbf;
        }
    }
}

.growth-stage-timeline__period-title {
    font-size: 15px;
    font-weight: 600;
    color: #1d2129;
    text-align: left;
    max-width: 100%;
    word-break: break-word;
}

.growth-stage-timeline__period-sub {
    font-size: 12px;
    color: #666;
    text-align: left;
    max-width: 100%;
    word-break: break-word;
    white-space: normal;
}

.growth-stage-timeline__track {
    position: relative;
    min-height: 48px;
}

.growth-stage-timeline__track-line {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 1px;
    margin-top: -0.5px;
    background: #e8e8e8;
    pointer-events: none;
    z-index: 0;
}

.growth-stage-timeline__track-grid {
    position: relative;
    z-index: 1;
    display: grid;
    align-items: center;
    min-height: 48px;
    width: 100%;
}

.growth-stage-timeline__dot-wrap {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    pointer-events: none;
}

.growth-stage-timeline__dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #CDCDCD;
    border: 1px solid #fff;
    box-sizing: border-box;
    box-shadow: 0px 2px 3px 0px #00000012;

}

.growth-stage-timeline__handle {
    position: absolute;
    top: 50%;
    z-index: 2;
    transform: translate(-50%, -50%);
    touch-action: none;
    cursor: grab;

    &:active {
        cursor: grabbing;
    }
}

.growth-stage-timeline__handle-core {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.growth-stage-timeline__tooltip-wrap {
    position: absolute;
    left: 50%;
    bottom: 100%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 8px;
    pointer-events: none;
    z-index: 3;
}

.growth-stage-timeline__tooltip {
    max-width: min(240px, calc(100vw - 24px));
    white-space: nowrap;
    padding: 6px 12px;
    border-radius: 999px;
    background: #8c8c8c;
    color: #fff;
    font-size: 11px;
    line-height: 1.4;
    text-align: center;
}

.growth-stage-timeline__tooltip-caret {
    width: 0;
    height: 0;
    margin-top: -1px;
    border-width: 5px 5px 0 5px;
    border-style: solid;
    border-color: #8c8c8c transparent transparent transparent;
}

.growth-stage-timeline__handle-body {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: 2px;
    width: 16px;
    height: 30px;
    border-radius: 7px;
    background: #1890ff;
    box-shadow: 0 2px 6px rgba(24, 144, 255, 0.35);
    transition: width 0.2s;

    &--wide {
        width: 48px;
        gap: 4px;
        border-radius: 10px;
    }
}

.growth-stage-timeline__handle-bar {
    display: block;
    width: 2px;
    height: 10px;
    border-radius: 1px;
    background: #fff;
}

.growth-stage-timeline__labels {
    display: grid;
    margin-top: 2px;
    gap: 0;
    width: 100%;
}

.growth-stage-timeline__label-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 0 4px 4px;
    box-sizing: border-box;
    min-width: 0;

    &--wide {
        .growth-stage-timeline__label-text {
            max-width: 100%;
            white-space: nowrap;
        }
    }
}

.growth-stage-timeline__label-text {
    font-size: 11px;
    color: #bfbfbf;
    width: max-content;
    word-break: break-all;
    transition: color 0.2s, font-size 0.2s;

    &--active {
        font-size: 14px;
        color: #1890ff;
        font-weight: 600;
    }
}

.growth-stage-timeline__tags {
    margin-top: 6px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 100%;
}

.growth-stage-timeline__tag {
    display: inline-block;
    max-width: 100%;
    padding: 2px 6px;
    border-radius: 4px;
    background: #00a870;
    color: #fff;
    font-size: 10px;
    line-height: 1.3;
    word-break: break-all;
}
</style>
