<script setup lang="ts">
import { MlflowService } from "@/components/service/mlflow/MlflowService";
import {
  computed,
  watch,
  ref,
  nextTick,
  onMounted,
  onBeforeUnmount,
} from "vue";
import Plotly from "plotly.js-dist-min";

const props = defineProps<{ experimentInfo: any }>();
const emit = defineEmits<{ (e: "close"): void }>();

/* ============ Tabs ============ */
const mainTab = ref<"details" | "viz">("details");
const vizTab = ref<"metrics" | "scatter" | "box" | "contour">("metrics");

/* ============ expName pick ============ */
function pickExpName(v: any): string {
  return v?.expName || v?.experiment || v?.name || v?.raw?.displayName || "";
}

/* ============ MLflow state ============ */
const runs = ref<any[]>([]);
const loadingRuns = ref(false);

/* --- 단건 조회 state --- */
const selectedRunId = ref<string>("");
const loadingRunDetail = ref(false);
const runDetail = ref<any | null>(null);

/* 표시용 라벨 */
const selectedLabel = computed(
  () => runDetail.value?.info?.run_name ?? runDetail.value?.info?.run_id ?? "-",
);

/* ============ Plotly refs ============ */
const elMetrics = ref<HTMLDivElement | null>(null);

/* ===== 유틸: 단건 값 꺼내기 ===== */
function metricValue(key: "accuracy" | "precision" | "recall" | "f1_score") {
  const m = (runDetail.value?.data?.metrics ?? []).find(
    (x: any) => x.key === key,
  );
  return m?.value ?? null;
}

/* 선택한 run의 메트릭 표 데이터 */
const selectedMetrics = computed(() => {
  const mm: Array<{ key: string; value: number }> =
    runDetail.value?.data?.metrics ?? [];
  return mm.map((m) => ({ key: m.key, value: m.value }));
});

/* ===== 부모에서 내려온 runId 픽 ===== */
function pickParentRunId(v: any): string {
  const cand = [
    v?.run_id,
    v?.runId,
    v?.raw?.run_id,
    v?.raw?.runId,
    v?.raw?.kfp_run_id,
    v?.raw?.kubeflow_run_id,
    v?.raw?.id,
  ].filter(Boolean);
  return String(cand[0] ?? "");
}

/* ===== MLflow 태그 읽기 (array or object 모두 대응) ===== */
function getTag(run: any, key: string): string | undefined {
  const tags = run?.data?.tags;
  if (Array.isArray(tags)) return tags.find((t: any) => t?.key === key)?.value;
  if (tags && typeof tags === "object") return tags[key];
  return undefined;
}

/* ===== 차트 렌더: 선택한 단건만 ===== */
function drawCharts() {
  const mm = selectedMetrics.value
    // value가 숫자인 것만 필터링
    .filter((m) => typeof m.value === "number" && isFinite(m.value));

  const x = mm.map((m) => m.key);
  const y = mm.map((m) => m.value);

  const layout: Partial<any> = {
    margin: { t: 40, r: 20, b: 60, l: 50 },
    height: 400,
    showlegend: false,
    paper_bgcolor: "rgba(0,0,0,0)",
    plot_bgcolor: "rgba(0,0,0,0)",

    font: { color: "#E0E0E0" },
    xaxis: {
      automargin: true,

      gridcolor: "rgba(255,255,255,0.08)",
      zerolinecolor: "rgba(255,255,255,0.18)",
      linecolor: "rgba(255,255,255,0.18)",
    },
    yaxis: {
      rangemode: "tozero",
      gridcolor: "rgba(255,255,255,0.08)",
      zerolinecolor: "rgba(255,255,255,0.18)",
      linecolor: "rgba(255,255,255,0.18)",
    },
  };

  const trace: any = {
    type: "bar",
    x,
    y,
    text: y.map((v) => (typeof v === "number" ? v.toFixed(4) : "")),
    textposition: "auto",
    hovertemplate: "%{x}: %{y}<extra></extra>",
  };

  const config = { displayModeBar: false, responsive: true };

  if (elMetrics.value) {
    if (x.length === 0) {
      Plotly.purge(elMetrics.value);
      elMetrics.value.innerHTML =
        '<div style="padding:16px;color:#999;text-align:center;">No Data</div>';
    } else {
      Plotly.react(elMetrics.value, [trace], layout, config);
    }
  }
}

