/* BioTrustCore Core Monitor — 반도체/기판 테마. 차트 색은 dataviz 기준 팔레트(상태색 고정) */
:root {
  color-scheme: dark;
  --page: #0b0f15; --surface: #121924; --surface-2: #182233; --surface-3: #1f2b3f; --line: #263447; --line-2: #34465f;
  --ink: #e8eef6; --ink-2: #b8c4d4; --ink-3: #8393a8; --trace: rgba(57,135,229,.14); --glow: rgba(57,135,229,.45);
  --series-1: #3987e5; --series-1-soft: rgba(57,135,229,.16); --status-good: #0ca30c; --status-warn: #fab219; --status-serious: #ec835a; --status-crit: #d03b3b;
  --seq-250: #86b6ef; --seq-300: #6da7ec; --seq-350: #5598e7; --seq-400: #3987e5; --seq-450: #2a78d6; --seq-500: #256abf; --seq-600: #184f95;
  --grid: #2c2c2a; --axis: #383835; --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; --sans: -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Noto Sans KR", "Segoe UI", Roboto, sans-serif;
  --radius: 10px;
}
:root[data-theme="light"] {
  color-scheme: light;
  --page: #f4f6f9; --surface: #ffffff; --surface-2: #f2f5f9; --surface-3: #e9eef5; --line: #d9e0ea; --line-2: #c4cfdd;
  --ink: #0b0b0b; --ink-2: #52514e; --ink-3: #898781; --trace: rgba(42,120,214,.10); --glow: rgba(42,120,214,.35);
  --series-1: #2a78d6; --series-1-soft: rgba(42,120,214,.14); --seq-250: #86b6ef; --seq-300: #6da7ec; --seq-350: #5598e7; --seq-400: #3987e5; --seq-450: #2a78d6; --seq-500: #256abf; --seq-600: #184f95;
  --grid: #e1e0d9; --axis: #c3c2b7;
}
* { box-sizing: border-box; }
html, body { margin: 0; background: var(--page); color: var(--ink); font-family: var(--sans); font-size: 14px; line-height: 1.5; }
body { background-image: linear-gradient(var(--trace) 1px, transparent 1px), linear-gradient(90deg, var(--trace) 1px, transparent 1px); background-size: 28px 28px; background-attachment: fixed; }
.mono { font-family: var(--mono); } .hidden { display: none !important; } .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
a { color: var(--series-1); text-decoration: none; }
/* 헤더 */
.hdr { position: sticky; top: 0; z-index: 10; display: flex; align-items: center; gap: 18px; padding: 10px 20px; background: color-mix(in srgb, var(--surface) 88%, transparent); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
.brand { display: flex; align-items: center; gap: 12px; } .brand .t { font-weight: 800; font-size: 17px; letter-spacing: -.01em; } .brand .thin { font-weight: 400; color: var(--ink-2); } .brand .s { font-size: 12px; color: var(--ink-3); }
.die { width: 30px; height: 30px; border-radius: 6px; background: linear-gradient(135deg, var(--surface-3), var(--surface-2)); border: 1px solid var(--line-2); position: relative; }
.die::after { content: ""; position: absolute; inset: 8px; border-radius: 3px; background: var(--series-1); box-shadow: 0 0 12px var(--glow); }
.filters { display: flex; align-items: center; gap: 4px; margin-left: 12px; } .filters .lbl { font-size: 12px; color: var(--ink-3); margin-right: 4px; }
.range { appearance: none; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2); padding: 4px 10px; border-radius: 6px; font-size: 12px; cursor: pointer; } .range.active { background: var(--series-1); color: #fff; border-color: transparent; font-weight: 600; }
.hdr-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.live { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-2); padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface-2); }
.clk { width: 8px; height: 8px; border-radius: 50%; background: var(--status-good); box-shadow: 0 0 8px var(--status-good); animation: clk 1.6s ease-in-out infinite; } .live.off .clk { background: var(--status-crit); box-shadow: none; animation: none; }
@keyframes clk { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.lnk { font-size: 12.5px; color: var(--ink-2); border: 1px solid var(--line); background: var(--surface-2); padding: 4px 10px; border-radius: 6px; } .lnk.btn { cursor: pointer; font-family: inherit; } .lnk:hover { color: var(--ink); }
/* 보드 */
.board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; padding: 16px 20px 40px; max-width: 1700px; margin: 0 auto; }
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px 14px; position: relative; min-width: 0; box-shadow: 0 1px 0 rgba(255,255,255,.03) inset, 0 2px 12px rgba(0,0,0,.18); }
.panel::before, .panel::after { content: ""; position: absolute; width: 6px; height: 6px; border-radius: 1px; background: var(--line-2); }
.panel::before { top: 8px; right: 8px; } .panel::after { bottom: 8px; left: 8px; }
/* 섹션 너비(칸) — 편집에서 1~4 칸으로 조절, 화면이 좁아지면 자동 축소 */
.panel[hidden] { display: none !important; }
.panel[data-span="1"] { grid-column: span 1; } .panel[data-span="2"] { grid-column: span 2; } .panel[data-span="3"] { grid-column: span 3; } .panel[data-span="4"] { grid-column: span 4; }
@media (max-width: 1250px) { .board { grid-template-columns: repeat(2, minmax(0, 1fr)); } .panel[data-span="3"], .panel[data-span="4"] { grid-column: span 2; } }
@media (max-width: 760px) { .board { grid-template-columns: 1fr; padding: 12px 16px; } .panel[data-span] { grid-column: span 1; } .hdr { flex-wrap: wrap; gap: 8px; } .hdr-right { margin-left: 0; } .filters { margin-left: 0; } }
.ph { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; } .ph h2 { margin: 0; font-size: 14px; font-weight: 700; letter-spacing: -.005em; } .ph .sub { font-weight: 400; color: var(--ink-3); font-size: 12px; margin-left: 6px; } .ph-r { margin-left: auto; font-size: 11.5px; color: var(--ink-3); }
.ic { font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; color: var(--ink-3); border: 1px solid var(--line-2); border-radius: 4px; padding: 1px 6px; background: var(--surface-2); }
.tbl-toggle { appearance: none; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2); font-size: 11.5px; padding: 2px 8px; border-radius: 5px; cursor: pointer; font-family: inherit; } .tbl-toggle.on { color: var(--ink); border-color: var(--line-2); }
.fl { font-size: 11.5px; color: var(--ink-3); display: inline-flex; align-items: center; gap: 4px; } .fl input[type=search] { background: var(--surface-2); border: 1px solid var(--line); color: var(--ink); border-radius: 5px; padding: 2px 6px; font-size: 11.5px; width: 150px; }
/* 구성요소 칩 */
.chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 10px; }
.chip { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px 10px 14px; background: linear-gradient(180deg, var(--surface-2), var(--surface)); position: relative; }
.chip::before { content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px; border-radius: 2px; background: var(--ink-3); }
.chip.good::before { background: var(--status-good); } .chip.warn::before { background: var(--status-warn); } .chip.crit::before { background: var(--status-crit); }
.chip .n { font-size: 11px; color: var(--ink-3); letter-spacing: .04em; text-transform: uppercase; font-family: var(--mono); } .chip .v { font-size: 15px; font-weight: 700; margin-top: 2px; display: flex; align-items: center; gap: 6px; } .chip .d { font-size: 11.5px; color: var(--ink-2); margin-top: 2px; word-break: break-all; }
.st { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px; }
.st.good { color: var(--status-good); background: color-mix(in srgb, var(--status-good) 16%, transparent); } .st.warn { color: var(--status-warn); background: color-mix(in srgb, var(--status-warn) 18%, transparent); } .st.crit { color: var(--status-crit); background: color-mix(in srgb, var(--status-crit) 18%, transparent); } .st.neutral { color: var(--ink-2); background: var(--surface-3); }
/* KPI */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.kpi { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; background: var(--surface-2); }
.kpi .l { font-size: 11.5px; color: var(--ink-3); } .kpi .v { font-size: 26px; font-weight: 700; line-height: 1.15; margin-top: 2px; letter-spacing: -.01em; } .kpi.hero .v { font-size: 40px; } .kpi .sub { font-size: 11.5px; color: var(--ink-2); margin-top: 2px; } .kpi svg { display: block; margin-top: 6px; }
/* 차트 공통 */
.chart { position: relative; min-height: 180px; } .chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart text { font-family: var(--mono); font-size: 10.5px; fill: var(--ink-3); font-variant-numeric: tabular-nums; } .chart .lbl { fill: var(--ink-2); font-family: var(--sans); font-size: 11px; } .chart .val { fill: var(--ink); font-size: 10.5px; }
.chart .grid { stroke: var(--grid); stroke-width: 1; } .chart .axis { stroke: var(--axis); stroke-width: 1; }
.chart .bar { transition: opacity .12s; } .chart .bar:hover, .chart .bar.hot { filter: brightness(1.15); } .chart .hit { fill: transparent; cursor: crosshair; }
.chart .empty { color: var(--ink-3); font-size: 12.5px; position: absolute; inset: 0; display: grid; place-items: center; }
.legend { display: flex; gap: 14px; font-size: 11.5px; color: var(--ink-2); margin: 0 0 4px 2px; } .legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
.tbl table { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 6px; } .tbl th, .tbl td { border-bottom: 1px solid var(--line); padding: 4px 6px; text-align: left; } .tbl td.n, .tbl th.n { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); } .tbl th { color: var(--ink-3); font-weight: 600; white-space: nowrap; }
.tooltip { position: fixed; z-index: 30; pointer-events: none; background: var(--surface-3); color: var(--ink); border: 1px solid var(--line-2); border-radius: 8px; padding: 8px 10px; font-size: 12px; box-shadow: 0 6px 24px rgba(0,0,0,.35); opacity: 0; transform: translateY(4px); transition: opacity .1s, transform .1s; max-width: 320px; }
.tooltip.show { opacity: 1; transform: none; } .tooltip .tt { color: var(--ink-3); font-size: 11px; margin-bottom: 4px; font-family: var(--mono); } .tooltip .tr { display: flex; align-items: center; gap: 8px; justify-content: space-between; } .tooltip .tr b { font-variant-numeric: tabular-nums; } .tooltip .key { display: inline-block; width: 12px; height: 3px; border-radius: 2px; margin-right: 6px; vertical-align: 2px; }
/* 프로세스 */
.meters { display: grid; gap: 10px; } .meter .ml { display: flex; justify-content: space-between; font-size: 12px; color: var(--ink-2); } .meter .ml b { color: var(--ink); font-variant-numeric: tabular-nums; }
.meter .track { height: 8px; border-radius: 4px; background: color-mix(in srgb, var(--series-1) 18%, var(--surface-2)); overflow: hidden; margin-top: 4px; } .meter .fill { height: 100%; border-radius: 4px; background: var(--series-1); transition: width .4s; } .meter .fill.warn { background: var(--status-warn); } .meter .fill.crit { background: var(--status-crit); }
.qgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 10px; } .q { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; background: var(--surface-2); } .q .n { font-size: 11px; color: var(--ink-3); font-family: var(--mono); } .q .v { font-size: 18px; font-weight: 700; } .q .d { font-size: 11px; color: var(--ink-2); }
/* 버스 피드 */
.bus-head, .bus .item { display: grid; grid-template-columns: 112px 64px minmax(150px, 1.4fr) minmax(140px, 1fr) 96px 70px 140px; gap: 10px; align-items: center; }
.bus-head { font-size: 11px; color: var(--ink-3); padding: 4px 10px; border-bottom: 1px solid var(--line); font-family: var(--mono); letter-spacing: .03em; }
.bus { overflow-y: auto; max-height: var(--body-h, 360px); position: relative; }
.bus .item { padding: 6px 10px; border-bottom: 1px solid var(--line); font-size: 12.5px; cursor: pointer; position: relative; } .bus .item:hover { background: var(--surface-2); } .bus .item.sel { background: var(--surface-3); }
.bus .item::before { content: ""; position: absolute; left: 0; top: 6px; bottom: 6px; width: 3px; border-radius: 2px; background: transparent; }
.bus .item.running::before { background: var(--series-1); animation: pulse 1s ease-in-out infinite; } .bus .item.success::before { background: var(--status-good); } .bus .item.error::before { background: var(--status-crit); } .bus .item.timeout::before { background: var(--status-warn); }
.bus .item.new { animation: slidein .45s ease-out; } @keyframes slidein { from { background: var(--series-1-soft); transform: translateX(-6px); opacity: .2; } to { background: transparent; transform: none; opacity: 1; } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.bus .t { font-family: var(--mono); color: var(--ink-3); font-size: 11.5px; } .bus .k { font-size: 10.5px; font-family: var(--mono); color: var(--ink-2); border: 1px solid var(--line-2); border-radius: 4px; padding: 0 5px; width: max-content; }
.bus .k.inbound { color: var(--series-1); border-color: color-mix(in srgb, var(--series-1) 50%, transparent); }
.bus .c { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .bus .c b { font-family: var(--mono); font-size: 11px; color: var(--ink-3); margin-right: 6px; font-weight: 600; }
.bus .tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .bus .tx code { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.bus .ms { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); text-align: right; } .bus .tr { font-family: var(--mono); font-size: 11px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; }
.code { font-family: var(--mono); font-weight: 700; font-size: 12px; padding: 1px 7px; border-radius: 5px; display: inline-block; }
.code.success { color: var(--status-good); background: color-mix(in srgb, var(--status-good) 16%, transparent); } .code.error { color: var(--status-crit); background: color-mix(in srgb, var(--status-crit) 16%, transparent); } .code.timeout { color: var(--status-warn); background: color-mix(in srgb, var(--status-warn) 18%, transparent); } .code.running { color: var(--series-1); background: var(--series-1-soft); }
@media (max-width: 900px) { .bus-head, .bus .item { grid-template-columns: 104px 56px 1fr 1fr 80px; } .bus-head span:nth-child(n+6), .bus .item > *:nth-child(n+6) { display: none; } }
/* 센터 이벤트 */
.center-stats { font-size: 11.5px; color: var(--ink-2); margin: -2px 0 6px; }
.center-events { max-height: var(--body-h, 330px); overflow-y: auto; }
.center-events .ev { display: grid; grid-template-columns: 112px 112px 1fr 52px; gap: 10px; padding: 4px 8px; border-bottom: 1px solid var(--line); font-size: 12px; } .center-events .ev .t { font-family: var(--mono); color: var(--ink-3); font-size: 11.5px; } .center-events .ev .k { font-family: var(--mono); font-size: 10.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .center-events .ev .m { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .center-events .ev .ms { font-family: var(--mono); color: var(--ink-3); text-align: right; }
/* 드로어 */
.drawer { position: fixed; top: 0; right: 0; height: 100vh; width: min(720px, 96vw); background: var(--surface); border-left: 1px solid var(--line-2); box-shadow: -12px 0 40px rgba(0,0,0,.45); transform: translateX(102%); transition: transform .22s ease; z-index: 20; display: flex; flex-direction: column; }
.drawer.open { transform: none; }
.dh { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--line); } .dt { font-weight: 700; font-size: 15px; } .ds { font-size: 11.5px; color: var(--ink-3); margin-top: 2px; } .dh .lnk { margin-left: auto; }
.db { padding: 14px 18px 30px; overflow-y: auto; }
.db h3 { font-size: 13px; margin: 16px 0 6px; color: var(--ink-2); text-transform: uppercase; letter-spacing: .05em; font-family: var(--mono); } .db h3:first-child { margin-top: 0; }
.kv { display: grid; grid-template-columns: 150px 1fr; gap: 3px 10px; font-size: 12.5px; } .kv .k { color: var(--ink-3); } .kv .v { font-family: var(--mono); font-size: 12px; word-break: break-all; }
.pipe { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } .pipe .stg { border: 1px solid var(--line-2); background: var(--surface-2); border-radius: 6px; padding: 4px 8px; font-family: var(--mono); font-size: 11px; } .pipe .stg small { display: block; color: var(--ink-3); font-size: 10px; } .pipe .arrow { color: var(--ink-3); font-size: 11px; }
.pipe .stg.err { border-color: var(--status-crit); color: var(--status-crit); }
.evlist { list-style: none; margin: 6px 0 0; padding: 0; } .evlist li { display: grid; grid-template-columns: 64px 160px 1fr; gap: 8px; padding: 4px 0; border-bottom: 1px dashed var(--line); font-size: 12px; } .evlist .o { font-family: var(--mono); color: var(--ink-3); } .evlist .s { font-family: var(--mono); font-weight: 600; } .evlist .d { color: var(--ink-2); word-break: break-all; font-family: var(--mono); font-size: 11px; }
pre { background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; font-family: var(--mono); font-size: 11.5px; overflow: auto; margin: 6px 0; white-space: pre-wrap; word-break: break-all; }
.telegram { font-family: var(--mono); font-size: 11.5px; line-height: 1.7; word-break: break-all; background: var(--surface-2); border: 1px solid var(--line); padding: 8px 10px; border-radius: 8px; } .telegram span:nth-child(odd) { background: rgba(57,135,229,.22); } .telegram span:nth-child(even) { background: rgba(25,158,112,.2); } .telegram span { cursor: help; }
details { border: 1px solid var(--line); border-radius: 8px; padding: 0 10px; margin: 6px 0; } details summary { cursor: pointer; padding: 6px 0; font-size: 12.5px; }
@media (prefers-reduced-motion: reduce) { .clk, .bus .item.running::before, .bus .item.new { animation: none; } .drawer { transition: none; } }

/* ─────────── 섹션 높이(편집에서 3단계) ─────────── */
.panel[data-h="s"] { --body-h: 190px; --xv-h: 170px; }
.panel[data-h="m"] { --body-h: 360px; --xv-h: 240px; }
.panel[data-h="l"] { --body-h: 560px; --xv-h: 360px; }

/* ─────────── 헤더 추가 요소 ─────────── */
.sel { appearance: none; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2); padding: 4px 22px 4px 9px; border-radius: 6px; font-size: 12px; font-family: inherit; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(135deg, var(--ink-3) 50%, transparent 50%); background-position: right 10px center, right 6px center; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat; }
.hdr .tick { position: absolute; left: 0; bottom: -1px; height: 2px; width: 100%; background: transparent; overflow: hidden; }
.hdr .tick::after { content: ""; display: block; height: 100%; width: 100%; background: linear-gradient(90deg, transparent, var(--series-1)); transform-origin: left; transform: scaleX(0); animation: tickfill var(--tick, 5s) linear infinite; }
.hdr .tick.off::after { animation: none; }
@keyframes tickfill { from { transform: scaleX(0); opacity: .9; } to { transform: scaleX(1); opacity: .25; } }
.nowbox { border: 1px solid var(--line); background: var(--surface-2); border-radius: 6px; padding: 2px 8px; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); }
.nowbox small { font-size: 10.5px; font-weight: 400; color: var(--ink-3); margin-left: 3px; }
.nowbox.hot { border-color: color-mix(in srgb, var(--series-1) 60%, transparent); box-shadow: 0 0 0 2px var(--series-1-soft); }

/* ─────────── 섹션 편집 ─────────── */
.editbar { position: sticky; top: 52px; z-index: 9; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 9px 20px; background: color-mix(in srgb, var(--surface-2) 94%, transparent); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line-2); }
.editbar[hidden] { display: none; }
.editbar .eb-t { font-weight: 700; font-size: 13px; } .editbar .eb-d { font-size: 11.5px; color: var(--ink-3); } .editbar .eb-sp { margin-left: auto; }
.eb-list { display: flex; gap: 6px; flex-wrap: wrap; }
.eb-list label { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; border: 1px solid var(--line); background: var(--surface); border-radius: 999px; padding: 3px 10px; cursor: pointer; color: var(--ink-3); }
.eb-list label.on { color: var(--ink); border-color: var(--line-2); }
.sec-ctl { display: none; align-items: center; gap: 2px; }
/* 편집 컨트롤은 제목 아래 줄에 붙여 좁은 섹션에서도 제목이 깨지지 않게 한다 */
.board.editing .ph { flex-wrap: wrap; }
.board.editing .sec-ctl { display: flex; flex: 1 0 100%; justify-content: flex-end; margin-top: 5px; padding-top: 5px; border-top: 1px dashed var(--line); }
.sec-ctl .sc { appearance: none; border: 1px solid var(--line-2); background: var(--surface-2); color: var(--ink-2); font-size: 11px; line-height: 1; padding: 3px 6px; border-radius: 5px; cursor: pointer; font-family: inherit; }
.sec-ctl .sc:hover { color: var(--ink); background: var(--surface-3); } .sec-ctl .sc[disabled] { opacity: .35; cursor: default; }
.sec-ctl .sc.x:hover { color: var(--status-crit); border-color: var(--status-crit); }
.sec-ctl .val { font-family: var(--mono); font-size: 11px; color: var(--ink-3); min-width: 34px; text-align: center; }
.grip { display: none; cursor: grab; color: var(--ink-3); font-size: 13px; letter-spacing: -2px; user-select: none; padding: 0 2px; }
.board.editing .grip { display: inline-block; }
.board.editing .panel { outline: 1px dashed var(--line-2); outline-offset: 2px; }
.board.editing .ph { cursor: grab; }
.panel.dragging { opacity: .45; }
.panel.dropzone { outline: 2px dashed var(--series-1) !important; outline-offset: 2px; }
.panel.landed { animation: landed .5s ease-out; }
@keyframes landed { from { transform: scale(.97); box-shadow: 0 0 0 4px var(--series-1-soft); } to { transform: none; } }

