@charset "UTF-8";
@import url("tokens.css?v=20260730.2");

/* Spring JSP와 Cloudflare 셸이 공유한다. JS 모듈이 조회하는 ID·클래스는 두 셸에서 같아야 한다.
   색·형태·모션 토큰은 tokens.css 한 곳에서만 정의한다. */

/* ===================== 기본 ===================== */

html {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
html, body { height: 100%; overflow: hidden; background: var(--bg); }
body {
    font-family: var(--font-ui);
    font-size: 10px;
    color: var(--text);
    text-rendering: optimizeLegibility;
    letter-spacing: -0.005em;
}

/* 수치·시각·좌표는 예외 없이 모노 — 판독부의 목소리를 하나로 묶는다 */
.mono, .info_time, .lg_share,
#legend_scale .lg_ticks, .grid_stats dd, .map_scale,
.forecast_timeline_ticks, .forecast_timeline li span,
.latitude, .longitude, .timeline_readout {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "zero" 1;
}

button, input, select, textarea, [role="button"] {
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0.12);
}
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible,
a:focus-visible, summary:focus-visible, [role="button"]:focus-visible, [tabindex]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-1);
}
.sr-only {
    position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important;
    margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important; border: 0 !important;
}
.skip-link {
    position: fixed; top: 8px; left: 8px; z-index: 3000; transform: translateY(-160%);
    padding: 10px 15px; border-radius: var(--r-2); background: var(--accent); color: var(--on-accent);
    font-size: 1.3rem; font-weight: 700; box-shadow: var(--e-2);
    transition: transform var(--t) var(--ease-spring);
}
.skip-link:focus-visible { transform: translateY(0); }

/* ===================== 레이아웃 뼈대 ===================== */

.app { position: relative; width: 100vw; height: 100vh; height: 100dvh; overflow: hidden; }

.map_workspace { position: absolute; inset: 0; z-index: 1; }

/* 빈 바다·여백에 계기 격자를 깔아 '죽은 배경'을 없앤다.
   OL 캔버스는 그려진 곳 외에는 투명하므로 이 배경이 그대로 비친다. */
.map {
    position: absolute; z-index: 1; width: 100%; height: 100%;
    background-color: var(--bg-map-weather);
    background-image:
        linear-gradient(var(--graticule) 1px, transparent 1px),
        linear-gradient(90deg, var(--graticule) 1px, transparent 1px);
    background-size: 72px 72px;
    background-position: center center;
    transition: background-color .3s var(--ease);
}
#map:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px var(--accent); }
.map-weather    { background-color: var(--bg-map-weather); }
.map-boundaries { background-color: var(--bg-map-boundaries); }
#wind_field_canvas {
    position: absolute; inset: 0; z-index: 10; pointer-events: none;
    opacity: 1; transition: opacity .08s linear;
}
#wind_field_canvas.is-map-moving { opacity: 0; }

/* 크롬 진입 — 로드 시 한 번의 정돈된 연출 */
@keyframes boraRise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes boraDrop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.topbar        { animation: boraDrop .42s var(--ease) both; }
.explore_modes { animation: boraDrop .42s var(--ease) .06s both; }
.map_status_panel { animation: boraDrop .42s var(--ease) .10s both; }
.legend_stack  { animation: boraRise .42s var(--ease) .14s both; }
.timeline      { animation: boraRise .42s var(--ease) .10s both; }

.map_notice {
    position: absolute; left: 50%; bottom: 100px; z-index: 24; transform: translateX(-50%);
    width: max-content; max-width: min(420px, calc(100vw - 24px)); padding: 9px 14px;
    border: 1px solid var(--stroke); border-radius: var(--r-2); background: var(--surface-solid);
    color: var(--text-2); box-shadow: var(--e-2); font-size: 1.2rem; font-weight: 600;
    line-height: 1.4; text-align: center; pointer-events: none;
}
.map_notice[data-action="true"] {
    display: flex; align-items: center; gap: 10px; pointer-events: auto;
}
.map_notice button {
    min-height: 32px; padding: 0 12px; flex: none; border-radius: var(--r-2);
    background: var(--accent); color: var(--on-accent); font-weight: 700;
}
.map_notice button:hover { filter: brightness(.94); }
.map_notice button:active { scale: .96; }
.map_notice[hidden] { display: none; }

/* ===================== 상단 바 ===================== */

.topbar {
    position: absolute; top: 0; left: 0; right: 0; z-index: 30;
    height: 52px; padding: 0 10px 0 8px;
    display: flex; align-items: center; gap: 0; pointer-events: none;
    background: var(--surface-solid);
    box-shadow: inset 0 -1px 0 var(--stroke);
}
.topbar > * { pointer-events: auto; }

.brand {
    align-self: stretch; display: flex; align-items: center; gap: 9px;
    padding: 0 15px 0 8px; margin-right: 2px;
    box-shadow: inset -1px 0 0 var(--stroke);
}
.brand svg { display: block; color: var(--text); }
.brand .brand_txt { line-height: 1.1; }
.brand .brand_txt strong {
    display: block; color: var(--text); font-family: var(--font-mono);
    font-size: 1.55rem; font-weight: 600; letter-spacing: .2em; text-indent: .2em;
}
.brand .brand_txt span {
    display: block; margin-top: 2px; color: var(--text-3); font-family: var(--font-mono);
    font-size: .82rem; font-weight: 400; letter-spacing: .16em;
}