function resizeCharts() {
  if (elMetrics.value) Plotly.Plots.resize(elMetrics.value);
}

/* ===== 응답 정규화 + fallback ===== */
function normalizeRun(res: any) {
  const v = res?.data?.run ?? res?.run ?? res?.data ?? res;
  return v?.info && v?.data ? v : null;
}
function findFromList(runId: string) {
  return (
    runs.value.find(
      (r) =>
        r?.info?.run_id === runId ||
        r?.info?.run_uuid === runId ||
        r?.info?.run_name === runId,
    ) ?? null
  );
}

async function fetchRuns(expName?: string) {
  const parentRunId = pickParentRunId(props.experimentInfo);
  if (!expName) {
    runs.value = [];
    selectedRunId.value = "";
    return;
  }

  loadingRuns.value = true;
  try {
    // 1) 실험명으로 experiment_id 조회
    const expRes = await MlflowService.getExperimentByName(expName);
    const exp = expRes?.data ?? expRes;
    const expId = String(
      exp?.experiment_id ?? exp?.experimentId ?? exp?.id ?? "",
    );
    if (!expId) {
      runs.value = [];
      selectedRunId.value = "";
      return;
    }

    // 2) experiment_id로 runs 전체 조회
    const runsRes = await MlflowService.getRuns(expId);
    const body = runsRes?.data ?? runsRes;
    const list =
      body?.runs ?? body?.data?.runs ?? (Array.isArray(body) ? body : []);

    // 3) 부모 runId 태그와 매칭 → 없으면 전체 리스트 사용(이전 동작처럼)
    const matched = (Array.isArray(list) ? list : []).filter(
      (r: any) => getTag(r, "kubeflow_run_id") === parentRunId,
    );
    const final = matched.length > 0 ? matched : list;

    // 최신순 정렬 + 기본 선택
    const sorted = [...final].sort(
      (a, b) => (b?.info?.start_time ?? 0) - (a?.info?.start_time ?? 0),
    );
    runs.value = sorted;
    selectedRunId.value =
      sorted[0]?.info?.run_id || sorted[0]?.info?.run_uuid || "";
  } finally {
    loadingRuns.value = false;
  }
}

const runItems = computed(() =>
  (runs.value || []).map((r: any) => {
    const id = r?.info?.run_id || r?.info?.run_uuid || "";
    const name = r?.info?.run_name || id; // ✅ 시간 제거, 이름만 표시
    return { value: id, label: name };
  }),
);

async function fetchRunDetail(runId: string) {
  if (!runId) {
    runDetail.value = null;
    await nextTick();
    drawCharts();
    return;
  }
  loadingRunDetail.value = true;
  try {
    const res = await MlflowService.getExperimentRun(runId);
    runDetail.value = normalizeRun(res) || findFromList(runId);
    await nextTick();
    drawCharts();
  } finally {
    loadingRunDetail.value = false;
  }
}

/* ============ 트리거 ============ */
// 탭 전환 시 viz 탭이면 로드
watch(
  () => mainTab.value,
  async (t) => {
    if (t === "viz") {
      await fetchRuns(pickExpName(props.experimentInfo));
      await fetchRunDetail(selectedRunId.value);
    }
  },
  { immediate: true },
);

// 부모 execution 바뀌면 viz 탭일 때만 재조회
watch(
  () => props.experimentInfo,
  async () => {
    if (mainTab.value === "viz") {
      await fetchRuns(pickExpName(props.experimentInfo));
      await fetchRunDetail(selectedRunId.value);
    }
  },
);

// 선택된 runId가 바뀌면 단건 상세 갱신
watch(selectedRunId, (id) => fetchRunDetail(id));

// metrics 서브탭일 때 리렌더
watch(vizTab, async (t) => {
  if (mainTab.value === "viz" && t === "metrics") {
    await nextTick();
    drawCharts();
    resizeCharts();
  }
});

function onResize() {
  if (mainTab.value === "viz" && vizTab.value === "metrics") {
    resizeCharts();
  }
}
onMounted(() => window.addEventListener("resize", onResize));
onBeforeUnmount(() => window.removeEventListener("resize", onResize));