/* ─────────── 실시간 트래픽(X-View) ─────────── */
.xview { position: relative; height: var(--xv-h, 240px); }
.xview svg { display: block; width: 100%; height: 100%; overflow: visible; }
.xview text { font-family: var(--mono); font-size: 10px; fill: var(--ink-3); font-variant-numeric: tabular-nums; }
.xview .grid { stroke: var(--grid); stroke-width: 1; } .xview .grid.mid { stroke-dasharray: 2 4; }
.xview .axis { stroke: var(--axis); stroke-width: 1; }
.xview .nowline { stroke: var(--series-1); stroke-width: 1.5; opacity: .5; }
.xview .nowcap { fill: var(--series-1); }
.xview .band { fill: var(--series-1); opacity: .05; }
.xv-dot { transform-box: fill-box; transform-origin: center; animation: dotIn .4s cubic-bezier(.2, 1.5, .4, 1) both; cursor: pointer; }
.xv-dot:hover { stroke: var(--ink); stroke-width: 1.5; }
@keyframes dotIn { 0% { transform: scale(0); opacity: 0; } 65% { transform: scale(1.7); opacity: 1; } 100% { transform: scale(1); } }
.xv-ping { transform-box: fill-box; transform-origin: center; fill: none; stroke-width: 1.5; pointer-events: none; animation: ping .85s ease-out forwards; }
@keyframes ping { 0% { transform: scale(.5); opacity: .7; } 100% { transform: scale(3.6); opacity: 0; } }
.xv-run { fill: none; stroke: var(--series-1); stroke-width: 1.6; animation: runpulse 1.1s ease-in-out infinite; }
@keyframes runpulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.xv-sec { opacity: .85; transition: height .25s ease-out, y .25s ease-out; }
.xview .empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--ink-3); font-size: 12.5px; }
.xview .hit { fill: transparent; }