/* 데이터 영역 — 활성은 흰 밑줄(계기 백라이트) */
.data_domain_nav {
    align-self: stretch; display: flex; align-items: stretch; padding: 0 3px;
    box-shadow: inset -1px 0 0 var(--stroke);
}
.data_domain_nav button {
    position: relative; min-width: 74px; padding: 0 13px;
    display: flex; align-items: center; justify-content: center; gap: 7px;
    color: var(--text-3); font-size: 1.28rem; font-weight: 600;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.data_domain_nav button:hover { color: var(--text); background: var(--chip); }
.data_domain_nav button.on { color: var(--text); }
.data_domain_nav button.on::after {
    content: ''; position: absolute; left: 11px; right: 11px; bottom: 0; height: 2px;
    background: var(--lit); border-radius: 2px 2px 0 0;
    animation: boraRise .22s var(--ease-spring) both;
}
.nav_icon {
    width: 16px; height: 16px; flex: none; overflow: visible;
    color: currentColor; opacity: .72;
    transition: opacity var(--t) var(--ease), transform var(--t) var(--ease);
}
.data_domain_nav button:hover .nav_icon,
.data_domain_nav button.on .nav_icon,
.mobile_primary_controls button:hover .nav_icon,
.mobile_primary_controls button.on .nav_icon { opacity: 1; }

/* 설정 토글 — 지도 위를 떠다니지 않고 상단 바 안에 자리를 갖는다 */
.dock_toggle {
    align-self: center; flex: none; order: -1; margin-right: 4px;
    width: 38px; min-width: 38px; height: 38px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    border: 1px solid transparent; border-radius: var(--r-2);
    background: transparent; color: var(--text-2);
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.dock_toggle:hover { color: var(--text); background: var(--chip-hover); }
.dock_toggle[aria-expanded="true"] {
    color: var(--text); background: var(--lit-bg); border-color: var(--lit-edge);
}
.dock_toggle_label { display: none; }
.mobile_primary_controls { display: none; }

/* 검색 */
.search-container { position: relative; width: min(290px, 23vw); margin-left: auto; padding-left: 10px; }
.station_query {
    width: 100%; height: 34px; padding: 0 108px 0 12px; color: var(--text); font-size: 1.3rem;
    background: var(--chip); border: 1px solid var(--stroke); border-radius: var(--r-2);
    transition: border-color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.station_query::placeholder { color: var(--text-3); }
.station_query:hover { background: var(--chip-hover); }
.station_query:focus-visible {
    outline: none; border-color: var(--stroke-strong); background: var(--surface-3);
    box-shadow: 0 0 0 2px var(--lit-bg);
}
.station_search_button, .coordinate_search_button, .current_location_button {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 32px; height: 32px; border-radius: var(--r-2); background-color: transparent;
    background-repeat: no-repeat; background-position: center; cursor: pointer;
    opacity: .68; transition: opacity var(--t) var(--ease), background-color var(--t) var(--ease);
}
.station_search_button:hover, .coordinate_search_button:hover, .current_location_button:hover {
    opacity: 1; background-color: var(--chip-hover);
}
.station_search_button {
    right: 2px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
}
.current_location_button {
    right: 34px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='17' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m20 4-7.2 16-2.2-6.6L4 11.2 20 4Z'/%3E%3C/svg%3E");
}
.coordinate_search_button {
    right: 66px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Ccircle cx='12' cy='12' r='8'/%3E%3Cpath d='M12 2v3M12 19v3M2 12h3M19 12h3'/%3E%3C/svg%3E");
}
[data-theme="light"] .station_search_button {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230b0d11' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
}
[data-theme="light"] .current_location_button {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='17' viewBox='0 0 24 24' fill='none' stroke='%230b0d11' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m20 4-7.2 16-2.2-6.6L4 11.2 20 4Z'/%3E%3C/svg%3E");
}
[data-theme="light"] .coordinate_search_button {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230b0d11' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Ccircle cx='12' cy='12' r='8'/%3E%3Cpath d='M12 2v3M12 19v3M2 12h3M19 12h3'/%3E%3C/svg%3E");
}
.current_location_button[aria-busy="true"] { opacity: .4; cursor: wait; }

.suggestions {
    position: absolute; top: calc(100% + 6px); left: 0; width: 100%; max-height: 260px; overflow-y: auto;
    background: var(--surface-2); border: 1px solid var(--stroke); border-radius: var(--r-3);
    box-shadow: var(--e-3); display: none; z-index: 1200; padding: 4px;
}
.station_suggestion_option {
    display: block; width: 100%; min-height: 38px; padding: 10px 12px; border-radius: var(--r-2);
    font-size: 1.3rem; color: var(--text-2); cursor: pointer; text-align: left;
    transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.station_suggestion_option:hover { background: var(--chip-hover); color: var(--text); }
.suggestion-empty { padding: 13px 12px; color: var(--text-3); font-size: 1.2rem; line-height: 1.5; text-wrap: pretty; }

/* 위경도 상세검색 팝오버 */
.coordinate_panel {
    min-width: 246px; padding: 16px; position: absolute; top: calc(100% + 6px); left: 0; z-index: 1100;
    background: var(--surface-2); border: 1px solid var(--stroke); border-radius: var(--r-3);
    box-shadow: var(--e-3); font-size: 1.3rem; color: var(--text); box-sizing: border-box;
}
.coordinate_panel h2 {
    min-height: 34px; display: flex; align-items: center; box-sizing: border-box; padding-right: 42px;
    font-family: var(--font-mono); font-size: 1.05rem; font-weight: 500; color: var(--text-3);
    letter-spacing: .015em; text-transform: none; margin-bottom: 10px;
}
.coordinate_panel p { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; color: var(--text-2); }
.coordinate_panel .coordinate_input {
    width: 152px; height: 38px; padding: 0 10px; font-family: var(--font-mono); font-size: 1.25rem;
    color: var(--text); background: var(--chip); border: 1px solid var(--stroke); border-radius: var(--r-2);
}
.coordinate_panel .coordinate_input:focus-visible {
    outline: none; border-color: var(--stroke-strong); box-shadow: 0 0 0 2px var(--lit-bg);
}
.coordinate_panel button.coordinate_lookup {
    display: block; width: 100%; height: 40px; margin-top: 12px; border-radius: var(--r-2);
    background: var(--accent); color: var(--on-accent); font-size: 1.35rem; font-weight: 700;
    transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.coordinate_panel button.coordinate_lookup:hover { filter: brightness(.94); }
.coordinate_panel button.coordinate_lookup:active { scale: .96; }
.coordinate_panel_close {
    position: absolute; top: 10px; right: 10px; width: 34px; height: 34px; line-height: 34px; text-align: center;
    border-radius: var(--r-2); background: transparent; color: var(--text-3); cursor: pointer; font-size: 1.2rem;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.coordinate_panel_close:hover { background: var(--chip-hover); color: var(--text); }

/* 상단 우측 액션 */
.top-actions { margin-left: 8px; display: flex; gap: 2px; }
.icon-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    height: 34px; min-width: 34px; padding: 0 10px; border-radius: var(--r-2);
    background: transparent; border: 1px solid transparent; color: var(--text-2);
    font-size: 1.15rem; font-weight: 600; cursor: pointer;
    transition: color var(--t) var(--ease), border-color var(--t) var(--ease),
        background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.icon-btn:hover { color: var(--text); background: var(--chip-hover); }
.icon-btn:active { scale: .96; }
.icon-btn.active { color: var(--text); background: var(--lit-bg); border-color: var(--lit-edge); }
.icon-btn svg { flex: none; }
.icon-btn .lbl { letter-spacing: -.01em; }

/* ===================== 좌측 설정 독 ===================== */

.dock {
    position: absolute; top: 52px; left: 0; bottom: 68px; z-index: 25;
    width: 304px; display: flex; flex-direction: column;
    background: var(--surface-solid);
    box-shadow: inset -1px 0 0 var(--stroke), 14px 0 40px -20px rgba(0, 0, 0, .7);
    transition: transform var(--t-slow) var(--ease), opacity var(--t) var(--ease);
}
.dock.collapsed { transform: translateX(-100%); opacity: 0; pointer-events: none; }
.dock_scroll {
    min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px 16px 22px;
    scrollbar-width: thin; scrollbar-color: var(--stroke-strong) transparent;
}
.dock_scroll::-webkit-scrollbar { width: 4px; }
.dock_scroll::-webkit-scrollbar-thumb { background: var(--stroke-strong); border-radius: 4px; }
.dock_header {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
    margin: 0 0 4px; padding: 0 0 13px; box-shadow: inset 0 -1px 0 var(--stroke);
}
.dock_heading { min-width: 0; }
.dock_heading h2 {
    color: var(--text); font-size: 1.45rem; font-weight: 700; letter-spacing: -.02em; text-wrap: balance;
}
.dock_heading p {
    margin-top: 5px; color: var(--text-3); font-family: var(--font-mono);
    font-size: 1.05rem; font-weight: 450; letter-spacing: .01em;
}
.dock_collapse {
    flex: none; width: 32px; height: 32px; margin: -3px -4px 0 0; border-radius: var(--r-2);
    background: transparent; color: var(--text-3); font-size: 1.7rem; line-height: 1;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.dock_collapse:hover { background: var(--chip-hover); color: var(--text); }
.dock_collapse:active { scale: .96; }

/* 지도 위 기상 요소 선택기 */
.explore_modes {
    position: absolute; top: 62px; left: 50%; z-index: 31; transform: translateX(-50%);
    display: flex; align-items: stretch; gap: 0; padding: 0 2px;
    border-radius: var(--r-2); background: var(--surface-solid);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-2);
}
.app:not([data-data-domain="weather"]) .explore_modes { display: none; }
.explore_modes button {
    position: relative; min-width: 66px; height: 34px; padding: 0 11px;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    border-radius: 0; color: var(--text-3); background: transparent;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.explore_modes button + button { box-shadow: inset 1px 0 0 var(--stroke); }
.explore_modes button:hover { color: var(--text); background: var(--chip); }
.explore_modes button:active { transform: scale(.96); }
.explore_modes button.on { color: var(--text); background: var(--lit-bg); }
.explore_modes button.on::after {
    content: ''; position: absolute; left: 9px; right: 9px; bottom: 0; height: 2px;
    background: var(--lit); animation: boraRise .22s var(--ease-spring) both;
}
.explore_modes .nav_icon { width: 15px; height: 15px; opacity: .68; }
.explore_modes button.on .nav_icon { opacity: 1; }
.explore_modes strong { font-size: 1.16rem; font-weight: 650; white-space: nowrap; }
.explore_mode_summary {
    position: absolute !important; width: 1px !important; height: 1px !important;
    padding: 0 !important; margin: -1px !important; overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important;
}

/* 필드 · 라벨 */
.field { margin-bottom: 15px; }
.field:last-child { margin-bottom: 4px; }
.field_compact { margin-bottom: 11px; }
.field > .flabel {
    display: flex; align-items: center; gap: 7px; margin-bottom: 9px;
    font-family: var(--font-ui); font-size: 1.1rem; font-weight: 650;
    letter-spacing: .01em; color: var(--text-2);
}
.field > .flabel::before {
    content: ''; flex: none; width: 7px; height: 1px; background: var(--stroke-strong);
}
.field > legend.flabel { width: 100%; }
.field > .flabel .sub {
    margin-left: auto; font-size: .98rem; font-weight: 400; letter-spacing: .01em; color: var(--text-3); opacity: 1;
}

/* 세그먼트 — 점등 상태는 명도로만 */
.seg {
    display: flex; padding: 2px; gap: 2px; background: var(--chip);
    border: 1px solid var(--stroke); border-radius: var(--r-2);
}
.seg button {
    flex: 1; height: 38px; border-radius: var(--r-1); font-size: 1.25rem; font-weight: 600;
    color: var(--text-2); white-space: nowrap;
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.seg button:hover { color: var(--text); background: var(--chip-hover); }
.seg button.on {
    background: var(--lit-bg); color: var(--text); font-weight: 700;
    box-shadow: inset 0 0 0 1px var(--lit-edge);
}
.seg button:disabled { cursor: not-allowed; color: var(--text-3); background: transparent; box-shadow: none; opacity: .55; }
.seg button:disabled:hover { color: var(--text-3); background: transparent; }
.seg.seg-3 button { font-size: 1.2rem; }
.metric_segment button { height: 50px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; }
.metric_segment button strong { font-size: 1.26rem; font-weight: 700; }
.metric_segment button small {
    color: currentColor; font-family: var(--font-mono); font-size: .85rem; font-weight: 400;
    letter-spacing: .04em; opacity: .6;
}
.metric_context[hidden] { display: none; }
.metric_context { margin-top: 11px; padding-top: 11px; box-shadow: inset 0 1px 0 var(--stroke); }
.metric_context > .flabel {
    width: 100%; margin-bottom: 8px; color: var(--text-2); font-family: var(--font-ui);
    font-size: 1.02rem; font-weight: 650; letter-spacing: .01em;
}
.metric_context_segment button {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
    min-width: 0; height: 44px; padding-inline: 6px;
}
.metric_context_segment button strong { max-width: 100%; overflow: hidden; font-size: 1.12rem; font-weight: 680; text-overflow: ellipsis; }
.metric_context_segment button small {
    max-width: 100%; overflow: hidden; color: currentColor; font-family: var(--font-mono);
    font-size: .8rem; font-weight: 400; opacity: .58; text-overflow: ellipsis;
}
.metric_context_single button { flex-direction: row; justify-content: flex-start; gap: 8px; padding-inline: 11px; }
.metric_context_single button small { margin-left: auto; }
.metric_disclosure { margin-top: 4px; box-shadow: inset 0 1px 0 var(--stroke); }
.metric_disclosure > summary {
    position: relative; display: flex; align-items: center; gap: 8px; min-height: 38px;
    padding: 7px 24px 7px 2px; color: var(--text-2); cursor: pointer; list-style: none; user-select: none;
}
.metric_disclosure > summary::-webkit-details-marker { display: none; }
.metric_disclosure > summary::after {
    content: ''; position: absolute; right: 7px; width: 5px; height: 5px;
    border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3);
    transform: rotate(45deg) translateY(-2px); transition: transform var(--t) var(--ease);
}
.metric_disclosure[open] > summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.metric_disclosure > summary:hover { color: var(--text); }
.metric_disclosure > summary span { font-size: 1.1rem; font-weight: 650; }
.metric_disclosure > summary small {
    margin-left: auto; color: var(--text-3); font-family: var(--font-mono);
    font-size: .96rem; font-weight: 400; letter-spacing: .01em;
}
.metric_disclosure_body { padding: 2px 0 8px; }
.metric_context_note { margin: 7px 2px 0; color: var(--text-3); font-size: .95rem; line-height: 1.45; text-wrap: pretty; }

/* 표시 레이어 — 다중 선택은 체크로 구분 */
.chiprow {
    display: flex; gap: 2px; padding: 2px; border: 1px solid var(--stroke);
    border-radius: var(--r-2); background: var(--chip);
}
.chiprow .chip {
    flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px; height: 38px;
    border-radius: var(--r-1); border: 0; background: transparent;
    color: var(--text-2); font-size: 1.18rem; font-weight: 600; white-space: nowrap;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease), opacity var(--t) var(--ease);
}
.chiprow .chip:hover { color: var(--text); background: var(--chip-hover); }
.chiprow .chip .dot {
    position: relative; flex: none; width: 12px; height: 12px; border-radius: var(--r-1); background: transparent;
    box-shadow: inset 0 0 0 1px var(--stroke-strong); transition: background-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.chiprow .chip.on { color: var(--text); background: var(--lit-bg); box-shadow: inset 0 0 0 1px var(--lit-edge); }
.chiprow .chip.on .dot { background: var(--accent); box-shadow: none; }
.chiprow .chip.on .dot::after {
    content: ''; position: absolute; left: 3px; top: 3px; width: 5px; height: 3px;
    border-left: 1.6px solid var(--on-accent); border-bottom: 1.6px solid var(--on-accent); transform: rotate(-45deg);
}
.chiprow .chip:disabled { opacity: .32; pointer-events: none; }

/* 오버레이 상태 피드백 — 채도 대신 명도 + 신호색 */
.air_quality_status, .cctv_status, .severe_weather_status {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 8px;
    margin-top: 8px; padding: 8px 10px; border-radius: var(--r-2); background: var(--chip);
    box-shadow: inset 0 0 0 1px var(--stroke);
    color: var(--text-2); font-size: 1rem; line-height: 1.45; text-wrap: pretty;
}
.dock_scrim { display: none; }
.air_quality_status[hidden], .cctv_status[hidden], .severe_weather_status[hidden] { display: none; }
.air_quality_status_icon, .cctv_status_icon, .severe_weather_status_icon {
    width: 7px; height: 7px; border-radius: 50%; background: var(--state-idle);
}
.air_quality_status[data-state="loading"] .air_quality_status_icon,
.cctv_status[data-state="loading"] .cctv_status_icon,
.severe_weather_status[data-state="loading"] .severe_weather_status_icon {
    width: 12px; height: 12px; border: 2px solid var(--stroke-strong); border-top-color: var(--text);
    background: transparent; animation: weatherGridSpin .8s linear infinite;
}
.air_quality_status[data-state="ready"] .air_quality_status_icon,
.cctv_status[data-state="ready"] .cctv_status_icon,
.severe_weather_status[data-state="ready"] .severe_weather_status_icon { background: var(--state-ready); }
.air_quality_status[data-state="stale"] .air_quality_status_icon,
.cctv_status[data-state="stale"] .cctv_status_icon,
.cctv_status[data-state="partial"] .cctv_status_icon,
.severe_weather_status[data-state="stale"] .severe_weather_status_icon { background: var(--state-stale); }
.cctv_status[data-state="zoom"] .cctv_status_icon { background: var(--state-ready); }
.air_quality_status[data-state="error"], .cctv_status[data-state="error"], .severe_weather_status[data-state="error"] {
    color: var(--signal-text); background: var(--signal-soft); box-shadow: inset 0 0 0 1px var(--signal-line);
}
.air_quality_status[data-state="error"] .air_quality_status_icon,
.cctv_status[data-state="error"] .cctv_status_icon,
.severe_weather_status[data-state="error"] .severe_weather_status_icon { background: var(--state-error); }
#air_quality_retry, #cctv_retry, #severe_weather_retry {
    min-height: 30px; padding: 0 10px; border-radius: var(--r-2); color: var(--on-accent); background: var(--accent);
    font-size: 1rem; font-weight: 700; transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
#air_quality_retry:hover, #cctv_retry:hover, #severe_weather_retry:hover { filter: brightness(.94); }
#air_quality_retry:active, #cctv_retry:active, #severe_weather_retry:active { scale: .96; }
#cctv_toggle { min-height: 42px; }

/* 위험기상 컨트롤 */
.hazard_layer_list { gap: 2px; }
.hazard_control_mark {
    position: relative; flex: none; width: 16px; height: 16px; color: var(--text-3);
    transition: color var(--t) var(--ease), opacity var(--t) var(--ease);
}
.hazard_control_typhoon::before {
    content: ''; position: absolute; inset: 2px; border: 2px solid currentColor; border-radius: 50%;
}
.hazard_control_typhoon::after {
    content: ''; position: absolute; left: 7px; top: 0; width: 2px; height: 7px;
    border-radius: 999px; background: currentColor; transform: rotate(40deg); transform-origin: 50% 100%;
}
.hazard_control_lightning {
    background: currentColor;
    clip-path: polygon(48% 0, 93% 0, 64% 39%, 89% 39%, 26% 100%, 42% 55%, 15% 55%);
}
.hazard_control_warning::before {
    content: ''; position: absolute; inset: 1px; border: 2px solid currentColor; border-radius: 50%;
}
.hazard_control_warning::after {
    content: ''; position: absolute; left: 7px; top: 4px; width: 2px; height: 6px;
    border-radius: 999px; background: currentColor; box-shadow: 0 8px 0 -0.3px currentColor;
}
.hazard_layer_button[aria-pressed="true"] { color: var(--text); background: var(--lit-bg); }
.hazard_layer_button[aria-pressed="true"] .hazard_control_typhoon { color: var(--hazard-typhoon); }
.hazard_layer_button[aria-pressed="true"] .hazard_control_lightning { color: var(--hazard-lightning); }
.hazard_warning_open:hover .hazard_control_warning,
.hazard_warning_open[aria-expanded="true"] .hazard_control_warning { color: var(--hazard-warning); }
.hazard_window {
    margin: 8px 0 0 26px; padding: 9px; border-radius: var(--r-2); background: var(--chip);
    box-shadow: inset 0 0 0 1px var(--stroke);
}
.hazard_window[hidden] { display: none; }
.hazard_window > .flabel {
    width: 100%; margin-bottom: 7px; color: var(--text-3); font-family: var(--font-mono);
    font-size: 1.02rem; font-weight: 550; letter-spacing: .015em; text-transform: none;
}
.hazard_window .seg { background: var(--surface-solid); }

/* 발표시각 그리드 */
.forecast_run_buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.forecast_run_buttons li { display: contents; }
.forecast_run_buttons li:last-child { display: none; }
.forecast_run_button {
    height: 38px; border-radius: var(--r-2); background: var(--chip); color: var(--text-2);
    font-family: var(--font-mono); font-size: 1.2rem; font-weight: 500; letter-spacing: .04em;
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease);
}
.forecast_run_button:hover { background: var(--chip-hover); color: var(--text); }
.forecast_run_button.on { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.forecast_run_button:disabled { opacity: .3; cursor: not-allowed; }
.forecast_run_button:disabled:hover { background: var(--chip); color: var(--text-2); }

/* 날짜 줄 */
.date_row { display: flex; gap: 6px; }
.latest_run_button {
    flex: none; height: 38px; padding: 0 13px; border-radius: var(--r-2);
    background: var(--accent); color: var(--on-accent);
    font-family: var(--font-mono); font-size: 1.15rem; font-weight: 600; letter-spacing: .06em;
    transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.latest_run_button:hover { filter: brightness(.94); }
.latest_run_button:active { scale: .96; }
.forecast_date_control { position: relative; flex: 1; }
.forecast_date_control .forecast_date_input {
    width: 100%; height: 38px; padding: 0 40px 0 11px; font-family: var(--font-mono);
    font-size: 1.25rem; font-weight: 500; color: var(--text);
    background: var(--chip); border: 1px solid var(--stroke); border-radius: var(--r-2);
}
.forecast_date_control .forecast_date_input:focus-visible {
    outline: none; border-color: var(--stroke-strong); box-shadow: 0 0 0 2px var(--lit-bg);
}
.forecast_date_control .forecast_date_input::-webkit-calendar-picker-indicator {
    width: 18px; height: 18px; padding: 8px; margin-right: -4px; cursor: pointer; opacity: .6;
}
.forecast_date_control .forecast_date_input:hover::-webkit-calendar-picker-indicator { opacity: 1; }

.base_run_current {
    display: grid; gap: 3px; margin-bottom: 9px; padding: 10px 11px; border-radius: var(--r-2);
    background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
}
.base_run_current span {
    color: var(--text-3); font-family: var(--font-mono); font-size: 1rem;
    font-weight: 500; letter-spacing: .01em;
}
.base_run_current strong {
    color: var(--text); font-family: var(--font-mono); font-size: 1.25rem;
    font-weight: 600; letter-spacing: .02em;
}
.base_run_actions { display: grid; grid-template-columns: 1fr auto 1fr; gap: 5px; margin-bottom: 15px; }
.base_run_actions button {
    min-width: 0; min-height: 38px; padding: 0 8px; border-radius: var(--r-2);
    color: var(--text-2); background: var(--chip); font-size: 1.05rem; font-weight: 650;
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease), transform var(--t-fast) var(--ease);
}
.base_run_actions button:hover:not(:disabled) { color: var(--text); background: var(--chip-hover); }
.base_run_actions button:active:not(:disabled) { transform: scale(.96); }
.base_run_actions .latest_run_button { height: auto; min-width: 56px; color: var(--on-accent); }
.base_run_actions button:disabled { opacity: .32; cursor: not-allowed; }
.forecast_base_time_label { margin-top: 13px; }

/* 레이어 토글 목록 */
.layer_list { display: flex; flex-direction: column; gap: 2px; }
.lswitch {
    display: flex; align-items: center; gap: 11px; min-height: 38px; padding: 0 10px; border-radius: var(--r-2);
    font-size: 1.28rem; font-weight: 600; color: var(--text-2); background: transparent;
    text-align: left; width: 100%;
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease);
}
.lswitch:hover { background: var(--chip-hover); color: var(--text); }
.lswitch .dot {
    flex: none; width: 8px; height: 8px; border-radius: 50%; background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--text-3);
    transition: background-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.lswitch.clicked { color: var(--text); background: var(--lit-bg); }
.lswitch.clicked .dot { background: var(--lit); box-shadow: 0 0 0 3px var(--lit-bg); }
.lswitch .sub {
    margin-left: auto; color: var(--text-3); font-family: var(--font-mono);
    font-size: .98rem; font-weight: 400; letter-spacing: .01em;
}
.infrastructure_toggle { min-height: 42px; }
.infrastructure_toggle .dot {
    width: 10px; height: 10px; border-radius: var(--r-1); background: currentColor; opacity: .5;
    box-shadow: none; transition: background-color var(--t) var(--ease), opacity var(--t) var(--ease), transform var(--t) var(--ease);
}
.infrastructure_toggle[data-infrastructure="bridge"] .dot { transform: rotate(45deg); }
.infrastructure_toggle[data-infrastructure="airport"] .dot { border-radius: 0; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.infrastructure_toggle.clicked .dot { opacity: 1; }
.infrastructure_toggle.clicked[data-infrastructure="bridge"] .dot { background: var(--infrastructure-bridge); }
.infrastructure_toggle.clicked[data-infrastructure="airport"] .dot { background: var(--infrastructure-airport); }
.infrastructure_toggle.clicked[data-infrastructure="port"] .dot { background: var(--infrastructure-port); }
.view3d_dock_open { display: none; margin-top: 6px; box-shadow: inset 0 0 0 1px var(--stroke); background: var(--chip); }
#btn_3d:disabled, .view3d_dock_open:disabled { opacity: .35; cursor: not-allowed; }

/* 독 섹션 */
.dock_disclosure { margin: 0; border: 0; background: transparent; overflow: clip; box-shadow: inset 0 -1px 0 var(--stroke); }
.dock_disclosure summary {
    position: relative; display: flex; align-items: center; min-height: 44px; padding: 8px 32px 8px 2px;
    color: var(--text); cursor: pointer; list-style: none; user-select: none;
}
.dock_disclosure summary::-webkit-details-marker { display: none; }
.dock_disclosure summary::after {
    content: ''; position: absolute; right: 9px; width: 6px; height: 6px;
    border-right: 1.8px solid var(--text-3); border-bottom: 1.8px solid var(--text-3);
    transform: rotate(45deg) translateY(-2px); transition: transform var(--t) var(--ease);
}
.dock_disclosure[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.dock_disclosure summary:hover { background: var(--chip); }
.dock_disclosure summary:focus-visible { outline-offset: -3px; }
.dock_disclosure summary > span {
    font-family: var(--font-ui); font-size: 1.22rem; font-weight: 700;
    letter-spacing: -.005em; color: var(--text-2);
}
.dock_disclosure[open] summary > span { color: var(--text); }
.dock_disclosure summary small { display: block; margin-top: 2px; color: var(--text-3); font-size: 1rem; font-weight: 600; }
.dock_disclosure_body { padding: 13px 2px 18px; box-shadow: inset 0 1px 0 var(--stroke); background: transparent; }

.advanced_disclosure { margin-top: 6px; box-shadow: inset 0 1px 0 var(--stroke); }
.advanced_disclosure > summary {
    position: relative; min-height: 40px; padding: 0 26px 0 2px; display: flex; align-items: center;
    color: var(--text-3); cursor: pointer; list-style: none; font-size: 1.1rem; font-weight: 620;
}
.advanced_disclosure > summary:hover { color: var(--text-2); }
.advanced_disclosure > summary::-webkit-details-marker { display: none; }
.advanced_disclosure > summary::after {
    content: ''; position: absolute; right: 8px; width: 5px; height: 5px;
    border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3);
    transform: rotate(45deg) translateY(-2px); transition: transform var(--t) var(--ease);
}
.advanced_disclosure[open] > summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.advanced_disclosure_body { padding: 4px 0 2px; }
.advanced_disclosure_body .field { margin-bottom: 8px; }

/* 선택한 데이터 영역에 필요한 조작만 노출 */
.app[data-data-domain="weather"] #field_air_quality,
.app[data-data-domain="weather"] #field_cctv,
.app[data-data-domain="air"] [data-domain-control="weather"],
.app[data-data-domain="air"] #field_cctv,
.app[data-data-domain="traffic"] [data-domain-control="weather"],
.app[data-data-domain="traffic"] #field_air_quality { display: none; }
.app[data-data-domain="air"] #layer_settings > summary,
.app[data-data-domain="traffic"] #layer_settings > summary { display: none; }
.app[data-data-domain="air"] #layer_settings .dock_disclosure_body,
.app[data-data-domain="traffic"] #layer_settings .dock_disclosure_body { padding-top: 14px; box-shadow: none; }
.app[data-data-domain="air"] #seg_air_quality [data-air="off"],
.app[data-data-domain="traffic"] #field_cctv .layer_list { display: none; }
.app[data-data-domain="traffic"] #forecast_source_settings { display: none; }
.app[data-explore-mode="hazards"] .metric_field,
.app[data-explore-mode="hazards"] #field_weather_render,
.app[data-explore-mode="hazards"] #field_weather_stations,
.app[data-explore-mode="hazards"] #forecast_source_settings { display: none; }

@media (min-width: 901px) {
    .metric_field > .flabel, .metric_field > .metric_segment { display: none !important; }
    .metric_field { margin-bottom: 7px; }
    .metric_context { margin-top: 0; padding-top: 0; box-shadow: none; }
}

#baseTime { display: none; }

/* 배경지도 선택 */
.basemap_picker { position: relative; }
.basemap_picker > ul { display: grid !important; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.basemap_picker ul > li { min-width: 0; }
.basemap_picker ul > li > button {
    position: relative; width: 100%; min-height: 44px; border-radius: var(--r-2); padding: 4px 4px 6px;
    text-align: center; cursor: pointer; background: var(--chip);
    box-shadow: inset 0 0 0 1px var(--stroke);
    transition: box-shadow var(--t) var(--ease), background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.basemap_picker ul > li > button:hover { box-shadow: inset 0 0 0 1px var(--stroke-strong); background: var(--chip-hover); }
.basemap_picker ul > li > button:active { scale: .96; }
.basemap_picker ul > li > button.is-selected-basemap {
    background: var(--lit-bg); box-shadow: inset 0 0 0 1.5px var(--lit-edge);
}
.basemap_picker ul li img {
    width: 100%; height: auto; aspect-ratio: 210 / 164; object-fit: cover; border-radius: var(--r-1); display: block;
    filter: saturate(.35) contrast(1.04) brightness(.82);
    transition: filter var(--t) var(--ease);
}
.basemap_picker ul button:hover img { filter: saturate(.7) brightness(.95); }
.basemap_picker ul button.is-selected-basemap img { filter: saturate(1) contrast(1.02) brightness(1); }
.basemap_picker ul span { display: block; margin-top: 5px; font-size: 1.02rem; font-weight: 600; color: var(--text-3); white-space: nowrap; }
.basemap_picker ul > li > button.is-selected-basemap span { color: var(--text); }
.basemap_picker ul .basemap_label {
    display: flex; min-height: 16px; align-items: center; justify-content: center; gap: 4px;
    letter-spacing: -.015em;
}
.basemap_picker .basemap_label .nav_icon { width: 13px; height: 13px; color: currentColor; opacity: 1; }

/* ===================== 우상단 범례 ===================== */

.legend_stack {
    position: absolute; top: 62px; right: 12px; z-index: 20;
    display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
    max-height: calc(100dvh - 148px); overflow-y: auto; overscroll-behavior: contain;
    padding: 1px; scrollbar-width: thin; scrollbar-color: var(--stroke-strong) transparent;
}

.legend {
    position: relative; width: 212px; padding: 11px 12px 12px;
    border-radius: var(--r-3); background: var(--surface-solid);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-2);
}
.legend_title {
    margin-bottom: 10px; padding-bottom: 9px; box-shadow: inset 0 -1px 0 var(--stroke);
    color: var(--text-2); font-family: var(--font-ui); font-size: 1.1rem; font-weight: 650;
    letter-spacing: .01em;
}
.legend_toggle {
    display: none; width: 100%; min-height: 36px; padding: 0 10px; align-items: center; justify-content: space-between;
    border-radius: var(--r-2); background: var(--chip); color: var(--text); font-size: 1.15rem; font-weight: 700;
    white-space: nowrap; transition: background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.legend_toggle::after {
    content: ''; width: 6px; height: 6px; margin-left: 8px;
    border-right: 1.8px solid var(--text-3); border-bottom: 1.8px solid var(--text-3);
    transform: rotate(45deg) translateY(-2px); transition: transform var(--t) var(--ease);
}
.legend_toggle:hover { background: var(--chip-hover); }
.legend_toggle:active { scale: .96; }
.legend.legend-collapsed .legend_toggle::after { transform: rotate(-45deg); }
.legend.legend-collapsed #legend_scale,
.legend.legend-collapsed .grid_stats { display: none; }

/* 동적 범례 — 12행 표를 '연속 램프 + 분포 프로파일' 계기로 바꾼다.
   DOM(.lg_row/.lg_label/.lg_share)은 그대로 두고 스와치를 맞붙여 하나의 색 기둥으로 읽힌다. */
#legend_scale { font-size: 1.02rem; color: var(--text-2); }
#legend_scale .lg_row {
    display: grid; grid-template-columns: 10px 4.7em minmax(34px, 1fr) 2.3em;
    align-items: stretch; gap: 0 9px; min-height: 17px; line-height: 17px;
    white-space: nowrap;
}
#legend_scale .lg_row > i {
    width: 10px; height: 100%; border-radius: 0;
    box-shadow: inset 1px 0 0 rgba(255, 255, 255, .10), inset -1px 0 0 rgba(0, 0, 0, .28);
}
#legend_scale .lg_row:first-child > i { border-radius: 3px 3px 0 0; }
#legend_scale .lg_row:last-child > i { border-radius: 0 0 3px 3px; }
#legend_scale .lg_label {
    overflow: hidden; text-overflow: ellipsis; color: var(--text-2);
    font-family: var(--font-ui); font-size: 1.05rem; font-weight: 500;
    letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
#legend_scale .lg_distribution,
.air_legend_distribution {
    align-self: center; display: block; height: 5px; overflow: hidden; border-radius: 999px;
    background: var(--chip-hover);
}
#legend_scale .lg_distribution > span,
.air_legend_distribution > span { display: block; height: 100%; min-width: 0; border-radius: inherit; }
#legend_scale .lg_share {
    color: var(--text-3); font-size: .96rem; text-align: right; align-self: center;
}
#legend_scale .lg_gradwrap {
    display: grid; grid-template-columns: 10px minmax(64px, 1fr) 34px; gap: 9px; align-items: stretch; height: 152px;
}
#legend_scale .lg_grad { width: 10px; border-radius: 3px; box-shadow: inset 1px 0 0 rgba(255,255,255,.10), inset -1px 0 0 rgba(0,0,0,.28); }
#legend_scale .lg_sun_histogram { display: grid; grid-template-rows: repeat(10, 1fr); gap: 2px; min-width: 0; }
#legend_scale .lg_sun_bin { display: flex; align-items: center; min-width: 0; border-radius: 999px; background: var(--chip); }
#legend_scale .lg_sun_bin i { display: block; height: 66%; border-radius: 999px; }
#legend_scale .lg_ticks {
    display: flex; flex-direction: column; justify-content: space-between;
    color: var(--text-3); font-size: .88rem; text-align: right;
}
#legend_scale .lg_unit {
    margin-top: 10px; padding-top: 9px; box-shadow: inset 0 1px 0 var(--stroke);
    color: var(--text-3); font-family: var(--font-ui); font-size: .98rem; text-align: left;
}
.grid_stats { margin-top: 10px; padding-top: 10px; box-shadow: inset 0 1px 0 var(--stroke); font-size: 1.05rem; color: var(--text-2); }
.grid_stats[hidden] { display: none; }
.grid_stats h3 {
    margin-bottom: 8px; color: var(--text-2); font-family: var(--font-ui); font-size: 1.05rem;
    font-weight: 650; letter-spacing: .01em; text-align: left; font-variant-numeric: tabular-nums;
}
.grid_stats dl { display: grid; gap: 2px; margin: 0; }
.grid_stats dl div { display: flex; justify-content: space-between; gap: 12px; line-height: 1.7; white-space: nowrap; }
.grid_stats dt { color: var(--text-3); font-size: 1.05rem; }
.grid_stats dd { margin: 0; color: var(--text); font-size: 1.12rem; font-weight: 600; }

/* PM 범례 */
.air_legend { width: 212px; }
.air_legend[hidden] { display: none; }
.air_legend_gauge { margin-bottom: 10px; padding-bottom: 10px; box-shadow: inset 0 -1px 0 var(--stroke); }
.air_legend_rows { display: grid; gap: 7px; }
.air_legend_row { display: grid; gap: 3px; min-height: 26px; color: var(--text-2); font-size: .98rem; }
.air_legend_row_head { display: grid; grid-template-columns: 11px minmax(50px, 1fr) auto 26px; align-items: center; gap: 7px; }
.air_legend_row_head i { width: 11px; height: 8px; border-radius: 2px; }
.air_legend_row strong { color: var(--text); font-weight: 650; white-space: nowrap; }
.air_legend_row span { white-space: nowrap; font-family: var(--font-mono); font-size: .9rem; }
.air_legend_count { color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; text-align: right; }
.air_legend_meta {
    display: grid; gap: 3px; margin-top: 9px; padding-top: 9px; box-shadow: inset 0 1px 0 var(--stroke);
    color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; line-height: 1.5; letter-spacing: .02em;
}
.air_legend_notice { margin-top: 7px; color: var(--text-3); font-size: .85rem; line-height: 1.5; }
.air_legend.legend-collapsed .air_legend_body { display: none; }

/* 위험기상 범례 */
.hazard_legend { width: 212px; }
.hazard_legend[hidden] { display: none; }
.hazard_legend.legend-collapsed .hazard_legend_body { display: none; }
.hazard_legend_rows { display: grid; gap: 7px; }
.hazard_legend_rows li {
    display: grid; grid-template-columns: 26px minmax(0, 1fr); align-items: center; gap: 9px;
    min-height: 18px; color: var(--text-2); font-size: 1rem;
}
.hazard_legend_rows i { position: relative; display: block; width: 24px; height: 12px; }
.hazard_legend_rows [data-hazard-legend="typhoon-analysis"] i::before,
.hazard_legend_rows [data-hazard-legend="typhoon-forecast"] i::before {
    content: ''; position: absolute; left: 0; right: 0; top: 5px; border-top: 2px solid var(--hazard-typhoon);
}
.hazard_legend_rows [data-hazard-legend="typhoon-analysis"] i::after,
.hazard_legend_rows [data-hazard-legend="typhoon-forecast"] i::after {
    content: ''; position: absolute; right: 1px; top: 2px; width: 7px; height: 7px;
    border: 2px solid var(--hazard-typhoon); border-radius: 50%; background: var(--surface-solid);
}
.hazard_legend_rows [data-hazard-legend="typhoon-forecast"] i::before { border-top-style: dashed; opacity: .86; }
.hazard_legend_rows [data-hazard-legend="lightning-ground"] i::before {
    content: ''; position: absolute; left: 8px; top: 0; width: 10px; height: 12px;
    background: var(--hazard-lightning); clip-path: polygon(48% 0, 95% 0, 63% 42%, 88% 42%, 20% 100%, 40% 56%, 12% 56%);
}
.hazard_legend_rows [data-hazard-legend="lightning-cloud"] i::before {
    content: ''; position: absolute; left: 8px; top: 1px; width: 9px; height: 9px;
    border: 2px solid var(--hazard-cloud); border-radius: 50%; background: color-mix(in srgb, var(--hazard-cloud) 20%, transparent);
}
.hazard_legend_meta {
    display: grid; gap: 3px; margin-top: 9px; padding-top: 9px; box-shadow: inset 0 1px 0 var(--stroke);
    color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; line-height: 1.5;
}

/* PM 등급 게이지 */
.air_gauge { min-width: 0; font-variant-numeric: tabular-nums; }
.air_gauge_track { position: relative; display: flex; gap: 2px; height: 9px; }
.air_gauge_segment { flex: 1; min-width: 0; border-radius: 2px; }
.air_gauge_segment:first-child { border-radius: 999px 2px 2px 999px; }
.air_gauge_segment:nth-child(4) { border-radius: 2px 999px 999px 2px; }
.air_gauge_labels { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; margin-top: 5px; }
.air_gauge_labels span { min-width: 0; color: var(--text-3); font-size: .92rem; text-align: center; white-space: nowrap; }
.air_gauge_marker {
    position: absolute; z-index: 2; top: -3px; width: 2px; height: 15px; transform: translateX(-50%);
    border-radius: 999px; background: var(--text); box-shadow: 0 0 0 2px var(--surface-solid);
}
.air_gauge_value {
    position: absolute; left: 50%; bottom: calc(100% + 5px); transform: translateX(-50%);
    min-width: 24px; padding: 2px 5px; border-radius: var(--r-1); color: var(--text); background: var(--surface-3);
    box-shadow: inset 0 0 0 1px var(--stroke-strong);
    font-family: var(--font-mono); font-size: .84rem; font-weight: 600; line-height: 1.25; text-align: center;
}

/* ===================== 알림 · 오류 · 특보 ===================== */

#data_error {
    position: absolute; top: 104px; left: 50%; z-index: 32; transform: translateX(-50%);
    display: flex; align-items: center; gap: 10px; max-width: min(520px, calc(100vw - 32px));
    padding: 8px 8px 8px 14px; border-radius: var(--r-2); color: var(--signal-text);
    background: var(--signal-bg); box-shadow: inset 0 0 0 1px var(--signal-line), var(--e-2);
    font-size: 1.2rem; font-weight: 650;
}
#data_error[hidden] { display: none; }
#data_error span { min-width: 0; text-wrap: pretty; }
#retry_data {
    flex: none; min-height: 32px; padding: 0 12px; border-radius: var(--r-2);
    background: var(--signal); color: #fff; font-size: 1.15rem; font-weight: 700;
    transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
#retry_data:hover { filter: brightness(1.08); }
#retry_data:active { scale: .96; }

.warning_banner {
    position: absolute; top: 104px; left: 50%; z-index: 29; transform: translateX(-50%);
    display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; align-items: center; gap: 9px;
    width: max-content; max-width: min(520px, calc(100vw - 32px)); min-height: 36px; padding: 7px 12px;
    border-radius: var(--r-2); color: var(--text); background: var(--surface-solid);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hazard-warning) 40%, var(--stroke)), var(--e-2);
    text-align: left;
    transition: background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.warning_banner[hidden] { display: none; }
.warning_banner:hover { background: var(--surface-2); }
.warning_banner:active { scale: .96; }
.warning_banner_mark {
    width: 8px; height: 8px; border-radius: 50%; background: var(--hazard-warning);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--hazard-warning) 15%, transparent);
}
.warning_banner strong { font-size: 1.14rem; font-weight: 750; white-space: nowrap; }
.warning_banner #warning_banner_summary {
    min-width: 0; overflow: hidden; color: var(--text-2); font-size: 1.05rem;
    text-overflow: ellipsis; white-space: nowrap;
}
.warning_banner_chevron {
    width: 6px; height: 6px; margin: 0 3px 3px 4px; border-right: 2px solid var(--text-3); border-bottom: 2px solid var(--text-3);
    transform: rotate(45deg); transition: transform var(--t) var(--ease);
}
.warning_banner[aria-expanded="true"] .warning_banner_chevron { transform: rotate(225deg) translate(-2px, -2px); }
.warning_banner[data-severity="critical"] { box-shadow: inset 0 0 0 1px var(--signal-line), var(--e-2); }
.warning_banner[data-severity="critical"] .warning_banner_mark { background: var(--signal); box-shadow: 0 0 0 4px var(--signal-soft); }
#data_error:not([hidden]) ~ .warning_banner { top: 164px; }