/* ============ State History (Details 탭) ============ */
const rawHistory = computed<any[]>(() => {
  const h =
    props.experimentInfo?.raw?.state_history ??
    props.experimentInfo?.raw?.stateHistory ??
    props.experimentInfo?.state_history ??
    props.experimentInfo?.stateHistory ??
    [];

  if (Array.isArray(h) && h.length > 0) return h;

  const startIso =
    props.experimentInfo?.startTime &&
    !isNaN(new Date(props.experimentInfo.startTime).getTime())
      ? new Date(props.experimentInfo.startTime).toISOString()
      : undefined;

  const latest = [...(runs.value ?? [])].sort(
    (a, b) => (b?.info?.start_time ?? 0) - (a?.info?.start_time ?? 0),
  )[0];

  const endIso =
    latest?.info?.end_time && isFinite(Number(latest.info.end_time))
      ? new Date(Number(latest.info.end_time)).toISOString()
      : undefined;

  const status = String(props.experimentInfo?.status ?? "").toUpperCase();

  const out: Array<{ state: string; update_time?: string }> = [];
  if (startIso) out.push({ state: "PENDING", update_time: startIso });
  if (startIso) out.push({ state: "RUNNING", update_time: startIso });
  if (status === "SUCCEEDED" || status === "FAILED") {
    out.push({ state: status, update_time: endIso ?? startIso });
  }
  return out;
});

const history = computed(() =>
  rawHistory.value
    .slice()
    .filter((h) => h && h.state)
    .sort(
      (a: any, b: any) =>
        new Date(a.update_time || 0).getTime() -
        new Date(b.update_time || 0).getTime(),
    ),
);

const hPending = computed(() =>
  history.value.find((h) => (h.state || "").toUpperCase() === "PENDING"),
);
const hRunning = computed(() =>
  history.value.find((h) => (h.state || "").toUpperCase() === "RUNNING"),
);
const hTerminal = computed(() => {
  const t = history.value
    .slice()
    .reverse()
    .find((h) =>
      ["SUCCEEDED", "FAILED", "COMPLETED"].includes(
        (h.state || "").toUpperCase(),
      ),
    );
  return t ?? null;
});

const steps = computed(() => {
  const lastLabel = (
    hTerminal.value?.state ||
    props.experimentInfo?.status ||
    "COMPLETED"
  )
    .toString()
    .toUpperCase();

  return [
    {
      key: "PENDING",
      label: "PENDING",
      active: !!(hPending.value || hRunning.value || hTerminal.value),
      color: "primary",
      icon: "mdi-clock-outline",
      ts: hPending.value?.update_time,
    },
    {
      key: "RUNNING",
      label: "RUNNING",
      active: !!(hRunning.value || hTerminal.value),
      color: "info",
      icon: "mdi-progress-clock",
      ts: hRunning.value?.update_time,
    },
    {
      key: "TERMINAL",
      label: ["SUCCEEDED", "FAILED"].includes(lastLabel)
        ? lastLabel
        : "COMPLETED",
      active: !!hTerminal.value || ["SUCCEEDED", "FAILED"].includes(lastLabel),
      color:
        lastLabel === "FAILED"
          ? "error"
          : lastLabel === "SUCCEEDED"
            ? "success"
            : "surface-variant",
      icon:
        lastLabel === "FAILED"
          ? "mdi-close"
          : lastLabel === "SUCCEEDED"
            ? "mdi-check"
            : "mdi-dots-horizontal",
      ts: hTerminal.value?.update_time,
    },
  ];
});
const nSteps = 3;
const activeIndex = computed(() =>
  steps.value.map((s) => s.active).lastIndexOf(true),
);
const leftPct = (i: number) => (i / (nSteps - 1)) * 100;
const segWidthPct = () => 100 / (nSteps - 1);
const fmt = (iso?: string) => (iso ? new Date(iso).toLocaleString() : "—");
</script>