/* ─────────── 값 변화 애니메이션 ─────────── */
.kpi .v { transition: color .2s; } .kpi .v.bump { animation: bump .45s cubic-bezier(.2, 1.4, .4, 1); }
@keyframes bump { 0% { transform: scale(1); } 40% { transform: scale(1.09); color: var(--series-1); } 100% { transform: scale(1); } }
.chip.flash { animation: flashbg .9s ease-out; } @keyframes flashbg { from { background: var(--series-1-soft); } to { background: linear-gradient(180deg, var(--surface-2), var(--surface)); } }
.chart svg.anim-v .bar { transform-box: fill-box; transform-origin: bottom; animation: growv .45s cubic-bezier(.2, .9, .3, 1) both; }
.chart svg.anim-h .bar { transform-box: fill-box; transform-origin: left; animation: growh .45s cubic-bezier(.2, .9, .3, 1) both; }
@keyframes growv { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes growh { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.q .v { transition: color .2s; } .q.up .v { color: var(--series-1); }
.bus .item.new { animation: slidein .5s ease-out; }
.bus .t .d { color: var(--ink-3); opacity: .72; margin-right: 3px; }
.center-events .ev.new { animation: slidein .5s ease-out; }
.center-events .ev .t .d { opacity: .72; margin-right: 3px; }
.center-events .ev .job { color: var(--ink); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .xv-dot, .xv-ping, .xv-run, .kpi .v.bump, .chip.flash, .chart svg.anim-v .bar, .chart svg.anim-h .bar, .hdr .tick::after, .panel.landed, .center-events .ev.new { animation: none !important; }
}

/* ─────────── 대시보드 가이드(단계별 설명 투어) ─────────── */
.lnk.btn.accent { color: #fff; background: var(--series-1); border-color: transparent; font-weight: 600; }
.lnk.btn.accent:hover { filter: brightness(1.08); color: #fff; }
.tour-veil { position: fixed; inset: 0; z-index: 40; cursor: pointer; }
.tour-spot { position: fixed; z-index: 41; border-radius: 12px; border: 2px solid var(--series-1); pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(4, 8, 14, .76), 0 0 0 4px var(--series-1-soft), 0 0 30px var(--glow);
  transition: top .28s cubic-bezier(.4, 0, .2, 1), left .28s cubic-bezier(.4, 0, .2, 1), width .28s cubic-bezier(.4, 0, .2, 1), height .28s cubic-bezier(.4, 0, .2, 1); }
:root[data-theme="light"] .tour-spot { box-shadow: 0 0 0 9999px rgba(14, 24, 38, .55), 0 0 0 4px var(--series-1-soft), 0 0 24px var(--glow); }
.tour-card { position: fixed; z-index: 42; width: min(390px, calc(100vw - 28px)); background: var(--surface); border: 1px solid var(--line-2); border-radius: 12px; padding: 13px 16px 13px; box-shadow: 0 20px 56px rgba(0, 0, 0, .5); }
.tour-card .tc-h { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.tour-card .tc-step { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.tour-card .tc-badge { font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; color: var(--series-1); border: 1px solid color-mix(in srgb, var(--series-1) 45%, transparent); background: var(--series-1-soft); border-radius: 4px; padding: 1px 6px; }
.tour-card .tc-x { margin-left: auto; appearance: none; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2); border-radius: 6px; font-size: 12px; padding: 2px 8px; cursor: pointer; font-family: inherit; }
.tour-card .tc-x:hover { color: var(--ink); }
.tour-card h3 { margin: 0 0 6px; font-size: 15.5px; letter-spacing: -.01em; }
.tour-card .tc-b { font-size: 12.8px; color: var(--ink-2); line-height: 1.62; }
.tour-card .tc-b b { color: var(--ink); font-weight: 600; }
.tour-card .tc-b ul { margin: 6px 0 0; padding-left: 16px; } .tour-card .tc-b li { margin: 2px 0; }
.tour-card .tc-f { display: flex; align-items: center; gap: 8px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.tour-card .tc-dots { display: flex; gap: 4px; flex-wrap: wrap; margin-right: auto; max-width: 180px; }
.tour-card .tc-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--line-2); cursor: pointer; display: block; }
.tour-card .tc-dots i.on { background: var(--series-1); transform: scale(1.35); }
.tour-card .tc-f button { appearance: none; font-family: inherit; font-size: 12.5px; padding: 5px 12px; border-radius: 7px; cursor: pointer; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2); }
.tour-card .tc-f button.go { background: var(--series-1); border-color: transparent; color: #fff; font-weight: 600; }
.tour-card .tc-f button[disabled] { opacity: .4; cursor: default; }
.tour-card.pop { animation: tcpop .26s cubic-bezier(.2, 1.3, .4, 1); }
@keyframes tcpop { from { opacity: 0; transform: translateY(6px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .tour-spot { transition: none; } .tour-card.pop { animation: none; } }