.warning_panel {
    position: absolute; top: 150px; left: 50%; z-index: 29; transform: translateX(-50%);
    width: min(440px, calc(100vw - 24px)); max-height: min(56dvh, 520px); overflow-y: auto; overscroll-behavior: contain;
    padding: 15px; border-radius: var(--r-3); color: var(--text); background: var(--surface-solid);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-3);
}
.warning_panel[hidden] { display: none; }
#data_error:not([hidden]) ~ .warning_panel { top: 212px; }
.warning_panel_header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.warning_panel_header > div { min-width: 0; }
.warning_panel_header span {
    display: block; margin-bottom: 4px; color: var(--text-3); font-family: var(--font-mono);
    font-size: 1.02rem; font-weight: 550; letter-spacing: .015em; text-transform: none;
}
.warning_panel_header h2 { font-size: 1.4rem; font-weight: 750; text-wrap: balance; }
.warning_panel_close {
    flex: none; width: 34px; height: 34px; margin: -5px -5px 0 0; border-radius: var(--r-2);
    background: transparent; color: var(--text-3); font-size: 1.7rem; line-height: 1;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.warning_panel_close:hover { color: var(--text); background: var(--chip-hover); }
.warning_panel_close:active { scale: .96; }
.warning_panel_status { margin: 10px 0; color: var(--text-3); font-size: 1.02rem; line-height: 1.5; text-wrap: pretty; }
.warning_list { display: grid; gap: 6px; }
.warning_item { padding: 11px; border-radius: var(--r-2); background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke); }
.warning_item_header { display: flex; align-items: center; gap: 8px; min-width: 0; }
.warning_item_header strong { min-width: 0; overflow-wrap: anywhere; font-size: 1.16rem; font-weight: 750; }
.warning_level {
    flex: none; padding: 3px 7px; border-radius: 999px; color: var(--on-accent); background: var(--hazard-lightning);
    font-family: var(--font-mono); font-size: .82rem; font-weight: 600; letter-spacing: .04em;
}
.warning_level[data-severity="critical"] { color: #fff; background: var(--signal); }
.warning_item p { margin-top: 7px; color: var(--text-2); font-size: 1.02rem; line-height: 1.5; text-wrap: pretty; }
.warning_item time { display: block; margin-top: 6px; color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; }
.warning_panel_source {
    margin-top: 11px; padding-top: 10px; box-shadow: inset 0 1px 0 var(--stroke);
    color: var(--text-3); font-size: .85rem; line-height: 1.5; text-wrap: pretty;
}

/* 현재 지도 정보 — 설정 토글이 상단 바로 올라가 겹침이 사라졌다 */
.map_status_panel {
    position: absolute; z-index: 20; left: 12px; top: 62px;
    display: flex; align-items: center; gap: 0; min-height: 34px; padding: 0; color: var(--text);
    border-radius: var(--r-2); background: var(--surface-solid);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-2); white-space: nowrap; overflow: hidden;
}
.info_metric { padding: 0 11px; font-size: 1.18rem; font-weight: 750; letter-spacing: -.01em; }
.info_time {
    padding: 0 11px; box-shadow: inset 1px 0 0 var(--stroke);
    color: var(--text-2); font-size: 1.05rem; font-weight: 500; letter-spacing: .01em;
}
.info_hint {
    padding: 0 11px; box-shadow: inset 1px 0 0 var(--stroke);
    color: var(--text-3); font-size: 1.05rem; font-weight: 500;
}
.info_hint::before { content: none; }