<template>
  <v-container fluid class="h-100 pa-5 d-flex flex-column align-center">
    <v-card
      flat
      class="bg-shades-transparent d-flex flex-column justify-center w-100"
    >
      <v-card flat class="bg-shades-transparent w-100">
        <v-card-item class="text-h5 font-weight-bold pt-0 pa-5 pl-0">
          <div class="d-flex flex-row justify-start align-center">
            <div class="text-primary">Compare Executions</div>
          </div>
        </v-card-item>
      </v-card>

      <!-- Main Tabs -->
      <v-tabs v-model="mainTab" density="comfortable" color="primary">
        <v-tab value="details">Details</v-tab>
        <v-tab value="viz">Metrics</v-tab>
      </v-tabs>

      <v-window v-model="mainTab">
        <!-- ========= Details ========= -->
        <v-window-item value="details">
          <v-card flat class="bordered-box mb-6 w-100 rounded-lg pa-8">
            <v-card-title class="grey lighten-4 py-2 px-4">
              <span class="font-weight-bold">Execution Information</span>
            </v-card-title>

            <v-card-text class="px-6 pb-6 pt-4">
              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold">Name</v-col>
                <v-col cols="9">{{ props.experimentInfo.name }}</v-col>
              </v-row>
              <VDivider class="my-2" />

              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold">Status</v-col>
                <v-col cols="9">
                  <v-icon
                    v-if="props.experimentInfo.status === 'Succeeded'"
                    color="green"
                    >mdi-check-circle</v-icon
                  >
                  <v-icon
                    v-else-if="props.experimentInfo.status === 'Failed'"
                    color="red"
                    >mdi-close-circle</v-icon
                  >
                  {{ props.experimentInfo.status }}
                </v-col>
              </v-row>
              <VDivider class="my-2" />

              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold"
                  >Duration</v-col
                >
                <v-col cols="9">{{ props.experimentInfo.duration }}</v-col>
              </v-row>
              <VDivider class="my-2" />

              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold"
                  >Experiment Name</v-col
                >
                <v-col cols="9">{{ props.experimentInfo.expName }}</v-col>
              </v-row>
              <VDivider class="my-2" />

              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold"
                  >Workflow Name</v-col
                >
                <v-col cols="9">{{ props.experimentInfo.workflow }}</v-col>
              </v-row>
              <VDivider class="my-2" />

              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold"
                  >Start Time</v-col
                >
                <v-col cols="9">{{ props.experimentInfo.startTime }}</v-col>
              </v-row>
              <VDivider class="my-2" />

              <v-row align="center" class="py-2">
                <v-col cols="3" class="text-h6 font-weight-bold"
                  >Registry Status</v-col
                >
                <v-col cols="9">{{
                  props.experimentInfo.registryStatus
                }}</v-col>
              </v-row>
              <VDivider class="my-2" />

              <!-- State History -->
              <v-row align="center" class="py-6">
                <v-col cols="3" class="text-h6 font-weight-bold"
                  >State History</v-col
                >
                <v-col cols="9">
                  <div class="history-rail">
                    <div class="history-rail__line" />
                    <template v-for="i in 2" :key="'seg-' + i">
                      <div
                        class="history-rail__seg"
                        :style="{
                          left: `calc(${leftPct(i - 1)}% + var(--dot-size)/2)`,
                          width: `calc(${segWidthPct()}% - var(--dot-size))`,
                          background:
                            i - 1 < activeIndex
                              ? 'var(--color-active)'
                              : 'var(--color-idle)',
                        }"
                      />
                    </template>

                    <template v-for="(s, i) in steps" :key="'dot-' + s.key">
                      <div
                        class="history-rail__dot"
                        :style="{ left: leftPct(i) + '%' }"
                      >
                        <v-avatar
                          :color="s.active ? s.color : 'surface-variant'"
                          size="28"
                          class="elev-1"
                        >
                          <v-icon size="18">{{ s.icon }}</v-icon>
                        </v-avatar>
                      </div>
                      <div
                        class="history-rail__label"
                        :style="{ left: leftPct(i) + '%' }"
                      >
                        <v-chip
                          size="small"
                          :color="s.active ? s.color : undefined"
                          variant="tonal"
                          class="mb-1 text-uppercase font-weight-medium"
                        >
                          {{ s.label }}
                        </v-chip>
                        <div class="text-caption text-medium-emphasis">
                          {{ fmt(s.ts) }}
                        </div>
                      </div>
                    </template>
                  </div>
                </v-col>
              </v-row>
            </v-card-text>

            <v-sheet class="d-flex justify-end mb-2">
              <v-btn color="primary" @click="emit('close')">Back to List</v-btn>
            </v-sheet>
          </v-card>
        </v-window-item>

        <!-- ========= Visualizations ========= -->
        <v-window-item value="viz">
          <v-card class="rounded-lg pa-8 w-100">
            <v-window v-model="vizTab">
              <v-window-item value="metrics">
                <v-card-text>
                  <v-row class="mb-4" align="center">
                    <v-col cols="12" class="pa-0">
                      <v-alert
                        v-if="!loadingRuns && runs.length === 0"
                        type="info"
                        variant="tonal"
                        class="mx-3"
                        density="comfortable"
                      >
                        부모 runId와 일치하는 MLflow run이 없습니다.
                      </v-alert>
                    </v-col>

                    <v-col
                      cols="12"
                      class="d-flex align-center justify-between flex-wrap ga-3"
                    >
                      <div class="text-body-2">
                        Runs loaded:
                        <strong>{{ runs.length.toLocaleString() }}</strong>
                      </div>

                      <v-select
                        v-model="selectedRunId"
                        :items="runItems"
                        item-title="label"
                        item-value="value"
                        density="comfortable"
                        hide-details
                        :clearable="false"
                        clear-icon=""
                        style="min-width: 280px; max-width: 440px"
                      />
                      <v-progress-circular
                        v-if="loadingRuns || loadingRunDetail"
                        indeterminate
                        size="16"
                        class="ml-2"
                      />
                    </v-col>
                  </v-row>

                  <!-- (A) 선택한 단건 run 상세 -->
                  <v-card class="mb-6" variant="tonal">
                    <v-card-title class="py-2 px-4">Selected Run</v-card-title>
                    <v-card-text class="px-4 pb-4">
                      <v-row>
                        <v-col cols="12" md="6">
                          <v-table density="comfortable">
                            <tbody>
                              <tr>
                                <td style="width: 40%">Run ID</td>
                                <td>{{ runDetail?.info?.run_id || "—" }}</td>
                              </tr>
                              <tr>
                                <td>Run Name</td>
                                <td>{{ runDetail?.info?.run_name || "—" }}</td>
                              </tr>
                              <tr>
                                <td>Status</td>
                                <td>{{ runDetail?.info?.status || "—" }}</td>
                              </tr>
                              <tr>
                                <td>Start</td>
                                <td>
                                  {{
                                    runDetail?.info?.start_time
                                      ? new Date(
                                          runDetail.info.start_time,
                                        ).toLocaleString()
                                      : "—"
                                  }}
                                </td>
                              </tr>
                              <tr>
                                <td>End</td>
                                <td>
                                  {{
                                    runDetail?.info?.end_time
                                      ? new Date(
                                          runDetail.info.end_time,
                                        ).toLocaleString()
                                      : "—"
                                  }}
                                </td>
                              </tr>
                            </tbody>
                          </v-table>
                        </v-col>

                        <v-col cols="12" md="6">
                          <div class="text-subtitle-2 mb-2">Parameters</div>
                          <v-table density="compact">
                            <thead>
                              <tr>
                                <th>Key</th>
                                <th>Value</th>
                              </tr>
                            </thead>
                            <tbody>
                              <tr v-if="!runDetail?.data?.params?.length">
                                <td colspan="2" class="text-medium-emphasis">
                                  No params
                                </td>
                              </tr>
                              <tr
                                v-for="p in runDetail?.data?.params || []"
                                :key="p.key"
                              >
                                <td>{{ p.key }}</td>
                                <td>{{ p.value }}</td>
                              </tr>
                            </tbody>
                          </v-table>
                        </v-col>
                      </v-row>

                      <v-row class="mt-4">
                        <v-col cols="12" md="6">
                          <div class="text-subtitle-2 mb-2">Metrics</div>
                          <v-table density="compact">
                            <thead>
                              <tr>
                                <th>Metric</th>
                                <th>Value</th>
                              </tr>
                            </thead>
                            <tbody>
                              <tr v-if="!runDetail?.data?.metrics?.length">
                                <td colspan="2" class="text-medium-emphasis">
                                  No metrics
                                </td>
                              </tr>
                              <tr
                                v-for="m in runDetail?.data?.metrics || []"
                                :key="m.key"
                              >
                                <td>{{ m.key }}</td>
                                <td>{{ m.value }}</td>
                              </tr>
                            </tbody>
                          </v-table>
                        </v-col>

                        <v-col cols="12" md="6">
                          <div class="text-subtitle-2 mb-2">Tags</div>
                          <v-table density="compact">
                            <thead>
                              <tr>
                                <th>Key</th>
                                <th>Value</th>
                              </tr>
                            </thead>
                            <tbody>
                              <tr v-if="!runDetail?.data?.tags?.length">
                                <td colspan="2" class="text-medium-emphasis">
                                  No tags
                                </td>
                              </tr>
                              <tr
                                v-for="t in runDetail?.data?.tags || []"
                                :key="t.key"
                              >
                                <td>{{ t.key }}</td>
                                <td
                                  class="text-truncate"
                                  style="max-width: 420px"
                                >
                                  {{ t.value }}
                                </td>
                              </tr>
                            </tbody>
                          </v-table>
                        </v-col>
                      </v-row>
                    </v-card-text>
                  </v-card>

                  <!-- (B) 선택한 run 기준의 간단 메트릭 표 -->
                  <v-card flat class="mb-6">
                    <v-card-title
                      class="py-2 px-0 text-button text-medium-emphasis"
                    >
                      Model Metrics (selected run)
                    </v-card-title>
                    <v-table density="comfortable">
                      <thead>
                        <tr>
                          <th class="text-left" style="width: 50%">Metric</th>
                          <th class="text-left">Value</th>
                        </tr>
                      </thead>
                      <tbody>
                        <tr v-if="!selectedMetrics.length">
                          <td
                            colspan="2"
                            class="text-center py-6 text-medium-emphasis"
                          >
                            No Data
                          </td>
                        </tr>
                        <tr v-for="m in selectedMetrics" :key="m.key">
                          <td>{{ m.key }}</td>
                          <td>{{ m.value }}</td>
                        </tr>
                      </tbody>
                    </v-table>
                  </v-card>

                  <v-card flat class="mb-6">
                    <v-card-title
                      class="py-2 px-0 text-button text-medium-emphasis"
                    >
                      Metrics (bar chart)
                    </v-card-title>
                    <div
                      ref="elMetrics"
                      style="width: 100%; height: 400px"
                    ></div>
                  </v-card>
                </v-card-text>
              </v-window-item>

              <!-- placeholders -->
              <v-window-item value="scatter">
                <v-card-text class="px-6 py-10 text-medium-emphasis"
                  >(준비중) X/Y 축 선택 후 산점도 표시</v-card-text
                >
              </v-window-item>
              <v-window-item value="box">
                <v-card-text class="px-6 py-10 text-medium-emphasis"
                  >(준비중) 메트릭 분포 Box Plot</v-card-text
                >
              </v-window-item>
              <v-window-item value="contour">
                <v-card-text class="px-6 py-10 text-medium-emphasis"
                  >(준비중) 2D/3D Contour Plot</v-card-text
                >
              </v-window-item>
            </v-window>
            <v-sheet class="d-flex justify-end mb-2">
              <v-btn color="primary" @click="emit('close')">Back to List</v-btn>
            </v-sheet>
          </v-card>
        </v-window-item>
      </v-window>
    </v-card>
  </v-container>
</template>

<style scoped>
:root {
  --dot-size: 28px;
}
.history-rail {
  position: relative;
  width: 40%;
  padding: 12px 0 34px;
  --color-rail: rgba(255, 255, 255, 0.12);
  --color-idle: rgba(255, 255, 255, 0.12);
  --color-active: rgb(98, 0, 238);
}
.history-rail__line {
  position: absolute;
  left: 0;
  right: 0;
  top: 14px;
  height: 4px;
  background: var(--color-rail);
  border-radius: 2px;
}
.history-rail__seg {
  position: absolute;
  top: 14px;
  height: 4px;
  border-radius: 2px;
  transition:
    width 0.24s ease,
    background 0.24s ease;
}
.history-rail__dot {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
}
.history-rail__label {
  position: absolute;
  top: 28px;
  transform: translateX(-50%);
  text-align: center;
  white-space: nowrap;
}
</style>