/* ===================== 하단 타임라인 ===================== */

.timeline {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 25; width: auto;
    display: flex; align-items: center; gap: 14px;
    min-height: 76px; padding: 8px 16px 12px;
    background: var(--surface-solid);
    box-shadow: inset 0 1px 0 var(--stroke), 0 -14px 34px -22px rgba(0, 0, 0, .85);
}
.app[data-data-domain="traffic"] .timeline,
.app[data-explore-mode="hazards"] .timeline { display: none; }
.app[data-data-domain="traffic"] .dock,
.app[data-explore-mode="hazards"] .dock { bottom: 0; }
.app[data-data-domain="traffic"] .ol-zoom,
.app[data-explore-mode="hazards"] .ol-zoom { bottom: max(12px, env(safe-area-inset-bottom, 0px)); }

.forecast_run_list { display: flex; gap: 2px; flex: none; }
.forecast_run_list button {
    width: 34px; height: 34px; border-radius: var(--r-2); background: transparent; color: var(--text-2);
    display: inline-flex; align-items: center; justify-content: center;
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.forecast_run_list button:hover { background: var(--chip-hover); color: var(--text); }
.forecast_run_list button:active { scale: .96; }
.forecast_run_list button svg { display: block; }
#btn_play { background: var(--chip); }
#btn_play.playing { background: var(--accent); color: var(--on-accent); }

/* 캡션을 오른쪽으로 옮겨 트랙 위에 툴팁이 놓일 빈 공간을 확보한다 */
.timeline_content { flex: 1; min-width: 0; display: flex; align-items: center; gap: 16px; }
.timeline_caption {
    order: 2; flex: none; display: grid; gap: 2px; margin: 0; text-align: right;
    color: var(--text-3); font-size: 1.02rem; line-height: 1.3;
}
.timeline_caption strong {
    color: var(--text-2); font-family: var(--font-mono); font-size: 1rem; font-weight: 550;
    letter-spacing: .01em;
}
.timeline_caption span::before { content: none; }
.forecast_timeline { order: 1; position: relative; flex: 1; min-width: 0; padding: 24px 2px 5px; }
.forecast_timeline ul {
    position: relative; display: flex; align-items: center; pointer-events: none;
}
.forecast_timeline ul::before {
    content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 2px;
    transform: translateY(-50%); border-radius: 2px; background: rgba(255, 255, 255, .16);
}
.forecast_timeline li { flex: 1; position: relative; padding: 7px 0; }
.forecast_timeline li button {
    display: block; width: 100%; height: 3px; border-radius: 0; padding: 0;
    background: transparent; transition: background-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
    pointer-events: none;
}
[data-theme="light"] .forecast_timeline ul::before { background: rgba(11, 13, 17, .16); }
.forecast_timeline li { z-index: 1; }
.forecast_timeline li:nth-child(6n+1)::before {
    content: ''; position: absolute; left: 0; top: 1px; bottom: 1px; width: 1px;
    background: var(--stroke-strong); pointer-events: none;
}
/* 지나온 구간을 채워 진행도를 드러낸다 */
.forecast_timeline li:has(~ li.on) button { background: color-mix(in srgb, var(--lit) 62%, transparent); }
.forecast_timeline li.on button {
    background: var(--lit); transform: scaleY(3.4);
    box-shadow: 0 0 12px color-mix(in srgb, var(--lit) 55%, transparent);
}
.forecast_timeline li span {
    display: none; position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
    padding: 4px 9px; border-radius: var(--r-2); font-size: 1.1rem; font-weight: 500; white-space: nowrap;
    background: var(--surface-3); color: var(--text); box-shadow: inset 0 0 0 1px var(--stroke-strong), var(--e-1);
    letter-spacing: .01em;
}
.forecast_timeline li.on span { display: block; }
.forecast_timeline li:first-child span { left: 0; transform: none; }
.forecast_timeline li:last-child span { right: 0; left: auto; transform: none; }
.forecast_scrubber {
    position: absolute; z-index: 3; top: 20px; left: 0; width: 100%; height: 32px; margin: 0; padding: 0;
    appearance: none; -webkit-appearance: none; border: 0; background: transparent; cursor: ew-resize;
    touch-action: pan-y; accent-color: var(--accent);
}
.forecast_scrubber::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: transparent; }
.forecast_scrubber::-webkit-slider-thumb {
    width: 15px; height: 15px; margin-top: -4px; appearance: none; -webkit-appearance: none;
    border: 3px solid var(--surface-solid); border-radius: 50%; background: var(--lit);
    box-shadow: 0 0 0 1px var(--stroke-strong), 0 2px 10px rgba(0, 0, 0, .5);
}
.forecast_scrubber::-moz-range-track { height: 6px; border: 0; border-radius: 999px; background: transparent; }
.forecast_scrubber::-moz-range-progress { height: 6px; border-radius: 999px; background: transparent; }
.forecast_scrubber::-moz-range-thumb {
    width: 13px; height: 13px; border: 3px solid var(--surface-solid); border-radius: 50%;
    background: var(--lit); box-shadow: 0 0 0 1px var(--stroke-strong);
}
.forecast_scrubber:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: var(--r-2); }
.forecast_timeline_ticks { display: flex; justify-content: space-between; gap: 4px; padding: 5px 2px 0; line-height: 1.35; }
.forecast_timeline_ticks span { min-width: 0; font-size: .98rem; color: var(--text-2); white-space: nowrap; letter-spacing: .01em; }

/* ===================== 지도 팝업 ===================== */

.coordinate_popup {
    position: absolute; z-index: 1000; display: none; width: min(248px, calc(100vw - 16px)); min-width: 0;
    max-height: calc(100dvh - 16px); overflow-y: auto; box-sizing: border-box;
    padding: 14px; border-radius: var(--r-3);
    background: var(--surface-solid); box-shadow: 0 0 0 1px var(--stroke), var(--e-3);
    font-size: 1.3rem; color: var(--text);
}
.popup_content { font-size: 1.25rem; padding-right: 36px; }
.coordinate_latitude_field, .coordinate_longitude_field { display: flex; justify-content: space-between; gap: 14px; padding: 3px 0; border: 0; margin: 0; }
.coordinate_popup .label { font-weight: 500; color: var(--text-3); font-size: 1.1rem; }
.latitude, .longitude { margin: 0; font-size: 1.25rem; font-weight: 500; }
.coordinate_popup_actions { position: absolute; top: 9px; right: 9px; }
.coordinate_popup_close {
    position: static; width: 32px; height: 32px; border-radius: var(--r-2); font-size: 1.3rem;
    background: transparent; color: var(--text-3); border: none; cursor: pointer;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.coordinate_popup_close:hover { background: var(--chip-hover); color: var(--text); }
.station_chart_shell { margin-top: 12px; padding: 0; border: 0; background: transparent; text-align: center; }
.station_timeline_button {
    width: 100%; min-height: 38px; padding: 9px 0; border-radius: var(--r-2); font-size: 1.25rem; font-weight: 700;
    background: var(--accent); color: var(--on-accent);
    transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.station_timeline_button:hover { filter: brightness(.94); }
.station_timeline_button:active { scale: .96; }

.air_popup, .cctv_popup, .hazard_popup {
    position: absolute; box-sizing: border-box;
    max-height: calc(100dvh - 16px); overflow-y: auto; overscroll-behavior: contain;
    padding: 15px; border-radius: var(--r-3); color: var(--text); background: var(--surface-solid);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-3);
}
.air_popup { z-index: 1002; width: min(330px, calc(100vw - 16px)); }
.cctv_popup { z-index: 1003; width: min(344px, calc(100vw - 16px)); }
.hazard_popup {
    --hazard-popup-color: var(--hazard-warning);
    z-index: 1004; width: min(330px, calc(100vw - 16px));
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--hazard-popup-color) 34%, var(--stroke)), var(--e-3);
}
.air_popup[hidden], .cctv_popup[hidden], .hazard_popup[hidden] { display: none; }
.hazard_popup[data-kind="typhoon"] { --hazard-popup-color: var(--hazard-typhoon); }
.hazard_popup[data-kind="lightning"] { --hazard-popup-color: var(--hazard-lightning); }

.air_popup_header, .cctv_popup_header, .hazard_popup_header {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding-right: 2px;
}
.hazard_popup_header > div { min-width: 0; }
.air_popup_eyebrow, .cctv_popup_eyebrow, .hazard_popup_eyebrow {
    display: block; margin-bottom: 4px; color: var(--text-3); font-family: var(--font-mono);
    font-size: 1.02rem; font-weight: 550; letter-spacing: .015em; text-transform: none;
}
.air_popup_header h2, .cctv_popup_header h2, .hazard_popup_header h2 {
    color: var(--text); font-size: 1.42rem; font-weight: 780; text-wrap: balance; overflow-wrap: anywhere;
}
.air_popup_close, .cctv_popup_close, .hazard_popup_close {
    flex: none; width: 34px; height: 34px; margin: -6px -6px 0 0; border-radius: var(--r-2);
    background: transparent; color: var(--text-3); font-size: 1.7rem; line-height: 1;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.air_popup_close:hover, .cctv_popup_close:hover, .hazard_popup_close:hover { color: var(--text); background: var(--chip-hover); }
.air_popup_close:active, .cctv_popup_close:active, .hazard_popup_close:active { scale: .96; }

.air_popup_measure {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; margin: 14px 0 12px;
    font-size: 1rem; color: var(--text-3); font-family: var(--font-mono);
}
.air_popup_measure > span:first-child {
    color: var(--text-2); font-size: 1.05rem; font-weight: 500; letter-spacing: .1em;
}
.air_popup_measure strong {
    color: var(--text); font-family: var(--font-mono); font-size: 2.9rem; font-weight: 600; letter-spacing: -.04em;
}
.air_grade_badge {
    margin-left: auto; padding: 4px 8px; border-radius: 999px; color: var(--text);
    background: color-mix(in srgb, var(--grade-color, #64748b) 22%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--grade-color, #64748b) 68%, transparent);
    font-family: var(--font-ui); font-size: .98rem; font-weight: 750; white-space: nowrap;
}
.air_popup_gauges {
    display: grid; gap: 7px; margin: 10px 0 12px; padding: 10px; border-radius: var(--r-2);
    background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
}
.air_popup_gauge_row {
    display: grid; grid-template-columns: 42px minmax(0, 1fr); align-items: center; gap: 9px;
    min-height: 34px; padding: 4px 5px; border-radius: var(--r-2);
}
.air_popup_gauge_row.is-current { background: var(--lit-bg); box-shadow: inset 0 0 0 1px var(--lit-edge); }
.air_popup_gauge_row > strong { color: var(--text-3); font-family: var(--font-mono); font-size: .92rem; font-weight: 600; letter-spacing: .06em; }
.air_popup_gauge_row.is-current > strong { color: var(--text); }
.air_popup_gauge { padding-top: 14px; }

.air_popup_meta, .cctv_popup_meta, .hazard_popup_meta {
    display: grid; gap: 6px; padding: 11px; border-radius: var(--r-2); background: var(--chip);
    box-shadow: inset 0 0 0 1px var(--stroke);
}
.air_popup_meta > div { grid-template-columns: 56px minmax(0, 1fr); }
.cctv_popup_meta > div { grid-template-columns: 62px minmax(0, 1fr); }
.hazard_popup_meta > div { grid-template-columns: 70px minmax(0, 1fr); }
.air_popup_meta > div, .cctv_popup_meta > div, .hazard_popup_meta > div {
    display: grid; gap: 9px; font-size: 1rem; line-height: 1.5;
}
.air_popup_meta dt, .cctv_popup_meta dt, .hazard_popup_meta dt { color: var(--text-3); font-weight: 600; }
.air_popup_meta dd, .cctv_popup_meta dd, .hazard_popup_meta dd {
    min-width: 0; color: var(--text-2); overflow-wrap: anywhere; font-variant-numeric: tabular-nums;
}
.air_popup_source, .cctv_popup_source, .hazard_popup_source {
    margin-top: 9px; color: var(--text-3); font-size: .85rem; text-align: right; line-height: 1.5;
}
.hazard_popup_summary {
    margin: 12px 0; padding: 10px 11px; border-radius: var(--r-2);
    color: var(--text); background: color-mix(in srgb, var(--hazard-popup-color) 9%, var(--chip));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hazard-popup-color) 26%, transparent);
    font-size: 1.06rem; font-weight: 600; line-height: 1.55; text-wrap: pretty;
}

/* CCTV 미디어 */
.cctv_cluster_picker { margin-top: 12px; padding: 11px; border-radius: var(--r-2); color: var(--text-2); background: var(--chip); }
.cctv_cluster_picker[hidden], .cctv_media[hidden], .cctv_popup_meta[hidden], .cctv_popup_source[hidden] { display: none; }
.cctv_cluster_picker > p { margin: 0 0 8px; color: var(--text-3); font-size: .98rem; line-height: 1.5; }
.cctv_cluster_list { display: grid; gap: 5px; max-height: 280px; margin: 0; padding: 0; overflow-y: auto; list-style: none; }
.cctv_cluster_list button {
    display: grid; width: 100%; min-height: 42px; padding: 8px 10px; border: 0;
    border-radius: var(--r-2); color: var(--text); background: var(--surface-2); text-align: left;
    box-shadow: inset 0 0 0 1px var(--stroke);
    transition: box-shadow var(--t) var(--ease), background-color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.cctv_cluster_list button:hover { background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--stroke-strong); }
.cctv_cluster_list button:active { scale: .96; }
.cctv_cluster_list strong { overflow-wrap: anywhere; font-size: 1.02rem; line-height: 1.4; }
.cctv_cluster_list span { margin-top: 2px; color: var(--text-3); font-size: .9rem; line-height: 1.4; }
.cctv_media {
    position: relative; display: grid; place-items: center; aspect-ratio: 16 / 9; min-height: 166px;
    margin: 12px 0; overflow: hidden; border-radius: var(--r-2); color: var(--text-2); background: #05070A;
    box-shadow: inset 0 0 0 1px var(--stroke);
}
.cctv_media_placeholder { display: grid; justify-items: center; gap: 9px; padding: 14px; text-align: center; }
.cctv_media_placeholder[hidden], .cctv_media video[hidden], .cctv_media_status[hidden] { display: none; }
.cctv_camera_mark {
    position: relative; width: 34px; height: 23px; border: 2px solid var(--text-2); border-radius: var(--r-1);
}
.cctv_camera_mark::before {
    content: ''; position: absolute; left: 50%; top: 50%; width: 9px; height: 9px;
    border: 2px solid var(--text-2); border-radius: 50%; transform: translate(-50%, -50%);
}
.cctv_camera_mark::after {
    content: ''; position: absolute; right: -9px; top: 5px; width: 8px; height: 10px;
    background: var(--text-2); clip-path: polygon(0 20%, 100% 0, 100% 100%, 0 80%);
}
.cctv_play {
    min-height: 40px; padding: 0 16px; border-radius: var(--r-2); color: #05070A; background: #F3F5F8;
    font-size: 1.08rem; font-weight: 750; transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.cctv_play:hover { filter: brightness(.92); }
.cctv_play:active { scale: .96; }
.cctv_play:disabled { opacity: .5; cursor: wait; }
.cctv_media[data-state="unavailable"] .cctv_play:disabled { cursor: not-allowed; }
.cctv_media_placeholder p { color: var(--text-3); font-size: .92rem; text-wrap: pretty; }
.cctv_media video { display: block; width: 100%; height: 100%; object-fit: contain; background: #000; }
.cctv_media_status {
    position: absolute; left: 10px; right: 10px; bottom: 48px; margin: 0; padding: 8px 10px;
    border-radius: var(--r-2); color: #E7EAEE; background: rgba(5, 7, 10, .9); font-size: .98rem; text-align: center;
    text-wrap: pretty; pointer-events: none;
}
.cctv_media[data-state="loading"] .cctv_camera_mark { animation: cctv-pulse 1.1s ease-in-out infinite; }
.cctv_media[data-state="error"] .cctv_media_status { color: var(--signal-text); background: rgba(58, 12, 4, .94); }
.cctv_media[data-state="unavailable"] .cctv_media_status { color: #FCE9C4; background: rgba(58, 38, 4, .94); }
@keyframes cctv-pulse { 50% { opacity: .4; scale: .94; } }

/* API 미연결 데모 배지 */
#mock_badge {
    position: absolute; top: 62px; left: 50%; transform: translateX(-50%); z-index: 21;
    padding: 6px 13px; border-radius: 999px; font-size: 1.12rem; font-weight: 650;
    color: var(--signal-text); background: var(--signal-bg); box-shadow: inset 0 0 0 1px var(--signal-line);
    max-width: min(460px, calc(100vw - 24px)); box-sizing: border-box; text-align: center; text-wrap: balance;
}
.mock_badge_mark {
    display: inline-block; width: 8px; height: 8px; margin-right: 7px; border-radius: 50%;
    background: var(--signal); box-shadow: 0 0 0 3px var(--signal-soft);
}

/* 커서 리드아웃 */
#cursor_readout {
    display: none; position: absolute; left: 14px; bottom: 16px; z-index: 22;
    padding: 7px 11px; border-radius: var(--r-2); font-family: var(--font-mono); font-size: 1.05rem;
    color: var(--text-2); background: var(--surface-solid);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-1);
    font-variant-numeric: tabular-nums; pointer-events: none; white-space: nowrap;
}
#cursor_readout b { color: var(--text); font-weight: 600; margin-left: 5px; }

/* ===================== 시계열 모달 ===================== */

.station_modal {
    position: fixed; inset: 0; z-index: 1500;
    background: rgba(3, 5, 8, .72); overscroll-behavior: contain;
}
[data-theme="light"] .station_modal { background: rgba(11, 13, 17, .42); }
.popup {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: min(1180px, calc(100vw - 40px)); max-height: calc(100vh - 48px); overflow: hidden;
    display: flex; flex-direction: column;
    background: var(--surface-solid); border-radius: var(--r-4);
    box-shadow: 0 0 0 1px var(--stroke-strong), var(--e-3);
    animation: boraModalIn .28s var(--ease-spring) both;
}
@keyframes boraModalIn {
    from { opacity: 0; transform: translate(-50%, -46%) scale(.985); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
/* 파랑→보라 그라디언트 헤더를 걷어내고 무채색 계기 헤더로 */
.station_modal_header {
    position: relative; flex: none; display: flex; align-items: center;
    padding: 17px 22px; background: var(--surface-2);
    border-radius: var(--r-4) var(--r-4) 0 0; box-shadow: inset 0 -1px 0 var(--stroke);
}
.station_modal_header h2 {
    color: var(--text); font-size: 1.5rem; font-weight: 700; padding: 0 48px 0 0;
    letter-spacing: -.015em; text-wrap: balance;
}
.station_modal_header .station_modal_close {
    position: absolute; top: 50%; right: 14px; transform: translateY(-50%);
    width: 36px; height: 36px; border-radius: var(--r-2);
    font-size: 1.9rem; font-weight: 300; color: var(--text-3); background: transparent;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease);
}
.station_modal_header .station_modal_close:hover { background: var(--chip-hover); color: var(--text); }
.station_modal_body { padding: 16px; overflow-y: auto; overscroll-behavior: contain; background: var(--bg); }
[data-theme="light"] .station_modal_body { background: var(--surface-2); }

.station_chart_error {
    min-height: 220px; height: 100%; display: grid; place-items: center; box-sizing: border-box;
    align-content: center; gap: 14px; padding: 24px; border-radius: var(--r-3); color: var(--text-2);
    background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
    font-size: 1.18rem; line-height: 1.6; text-align: center; text-wrap: pretty;
}
.station_chart_retry, #forecast_strip_retry {
    min-height: 36px; padding: 0 15px; border-radius: var(--r-2); color: var(--on-accent); background: var(--accent);
    font-size: 1.12rem; font-weight: 750; transition: filter var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.station_chart_retry:hover, #forecast_strip_retry:hover { filter: brightness(.94); }
.station_chart_retry:active, #forecast_strip_retry:active { scale: .96; }
.station_chart_loading {
    min-height: 220px; height: 100%; display: grid; place-items: center; box-sizing: border-box;
    padding: 24px; border-radius: var(--r-3); color: var(--text-3); background: var(--chip);
    font-size: 1.15rem; line-height: 1.6; text-align: center;
}
.station_chart_loading::before {
    content: ''; width: 20px; height: 20px; margin-bottom: 44px; border-radius: 50%;
    border: 2px solid var(--stroke-strong); border-top-color: var(--text); animation: weatherGridSpin .8s linear infinite;
}

/* 흐린 보라 블롭과 그라디언트 패널을 없애고 하드 엣지 계기 카드로 */
.station_chart_panel {
    position: relative; isolation: isolate; overflow: hidden; padding: 15px; border-radius: var(--r-3);
    background: var(--surface-solid); box-shadow: inset 0 0 0 1px var(--stroke);
}
.station_chart_panel::before { content: none; }
.station_chart_header { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; margin-bottom: 13px; }
.station_chart_header > div > span {
    display: block; margin-bottom: 4px; color: var(--text-3); font-family: var(--font-mono);
    font-size: 1.02rem; font-weight: 550; letter-spacing: .015em; text-transform: none;
}
.station_chart_header h3 { color: var(--text); font-size: 1.42rem; font-weight: 780; letter-spacing: -.02em; }
.station_chart_header > span {
    max-width: 55%; color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; font-weight: 400;
    line-height: 1.4; text-align: right; letter-spacing: .02em;
}
.station_chart_summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-bottom: 10px; }
.station_metric_card {
    position: relative; min-width: 0; min-height: 84px; padding: 12px; overflow: hidden; border-radius: var(--r-2);
    background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
}
/* 상단 규칙선은 '데이터'를 가리키므로 채도를 허용한다 */
.station_metric_card::after {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: var(--text-3);
}
.station_metric_card.is-wind::after { background: #62c7f5; }
.station_metric_card.is-temperature::after { background: #ff8fa3; }
.station_metric_card.is-solar::after { background: #ffd166; }
.station_metric_card.is-direction::after { background: #b8a7ff; }
.station_metric_card.is-precipitation::after { background: #38bdf8; }
.station_metric_card.is-probability::after { background: #7dd3fc; }
.station_metric_label {
    display: block; color: var(--text-3); font-family: var(--font-mono); font-size: .85rem;
    font-weight: 500; letter-spacing: .015em; text-transform: none;
}
.station_metric_reading { display: flex; align-items: baseline; gap: 5px; margin-top: 9px; min-width: 0; }
.station_metric_reading strong {
    min-width: 0; color: var(--text); font-family: var(--font-mono);
    font-size: clamp(1.9rem, 2.6vw, 2.5rem); font-weight: 600;
    letter-spacing: -.045em; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.station_metric_reading span { color: var(--text-3); font-family: var(--font-mono); font-size: .98rem; font-weight: 500; white-space: nowrap; }
.station_metric_card > small { display: block; margin-top: 8px; color: var(--text-3); font-size: .88rem; }
.station_compass_content { display: flex; align-items: center; gap: 11px; margin-top: 6px; }
.station_compass {
    position: relative; flex: none; width: 56px; height: 56px; border-radius: 50%;
    background: radial-gradient(circle at 50% 50%, var(--surface-solid) 0 32%, transparent 34%),
        repeating-conic-gradient(from -1deg, var(--stroke-strong) 0 1.5deg, transparent 1.5deg 45deg),
        var(--chip);
    box-shadow: inset 0 0 0 1px var(--stroke);
}
.station_compass > span:not(.station_compass_arrow) {
    position: absolute; color: var(--text-3); font-family: var(--font-mono);
    font-size: .82rem; font-weight: 600; line-height: 1;
}
.station_compass_n { top: 4px; left: 50%; transform: translateX(-50%); }
.station_compass_e { right: 4px; top: 50%; transform: translateY(-50%); }
.station_compass_s { bottom: 4px; left: 50%; transform: translateX(-50%); }
.station_compass_w { left: 4px; top: 50%; transform: translateY(-50%); }
.station_compass_arrow {
    position: absolute; left: 50%; top: 50%; width: 3px; height: 20px; transform-origin: 50% 100%;
    transform: translate(-50%, -100%) rotate(var(--wind-bearing, 0deg)); border-radius: 999px;
    background: #62c7f5;
}
.station_compass_arrow::before {
    content: ''; position: absolute; top: -3px; left: 50%; transform: translateX(-50%);
    border-left: 4px solid transparent; border-right: 4px solid transparent; border-bottom: 7px solid #62c7f5;
}
.station_compass_arrow::after {
    content: ''; position: absolute; left: 50%; bottom: -3px; width: 7px; height: 7px; transform: translateX(-50%);
    border-radius: 50%; background: var(--surface-solid); box-shadow: inset 0 0 0 2px #62c7f5;
}
.station_compass_copy { display: grid; min-width: 0; }
.station_compass_copy strong { color: var(--text); font-size: 1.4rem; font-weight: 780; }
.station_compass_copy span { color: var(--text-2); font-family: var(--font-mono); font-size: .92rem; white-space: nowrap; }
.station_compass_copy small { margin-top: 2px; color: var(--text-3); font-size: .9rem; }
.station_chart_panel .chart { width: 100%; height: 350px; border-radius: var(--r-2); background: transparent; }
.station-chart-native { position: relative; overflow: hidden; }
.station-chart-root { display: block; width: 100%; height: 100%; touch-action: pan-y; }
.station-chart-svg-tooltip {
    position: absolute; z-index: 2; max-width: min(260px, calc(100% - 16px)); padding: 11px;
    border-radius: var(--r-2); color: var(--text); background: var(--surface-2);
    box-shadow: inset 0 0 0 1px var(--stroke-strong), var(--e-2); pointer-events: none;
}
.station_chart_tooltip { display: grid; gap: 6px; min-width: 150px; }
.station_chart_tooltip > b { padding-bottom: 6px; color: var(--text); box-shadow: inset 0 -1px 0 var(--stroke); font-size: 1.02rem; }
.station_chart_tooltip > span { display: grid; grid-template-columns: 8px minmax(44px, 1fr) auto; align-items: center; gap: 7px; color: var(--text-2); }
.station_chart_tooltip i { width: 7px; height: 7px; border-radius: 50%; }
.station_chart_tooltip strong { color: var(--text); font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; }
.station_data_details { margin-top: 10px; box-shadow: inset 0 1px 0 var(--stroke); }
.station_data_details summary {
    min-height: 42px; display: flex; align-items: center; color: var(--text-3); cursor: pointer;
    font-size: 1.02rem; font-weight: 650; list-style-position: inside;
}
.station_data_details summary:hover { color: var(--text); }
.station_data_table { max-height: 310px; overflow: auto; border-radius: var(--r-2); box-shadow: inset 0 0 0 1px var(--stroke); }
.station_data_table table {
    width: 100%; border-collapse: separate; border-spacing: 0; color: var(--text-2);
    font-family: var(--font-mono); font-size: .95rem; font-variant-numeric: tabular-nums;
}
.station_data_table caption {
    position: static; width: auto; height: auto; overflow: visible; padding: 10px; margin: 0; border: 0;
    color: var(--text-3); background: var(--surface-2); font-family: var(--font-ui);
    font-weight: 700; line-height: normal; text-align: left; text-indent: 0;
}
.station_data_table th, .station_data_table td { padding: 8px 10px; box-shadow: inset 0 -1px 0 var(--stroke); text-align: right; white-space: nowrap; }
.station_data_table th:first-child, .station_data_table td:first-child { text-align: left; }
.station_data_table thead th { position: sticky; top: 0; z-index: 1; color: var(--text); background: var(--surface-solid); font-weight: 600; }
.station_data_table tbody th { color: var(--text-3); font-weight: 500; }
.station_data_table tr:last-child > * { box-shadow: none; }

/* 지점 상세예보 스트립 */
.forecast_strip_section {
    margin-top: 12px; padding: 12px; border-radius: var(--r-3); background: var(--surface-solid);
    box-shadow: inset 0 0 0 1px var(--stroke);
}
.forecast_strip_header { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.forecast_strip_header h3 { color: var(--text); font-size: 1.22rem; font-weight: 750; text-wrap: balance; }
.forecast_strip_header span {
    color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; font-weight: 400;
    letter-spacing: .04em; white-space: nowrap;
}
.forecast_strip_state {
    min-height: 116px; display: flex; align-items: center; justify-content: center; gap: 10px;
    color: var(--text-3); font-size: 1.12rem; line-height: 1.55; text-align: center; text-wrap: pretty;
}
.forecast_strip_state[hidden] { display: none; }
.forecast_strip_state[data-state="error"] { flex-wrap: wrap; min-height: 64px; padding: 8px; color: var(--signal-text); }
.forecast_state_spinner {
    flex: none; width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--stroke-strong);
    border-top-color: var(--text); animation: weatherGridSpin .8s linear infinite;
}
.forecast_strip_state[data-state="error"] .forecast_state_spinner { display: none; }
.forecast_strip {
    display: grid; grid-auto-flow: column; grid-auto-columns: 112px; gap: 6px; overflow-x: auto;
    padding: 1px 1px 8px; scroll-snap-type: x proximity; scroll-padding-inline: 1px;
    overscroll-behavior-inline: contain; scrollbar-width: thin; scrollbar-color: var(--stroke-strong) transparent;
}
.forecast_strip[hidden] { display: none; }
.forecast_strip:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--r-2); }
.forecast_card {
    min-height: 148px; padding: 11px; box-sizing: border-box; scroll-snap-align: start; border-radius: var(--r-2);
    background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
    color: var(--text-2); font-variant-numeric: tabular-nums;
}
.forecast_card_time { display: flex; align-items: baseline; justify-content: space-between; gap: 5px; }
.forecast_card_date { color: var(--text-3); font-family: var(--font-mono); font-size: .85rem; white-space: nowrap; }
.forecast_card_time strong { color: var(--text); font-family: var(--font-mono); font-size: 1.08rem; font-weight: 600; white-space: nowrap; }
.forecast_condition { display: flex; align-items: center; gap: 7px; min-height: 26px; margin-top: 9px; }
.forecast_condition_label { min-width: 0; color: var(--text-2); font-size: .98rem; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.forecast_condition_mark { position: relative; flex: none; width: 18px; height: 18px; box-sizing: border-box; color: var(--text-2); }
.forecast_condition_mark.is-clear { border: 2px solid currentColor; border-radius: 50%; }
.forecast_condition_mark.is-cloud::before,
.forecast_condition_mark.is-cloud::after,
.forecast_condition_mark.is-rain::before,
.forecast_condition_mark.is-snow::before,
.forecast_condition_mark.is-mixed::before {
    content: ""; position: absolute; border: 2px solid currentColor; border-radius: 999px; background: var(--surface-solid);
}
.forecast_condition_mark.is-cloud::before,
.forecast_condition_mark.is-rain::before,
.forecast_condition_mark.is-snow::before,
.forecast_condition_mark.is-mixed::before { left: 1px; right: 1px; bottom: 3px; height: 8px; }
.forecast_condition_mark.is-cloud::after { width: 8px; height: 8px; left: 5px; top: 1px; }
.forecast_condition_mark.is-rain::after,
.forecast_condition_mark.is-mixed::after {
    content: ""; position: absolute; left: 4px; bottom: -1px; width: 2px; height: 4px; border-radius: 2px;
    background: #38bdf8; box-shadow: 5px 0 #38bdf8, 10px 0 #38bdf8;
}
.forecast_condition_mark.is-snow::after {
    content: ""; position: absolute; left: 3px; bottom: -1px; width: 3px; height: 3px; border-radius: 50%;
    background: var(--text); box-shadow: 5px 0 var(--text), 10px 0 var(--text);
}
.forecast_condition_mark.is-rain { color: #38bdf8; }
.forecast_condition_mark.is-snow { color: #a5b4fc; }
.forecast_condition_mark.is-mixed { color: #818cf8; }
.forecast_temperature { display: block; margin: 7px 0; color: var(--text); font-family: var(--font-mono); font-size: 1.65rem; font-weight: 600; letter-spacing: -.03em; }
.forecast_metrics { display: grid; gap: 3px; }
.forecast_metrics > div { display: flex; justify-content: space-between; gap: 5px; font-size: .9rem; line-height: 1.4; }
.forecast_metrics dt { color: var(--text-3); white-space: nowrap; }
.forecast_metrics dd { min-width: 0; color: var(--text-2); font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ===================== 로딩 ===================== */

.loading-overlay {
    display: none; position: fixed; inset: 0; z-index: 2001;
    background: rgba(3, 5, 8, .3); pointer-events: none;
}
.loading { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 2002; pointer-events: none; }
.loading::after {
    content: ""; display: block; width: 44px; height: 44px; border-radius: 50%;
    border: 3px solid var(--stroke); border-top-color: var(--text);
    animation: weatherGridSpin .8s linear infinite;
}
@keyframes weatherGridSpin { to { transform: rotate(360deg); } }

/* ===================== 3D 뷰 ===================== */

#view3d { position: fixed; inset: 0; z-index: 1400; display: none; background: #04060A; }
#view3d.open { display: block; }
#view3d canvas { display: block; cursor: grab; touch-action: none; }
#view3d canvas:active { cursor: grabbing; }
.view3d_hud {
    position: absolute; top: 16px; left: 16px; z-index: 2; display: flex; gap: 10px; align-items: center;
    padding: 9px 13px; border-radius: var(--r-2); font-size: 1.22rem; color: #D6DBE2;
    background: rgba(10, 13, 18, .82); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
}
.view3d_hud strong {
    font-family: var(--font-mono); font-weight: 600; letter-spacing: .16em; color: #fff;
}
.view3d_modes {
    position: absolute; top: 16px; left: 50%; transform: translateX(-50%); z-index: 2;
    display: flex; gap: 0; padding: 2px; border-radius: var(--r-2);
    background: rgba(10, 13, 18, .82); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
}
.view3d_modes button {
    flex: none; height: 34px; min-width: 62px; padding: 0 15px; border-radius: var(--r-1);
    font-size: 1.22rem; font-weight: 650; white-space: nowrap; color: #98A2AF;
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease), scale var(--t-fast) var(--ease);
}
.view3d_modes button:hover { color: #E7EAEE; }
.view3d_modes button:active { scale: .96; }
.view3d_modes button.on { background: #F3F5F8; color: #05070A; }
.view3d_close {
    position: absolute; top: 16px; right: 16px; z-index: 2; width: 40px; height: 40px; border-radius: var(--r-2);
    background: rgba(10, 13, 18, .82); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12); color: #E7EAEE; font-size: 1.7rem;
    transition: background-color var(--t) var(--ease);
}
.view3d_close:hover { background: rgba(40, 46, 56, .92); }
.view3d_tip {
    position: absolute; z-index: 2; display: none; max-width: calc(100vw - 16px); box-sizing: border-box;
    pointer-events: none; padding: 8px 11px; border-radius: var(--r-2);
    background: rgba(10, 13, 18, .94); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12); color: #E7EAEE;
    font-family: var(--font-mono); font-size: 1.08rem; line-height: 1.55; white-space: pre-line; font-variant-numeric: tabular-nums;
}
.view3d_scale {
    position: absolute; right: 16px; bottom: 16px; z-index: 2; display: grid;
    grid-template-columns: auto minmax(110px, 180px) auto auto; align-items: center; gap: 8px;
    padding: 8px 11px; border-radius: var(--r-2);
    background: rgba(10, 13, 18, .84); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1); color: #C4CBD4;
    font-family: var(--font-mono); font-size: .95rem; font-variant-numeric: tabular-nums;
}
.view3d_scale i { display: block; height: 8px; border-radius: 999px; }
.view3d_scale small { color: #98A2AF; font-size: .9rem; font-weight: 500; white-space: nowrap; }
.view3d_legendtip { position: absolute; bottom: 16px; left: 16px; z-index: 2; font-size: 1.08rem; color: #78828F; }

/* ===================== 지도 유틸리티 · OL 컨트롤 ===================== */

.map_utility_stack {
    position: absolute; left: 14px; bottom: 86px; z-index: 24;
    display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
    max-width: calc(100vw - 86px); pointer-events: none;
    transition: left var(--t) var(--ease), bottom var(--t) var(--ease);
}
.map_utility_row { display: flex; align-items: flex-end; gap: 8px; }
.map_scale {
    position: static; display: flex; align-items: flex-end; gap: 8px;
    min-height: 30px; padding: 6px 10px; border-radius: var(--r-2);
    background: var(--surface-solid); box-shadow: 0 0 0 1px var(--stroke), var(--e-1);
    color: var(--text-2); pointer-events: none; box-sizing: border-box;
}
.map_scale_label {
    padding-bottom: 2px; color: var(--text-3); font-size: 1.02rem; font-weight: 550;
    letter-spacing: .015em; text-transform: none; line-height: 1;
}
.map_scale > .ol-scale-line { position: static; padding: 0; border-radius: 0; background: transparent; }
.map_scale .ol-scale-line-inner {
    margin: 0; border-color: var(--text-2); color: var(--text); font-family: var(--font-mono);
    font-size: 1rem; font-weight: 500; line-height: 1.3; white-space: nowrap; transition: width var(--t) var(--ease);
}
.app[data-data-domain="traffic"] .map_status_panel { display: none; }
.app[data-data-domain="traffic"] .map_utility_stack,
.app[data-explore-mode="hazards"] .map_utility_stack { bottom: max(12px, env(safe-area-inset-bottom, 0px)); }
.app[data-data-domain="traffic"] #cursor_readout,
.app[data-explore-mode="hazards"] #cursor_readout { display: none !important; }
@media (min-width: 901px) {
    .app.dock-open .map_utility_stack { left: 318px; }
}

.map_measure_toggle {
    pointer-events: auto; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    min-width: 70px; min-height: 38px; padding: 0 11px; border-radius: var(--r-2);
    color: var(--text-2); background: var(--surface-solid); box-shadow: 0 0 0 1px var(--stroke), var(--e-1);
    font-size: 1.08rem; font-weight: 650; cursor: pointer;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease), transform var(--t-fast) var(--ease);
}
.map_measure_toggle:hover { color: var(--text); background: var(--surface-2); }
.map_measure_toggle:active { transform: scale(.96); }
.map_measure_toggle[aria-pressed="true"] { color: var(--on-accent); background: var(--accent); box-shadow: var(--e-1); }
.map_measure_toggle svg { flex: none; }

.distance_measure_panel {
    pointer-events: auto; width: min(288px, calc(100vw - 86px)); box-sizing: border-box;
    padding: 13px; border-radius: var(--r-3);
    color: var(--text); background: var(--surface-solid); box-shadow: 0 0 0 1px var(--stroke), var(--e-2);
}
.distance_measure_panel[hidden] { display: none; }
.distance_measure_header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.distance_measure_header > div { min-width: 0; }
.distance_measure_header h2 { font-size: 1.3rem; font-weight: 750; letter-spacing: -.015em; }
#distance_measure_close {
    flex: none; width: 30px; height: 30px; margin: -4px -4px 0 0; border-radius: var(--r-2);
    color: var(--text-3); background: transparent; font-size: 1.6rem; line-height: 1;
}
#distance_measure_close:hover { color: var(--text); background: var(--chip-hover); }
.distance_measure_readout {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 2px 10px;
    margin-top: 11px; padding: 11px; border-radius: var(--r-2);
    background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
}
.distance_measure_readout > span {
    color: var(--text-3); font-family: var(--font-mono); font-size: 1.02rem; font-weight: 550;
    letter-spacing: .015em; text-transform: none;
}
.distance_measure_readout strong {
    color: var(--text); font-family: var(--font-mono); font-size: 2rem; font-weight: 600;
    letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.distance_measure_readout small { grid-column: 1 / -1; margin-top: 3px; color: var(--text-3); font-size: 1.02rem; font-weight: 550; }
.distance_measure_hint { margin-top: 9px; color: var(--text-3); font-size: .98rem; line-height: 1.5; }
.distance_measure_actions { display: grid; grid-template-columns: 1fr .82fr .9fr; gap: 5px; margin-top: 10px; }
.distance_measure_actions button {
    min-width: 0; min-height: 36px; padding: 0 7px; border-radius: var(--r-2);
    color: var(--text-2); background: var(--chip); box-shadow: inset 0 0 0 1px var(--stroke);
    font-size: 1rem; font-weight: 650;
    transition: color var(--t) var(--ease), background-color var(--t) var(--ease), transform var(--t-fast) var(--ease), opacity var(--t) var(--ease);
}
.distance_measure_actions button:hover:not(:disabled) { color: var(--text); background: var(--chip-hover); }
.distance_measure_actions button:active:not(:disabled) { transform: scale(.96); }
.distance_measure_actions button:disabled { opacity: .35; cursor: not-allowed; }
#distance_measure_finish:not(:disabled) { color: var(--on-accent); background: var(--accent); box-shadow: none; }

.measure_crosshair {
    position: absolute; left: 50%; top: 50%; z-index: 23; width: 18px; height: 18px;
    display: none; transform: translate(-50%, -50%); pointer-events: none;
    border: 1px solid rgba(5, 7, 10, .8); border-radius: 50%; box-shadow: 0 0 0 1px rgba(247, 250, 252, .7);
}
.measure_crosshair::before, .measure_crosshair::after {
    content: ''; position: absolute; left: 50%; top: 50%; background: var(--signal); box-shadow: 0 0 0 1px rgba(5, 7, 10, .55);
}
.measure_crosshair::before { width: 24px; height: 1px; transform: translate(-50%, -50%); }
.measure_crosshair::after { width: 1px; height: 24px; transform: translate(-50%, -50%); }
.map_workspace.measure-active .measure_crosshair { display: block; }
.map_workspace.measure-active #map .ol-viewport { cursor: crosshair !important; }
.map_workspace.measure-active #cursor_readout { display: none !important; }

/* top/left는 ol.css 기본값이 남으면 4방향 inset 투명 박스가 되어 지도 클릭을 전부 가로챈다 */
.ol-zoom { top: auto !important; left: auto !important; right: 14px; bottom: 98px; }
.ol-control { background: transparent; padding: 0; }
.ol-control button {
    width: 36px; height: 36px; margin: 0 0 5px; border-radius: var(--r-2); font-size: 1.6rem; font-weight: 400;
    background: var(--surface-solid); color: var(--text-2);
    box-shadow: 0 0 0 1px var(--stroke), var(--e-1);
    transition: background-color var(--t) var(--ease), color var(--t) var(--ease);
}
.ol-control button:hover { background: var(--surface-2); color: var(--text); }
.ol-control button:focus-visible { background: var(--surface-2); color: var(--text); outline: 2px solid var(--accent); outline-offset: 2px; }
.ol-rotate { display: none; }
.ol-attribution {
    bottom: 86px; right: 60px; max-width: calc(100% - 160px);
    padding: 3px 7px; border-radius: var(--r-1);
    background: rgba(5, 7, 10, .84); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12); font-size: 10px;
}
.ol-attribution ul { color: #CBD3DC; text-shadow: none; font-size: 10px; background: transparent; }
.ol-attribution a { color: #F3F5F8; }
.ol-attribution button { display: none; }
.ol-attribution.ol-collapsed ul { display: block; }
.ol-attribution.ol-uncollapsible { bottom: 86px; right: 60px; background: rgba(5, 7, 10, .84); }

/* ===================== 앱 알림 대화상자 ===================== */

.app-alert {
    max-width: min(430px, calc(100vw - 32px)); padding: 24px;
    background: var(--surface-solid); color: var(--text);
    border: 0; border-radius: var(--r-4); box-shadow: 0 0 0 1px var(--stroke-strong), var(--e-3);
}
.app-alert::backdrop { background: rgba(3, 5, 8, .68); }
.app-alert h2 { color: var(--text); font-size: 1.75rem; font-weight: 750; letter-spacing: -.02em; }
.app-alert p { margin-top: 12px; color: var(--text-2); font-size: 1.32rem; line-height: 1.6; white-space: pre-line; }
.app-alert-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 22px; }
.app-alert-actions button { min-height: 38px; padding: 0 17px; border-radius: var(--r-2); font-weight: 700; }
.app-alert-confirm { background: var(--accent); color: var(--on-accent); }
.app-alert-cancel { background: var(--chip-hover); color: var(--text); }


/* ===================== 터치 타깃 최소 크기 ===================== */
/* 계기 밀도를 위해 컨트롤을 조밀하게 잡았지만, 조작 요소의 최소 높이는
   기존 접근성 기준(40px / 목록·재생 항목 44px) 아래로 내려가지 않게 고정한다.
   반응형·coarse 포인터 규칙보다 앞에 두어 그쪽 상향값이 그대로 이긴다. */
.seg button, .chiprow .chip, .lswitch, .forecast_run_button, .latest_run_button,
.station_suggestion_option, .station_timeline_button, .legend_toggle, .map_measure_toggle,
.metric_disclosure > summary, .coordinate_panel .coordinate_input,
.forecast_date_control .forecast_date_input, .distance_measure_actions button,
#retry_data, #air_quality_retry, #cctv_retry, #severe_weather_retry,
.station_chart_retry, #forecast_strip_retry { min-height: 40px; }

.coordinate_panel_close, .coordinate_popup_close, .warning_panel_close,
.air_popup_close, .cctv_popup_close, .hazard_popup_close,
.station_modal_header .station_modal_close, .view3d_modes button, .ol-control button {
    width: 40px; height: 40px;
}
.view3d_close { width: 44px; height: 44px; }

.base_run_actions button, .advanced_disclosure > summary { min-height: 42px; }
.metric_context_segment button { height: 46px; }
#cctv_toggle, .infrastructure_toggle, .cctv_cluster_list button,
.cctv_play, .station_data_details summary { min-height: 44px; }

.icon-btn, .station_query, .dock_collapse, .forecast_run_list button { min-height: 36px; }
.icon-btn { height: 36px; min-width: 36px; }
.station_query { height: 36px; }
.dock_collapse, .forecast_run_list button { width: 36px; height: 36px; }
#distance_measure_close { width: 34px; height: 34px; }

/* ===================== 반응형 ===================== */

@media (min-width: 901px) and (max-width: 1700px) {
    /* 검색창과 중앙 요소 선택기가 좁아지면 상태 스트립에서 해설을 접는다 */
    .info_hint { display: none; }
}

@media (max-width: 1150px) {
    .brand .brand_txt span { display: none; }
    .info_hint { display: none; }
    .search-container { width: min(230px, 25vw); }
    .data_domain_nav button { min-width: 58px; padding-inline: 11px; }
    .explore_modes button { min-width: 46px; padding-inline: 9px; }
}

@media (max-width: 900px) {
    .dock_scrim:not([hidden]) {
        position: fixed; inset: 0; z-index: 31; display: block; background: rgba(3, 5, 8, .62);
    }
    .legend { width: min(224px, calc(100vw - 16px)); padding: 8px; }
    .legend_title { display: none; }
    .legend_toggle { display: flex; }
    .legend:not(.legend-collapsed) .legend_toggle { margin-bottom: 8px; }
    .legend.legend-collapsed { width: 118px; max-height: none; overflow: visible; }
    .weather_legend:not(.legend-ready) { width: 118px; max-height: none; overflow: visible; }
    .weather_legend:not(.legend-ready) #legend_scale,
    .weather_legend:not(.legend-ready) .grid_stats { display: none; }
    .air_legend, .hazard_legend { width: min(224px, calc(100vw - 16px)); }
    .air_legend.legend-collapsed, .hazard_legend.legend-collapsed { width: 118px; }
    .map_status_panel { display: none; }
    .icon-btn { padding: 0 9px; }
    .icon-btn .lbl { display: none; }

    .data_domain_nav, .topbar > .explore_modes { display: none; }
    .topbar { height: 52px; }
    .search-container { width: 220px; }

    .mobile_primary_controls {
        position: absolute; z-index: 28; top: 52px; left: 0; right: 52px;
        display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
        height: 44px; padding: 0; background: var(--surface-solid);
        box-shadow: inset 0 -1px 0 var(--stroke);
    }
    .mobile_primary_controls.is-hidden { display: none; }
    .mobile_primary_controls button {
        position: relative; min-width: 0; min-height: 44px; padding: 0 8px;
        display: flex; align-items: center; justify-content: center; gap: 7px;
        color: var(--text-3); font-size: 1.18rem; font-weight: 650;
        transition: color var(--t) var(--ease), background-color var(--t) var(--ease), transform var(--t-fast) var(--ease);
    }
    .mobile_primary_controls button + button { box-shadow: inset 1px 0 0 var(--stroke); }
    .mobile_primary_controls button:hover { color: var(--text); background: var(--chip); }
    .mobile_primary_controls button.on { color: var(--text); background: var(--lit-bg); }
    .mobile_primary_controls button.on::after {
        content: ''; position: absolute; left: 22%; right: 22%; bottom: 0; height: 2px; background: var(--lit);
    }
    .mobile_primary_controls button:active { transform: scale(.96); }

    /* 설정 독은 바텀시트로 — 드래그 핸들과 스프링 진입 */
    .dock {
        position: fixed; top: auto; right: 0; bottom: 0; left: 0; z-index: 32;
        width: 100%; max-height: min(72dvh, 640px);
        border-radius: var(--r-4) var(--r-4) 0 0;
        box-shadow: inset 0 1px 0 var(--stroke), 0 -24px 60px -20px rgba(0, 0, 0, .7);
        transform: translateY(100%); opacity: 0; pointer-events: none;
        transition: transform var(--t-slow) var(--ease-spring), opacity var(--t) var(--ease);
    }
    .dock::before {
        content: ''; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
        width: 38px; height: 4px; border-radius: 999px; background: var(--stroke-strong); pointer-events: none;
    }
    .dock.collapsed { transform: translateY(100%); }
    .dock.dock-ready:not(.collapsed) { transform: translateY(0); opacity: 1; pointer-events: auto; }
    .dock_scroll { padding: 22px 18px calc(20px + env(safe-area-inset-bottom, 0px)); }
    .dock_toggle {
        position: fixed; top: 52px; left: auto; right: 0; z-index: 28; order: 0; margin: 0;
        display: flex; width: 52px; min-width: 52px; height: 44px; padding: 0; border-radius: 0;
        border: 0; background: var(--surface-solid); color: var(--text-2);
        box-shadow: inset 0 -1px 0 var(--stroke), inset 1px 0 0 var(--stroke);
    }
    .dock_toggle[aria-expanded="true"] { background: var(--surface-solid); border: 0; }
    .dock_toggle_label { display: none; }
    .legend_stack { top: 108px; right: 8px; }
    .legend, .air_legend, .hazard_legend { width: min(204px, calc(100vw - 16px)); }
    .warning_banner { top: 108px; left: 8px; right: 220px; width: auto; max-width: none; transform: none; }
    .warning_panel { top: 154px; left: 8px; right: 8px; width: auto; transform: none; }
}

@media (max-width: 640px) {
    .topbar {
        top: 0; left: 0; right: 0;
        height: calc(48px + env(safe-area-inset-top, 0px));
        padding: env(safe-area-inset-top, 0px) 8px 0 4px;
        gap: 0; align-items: center;
    }
    .brand { align-self: stretch; padding: 0 10px 0 4px; gap: 7px; }
    .brand svg { width: 22px; height: 22px; }
    .brand .brand_txt strong { font-size: 1.35rem; letter-spacing: .16em; }
    .search-container { flex: 1; min-width: 0; width: auto; padding-left: 6px; }
    .station_query { height: 32px; padding-right: 68px; font-size: 1.35rem; }
    .station_search_button, .current_location_button { width: 30px; height: 30px; }
    .coordinate_search_button { display: none; }
    .top-actions { margin-left: 4px; }
    .icon-btn { width: 34px; height: 34px; padding: 0; }
    .top-actions #btn_3d { display: none; }
    .dock_toggle { top: calc(48px + env(safe-area-inset-top, 0px)); right: 0; width: 48px; min-width: 48px; height: 44px; }

    .coordinate_panel {
        position: fixed; top: calc(52px + env(safe-area-inset-top, 0px)); left: 8px; right: 8px;
        width: auto; min-width: 0; max-width: none;
        max-height: calc(100dvh - 76px); overflow-y: auto; border-radius: var(--r-3);
    }
    .suggestions { max-width: calc(100vw - 20px); }
    .map_status_panel { display: none; }
    #cursor_readout { display: none !important; }
    .view3d_dock_open { display: flex; }

    .mobile_primary_controls {
        top: calc(48px + env(safe-area-inset-top, 0px));
        left: 0; right: 48px; height: 44px; padding: 0; border-radius: 0;
    }
    .mobile_primary_controls button { height: 44px; border-radius: 0; gap: 6px; font-size: 1.14rem; }
    .mobile_primary_controls .nav_icon { width: 16px; height: 16px; }

    .dock { max-height: min(76dvh, 640px); }
    .legend_stack {
        top: calc(100px + env(safe-area-inset-top, 0px));
        right: calc(8px + env(safe-area-inset-right, 0px));
        max-height: calc(48dvh - env(safe-area-inset-top, 0px)); gap: 7px; overflow-y: auto;
    }
    .legend.legend-collapsed, .weather_legend:not(.legend-ready) { width: 94px; }
    .air_legend.legend-collapsed, .hazard_legend.legend-collapsed { width: 98px; }
    .grid_stats h3 { font-size: .82rem; }
    .grid_stats dl div { font-size: .98rem; line-height: 1.6; }
    #legend_scale .lg_row { grid-template-columns: 9px 4.4em minmax(28px, 1fr) 2.1em; font-size: .92rem; gap: 0 7px; }
    #legend_scale .lg_row > i { width: 9px; }

    .warning_banner {
        top: calc(100px + env(safe-area-inset-top, 0px)); left: 8px; right: 108px;
        grid-template-columns: auto auto minmax(0, 1fr) auto;
    }
    .warning_banner:not([hidden]) ~ .legend_stack { top: calc(148px + env(safe-area-inset-top, 0px)); }
    .warning_panel {
        top: calc(148px + env(safe-area-inset-top, 0px)); left: 8px; right: 8px;
        max-height: calc(100dvh - 164px - env(safe-area-inset-top, 0px));
    }
    .warning_panel:not([hidden]) ~ .legend_stack { display: none; }

    .timeline {
        left: 0; right: 0; bottom: 0; width: auto; min-height: 72px;
        padding: 8px max(8px, env(safe-area-inset-right, 0px)) calc(8px + env(safe-area-inset-bottom, 0px)) max(8px, env(safe-area-inset-left, 0px));
        border-radius: 0; transform: none; gap: 8px;
    }
    .forecast_run_list [data-forecast="ini"], .forecast_run_list [data-forecast="fnl"] { display: none; }
    .timeline_caption { display: none; }
    .app[data-explore-mode="air"] .timeline_caption,
    .app[data-explore-mode="road"] .timeline_caption {
        position: absolute; top: -28px; left: 2px; display: grid; margin: 0; padding: 5px 9px;
        border-radius: var(--r-2); color: var(--text-2); background: var(--surface-solid);
        box-shadow: 0 0 0 1px var(--stroke), var(--e-1); text-align: left;
    }
    .app[data-explore-mode="air"] .timeline_caption span,
    .app[data-explore-mode="road"] .timeline_caption span { display: none; }
    .app[data-data-domain="air"] .timeline_caption span { display: inline; }
    .forecast_timeline { padding-top: 24px; }
    .forecast_timeline li span { bottom: calc(100% + 5px); font-size: 1.02rem; padding: 3px 8px; }
    .forecast_timeline_ticks span:nth-child(2), .forecast_timeline_ticks span:nth-child(4) { display: none; }
    .forecast_timeline_ticks span { font-size: .86rem; letter-spacing: -.02em; }
    .forecast_run_buttons { grid-template-columns: repeat(4, 1fr); }
    .seg button, .chiprow .chip, .forecast_run_button, .latest_run_button, .lswitch, .forecast_run_list button,
    .base_run_actions button, .basemap_picker ul > li > button { min-height: 44px; }
    .forecast_scrubber { height: 44px; top: 14px; }
    .forecast_scrubber::-webkit-slider-thumb { width: 22px; height: 22px; margin-top: -8px; }
    .forecast_scrubber::-moz-range-thumb { width: 20px; height: 20px; }
    .map_notice { bottom: calc(86px + env(safe-area-inset-bottom, 0px)); }

    /* 시계열 모달 — 전면화 */
    .popup { width: calc(100vw - 12px); max-height: calc(100dvh - 12px); border-radius: var(--r-3); }
    .station_modal_header { border-radius: var(--r-3) var(--r-3) 0 0; padding: 15px 16px; }
    .station_modal_body { overflow: auto; padding: 12px; }
    .station_chart_panel { padding: 11px; }
    .station_chart_summary { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; }
    .station_chart_summary > :last-child:nth-child(odd) { grid-column: 1 / -1; }
    .station_metric_card { min-height: 78px; padding: 11px; }
    .station_chart_header { display: grid; align-items: start; gap: 6px; }
    .station_chart_header > span { max-width: none; font-size: .82rem; text-align: left; }
    .station_chart_panel .chart { height: clamp(280px, 42dvh, 350px); }
    .forecast_strip_section { padding: 10px; }
    .forecast_strip_header {
        display: grid; align-items: start; justify-content: stretch; gap: 4px;
    }
    .forecast_strip_header h3 { word-break: keep-all; }
    .forecast_strip_header span { line-height: 1.4; text-align: left; white-space: normal; }
    .forecast_strip { grid-auto-columns: 106px; }
    .forecast_card { min-height: 152px; }
    .air_quality_control button, #air_quality_retry, #cctv_retry, #forecast_strip_retry, .station_chart_retry,
    .air_popup_close, .cctv_popup_close, .cctv_play, .hazard_popup_close, .warning_panel_close,
    #severe_weather_retry { min-height: 44px; }

    .ol-zoom { right: 8px; bottom: calc(84px + env(safe-area-inset-bottom, 0px)); }
    .ol-attribution, .ol-attribution.ol-uncollapsible { bottom: calc(84px + env(safe-area-inset-bottom, 0px)); right: 52px; }
    .view3d_modes { top: 58px; left: 12px; transform: none; }
    .view3d_scale { right: 10px; bottom: 44px; grid-template-columns: auto minmax(76px, 130px) auto auto; }
    .view3d_legendtip { left: 10px; right: 10px; bottom: 12px; overflow: hidden; text-align: center; text-overflow: ellipsis; white-space: nowrap; }

    #data_error {
        position: fixed; top: calc(100px + env(safe-area-inset-top, 0px)); left: 8px; right: 8px;
        transform: none; width: auto; max-width: none; justify-content: space-between;
    }
    #data_error:not([hidden]) ~ .warning_banner { top: calc(166px + env(safe-area-inset-top, 0px)); }
    #data_error:not([hidden]) ~ .warning_panel { top: calc(214px + env(safe-area-inset-top, 0px)); }
    #data_error:not([hidden]) ~ .warning_banner:not([hidden]) ~ .legend_stack { top: calc(214px + env(safe-area-inset-top, 0px)); }
    #data_error:not([hidden]) ~ .legend_stack { top: calc(166px + env(safe-area-inset-top, 0px)); }

    .map_utility_stack {
        left: max(8px, env(safe-area-inset-left, 0px));
        bottom: calc(94px + env(safe-area-inset-bottom, 0px));
        max-width: calc(100vw - 72px);
    }
    .app[data-data-domain="traffic"] .map_utility_stack,
    .app[data-explore-mode="hazards"] .map_utility_stack { bottom: max(8px, env(safe-area-inset-bottom, 0px)); }
    .distance_measure_panel { width: min(280px, calc(100vw - 72px)); }
    .distance_measure_actions button { min-height: 44px; }
}

@media (max-width: 640px) and (orientation: portrait) {
    /* 대기질 타임라인 안내가 거리·축척 조작부를 가리지 않도록 여유를 확보한다. */
    .app[data-data-domain="air"] .map_utility_stack {
        bottom: calc(132px + env(safe-area-inset-bottom, 0px));
    }
}

@media (max-width: 360px) {
    .topbar { display: flex; grid-template: none; }
    .brand, .top-actions, .search-container { grid-area: auto; }
    .brand .brand_txt { display: none; }
    .coordinate_panel { top: calc(52px + env(safe-area-inset-top, 0px)); }
    .mobile_primary_controls, .dock_toggle { top: calc(48px + env(safe-area-inset-top, 0px)); }
    .dock { max-height: 80dvh; }
    .legend_stack { top: calc(100px + env(safe-area-inset-top, 0px)); }
}

@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
    .topbar { top: 0; left: 0; right: 0; height: 44px; padding-top: 0; }
    .mobile_primary_controls { top: 44px; left: 0; right: 48px; height: 40px; }
    .mobile_primary_controls button { min-height: 40px; height: 40px; }
    .dock {
        top: 44px; right: auto; bottom: 56px; left: 0;
        width: min(340px, calc(100vw - 24px)); max-height: none;
        border-radius: 0; transform: translateX(-100%);
        box-shadow: inset -1px 0 0 var(--stroke), 14px 0 40px -20px rgba(0, 0, 0, .7);
    }
    .dock::before { content: none; }
    .dock_scroll { padding-top: 14px; }
    .dock.collapsed { transform: translateX(-100%); }
    .dock.dock-ready:not(.collapsed) { transform: translateX(0); }
    .dock_toggle { top: 44px; right: 0; width: 48px; min-width: 48px; height: 40px; }
    .legend_stack { top: 92px; }
    .timeline { min-height: 56px; padding-block: 5px; }
    .forecast_timeline { padding-top: 20px; }
    .map_utility_stack { bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
    .app[data-data-domain="traffic"] .map_utility_stack,
    .app[data-explore-mode="hazards"] .map_utility_stack { bottom: max(8px, env(safe-area-inset-bottom, 0px)); }
    .distance_measure_panel { padding: 9px; }
    .distance_measure_hint { display: none; }
    .distance_measure_readout { margin-top: 7px; padding-block: 8px; }
    .distance_measure_actions { margin-top: 7px; }
}

@media (pointer: coarse) {
    .seg button, .chiprow .chip, .forecast_run_button, .latest_run_button, .lswitch, .base_run_actions button,
    .forecast_run_list button, .legend_toggle, .ol-control button, .station_search_button, .coordinate_search_button,
    .current_location_button, .coordinate_panel_close, .coordinate_popup_close, .icon-btn, .dock_collapse,
    .coordinate_lookup, .station_timeline_button, .air_popup_close, .cctv_popup_close, .cctv_play, #retry_data,
    #air_quality_retry, #cctv_retry, #forecast_strip_retry, .hazard_popup_close, .warning_panel_close,
    #severe_weather_retry, .map_measure_toggle, #distance_measure_close,
    .station_modal_header .station_modal_close,
    .distance_measure_actions button { min-width: 44px; min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        scroll-behavior: auto !important;
        transition-duration: .001ms !important;
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
    }
}
