@import url("taste-app.css");
@import url("https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500&display=swap");
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css");

/* 광안대교 계측 AX — achromatic-ledger (seed 380271458). 바탕은 바다·장부의 청회색 한 단계, 색은 상태에만. */
:root {
  --ground: #f2f4f7; --surface: #ffffff; --raised: #eceef1; --active: #e6e9ed;
  --border: #e3e6ea; --rule: #eef0f3; --control: #cfd4da;
  --text: #0e1116; --muted: #5a616b; --faint: #5f6670;
  /* 부산시설공단(BISCO) 로고 색(logo.svg): 남색 #00336e · 파랑 #004e9a · 녹색 #58b431(스우시 그라데이션 #58b431→#0068b7) */
  --bisco-navy: #00336e; --bisco-blue: #004e9a; --bisco-green: #58b431; --bisco-sky: #0a71a6;
  --accent: #00336e; --primary: #00336e; --primary-ink: #ffffff;
  --data: #004e9a; --chart-1: #00336e; --chart-2: #8a95a0; --chart-3: #0a71a6; --chart-muted: #c9ced4;
  /* 재난 5단계 색은 공단 2D 상황판 · 개선안 그림의 관례(정상 녹 · 관심 연두 · 주의 노랑 · 경계 주황 · 심각 빨강) */
  --lv0: #2f8f2a; --lv1: #8dc63f; --lv2: #e6b400; --lv3: #ee7a14; --lv4: #d1232a; --blocked: #6b6b6b; --missing: #9a9a9a;
  --font: "Geist", "Pretendard Variable", Pretendard, -apple-system, system-ui, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --fs-title: 24px; --fs-section: 16px; --fs-kpi: 30px; --fs-body: 14px; --fs-small: 13px;
  --radius-card: 8px; --radius-control: 6px; --row-height: 44px; --sidebar-width: 256px;
  --gap: 12px; --pad: 24px; --card-pad: 20px; --control-height: 36px; --nav-row: 32px;
}
html { height: 100%; }
body { height: 100%; }
.mono { font-family: var(--mono); font-size: 13px; }
.num { font-variant-numeric: tabular-nums; }

/* ---------- 셸 ---------- */
.app { height: 100svh; min-height: 0; }
.sidebar { border-right: 1px solid var(--border); padding: 20px 12px 16px; }
.brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 18px; }
.brand .mark { width: 30px; height: 30px; flex: none; }
.brand .name { font-weight: 600; line-height: 1.2; }
.brand .scope { color: var(--muted); font-size: var(--fs-small); margin-top: 2px; }
.switcher { display: flex; align-items: center; justify-content: space-between; height: 36px; padding: 0 10px; margin: 0 0 12px; border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface); font-weight: 500; }
.switcher .chev { width: 12px; height: 12px; background: currentColor; -webkit-mask: var(--chevron) center / 12px no-repeat; mask: var(--chevron) center / 12px no-repeat; transform: rotate(90deg); color: var(--muted); }
.nav-item .count { margin-left: auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 6px; background: var(--lv4); color: #fff; font-size: 11px; font-weight: 500; display: inline-flex; align-items: center; justify-content: center; }
.nav-item .count.quiet { background: var(--raised); color: var(--text); }
.sidebar .bottom .row { min-height: 40px; padding: 8px; gap: 10px; }
.avatar { width: 26px; height: 26px; border-radius: 50%; background: #dfe9f5; color: #00336e; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; flex: none; }
.canvas { overflow: auto; height: 100svh; }

/* 제목행 */
.title-row { margin-bottom: 16px; align-items: flex-start; }
.title-row .finding { margin-top: 8px; color: var(--text); max-width: 72ch; }
.title-row .right { display: flex; align-items: center; gap: 10px; flex: none; }
.scenario { display: flex; align-items: center; gap: 8px; }
.scenario .lbl { color: var(--faint); font-size: var(--fs-small); }
.stamp { white-space: nowrap; }

/* 패널 */
.panel { display: flex; flex-direction: column; min-width: 0; }
.panel > header { margin-bottom: 12px; }
.panel .foot { margin-top: auto; padding-top: 12px; display: flex; justify-content: space-between; align-items: center; color: var(--muted); font-size: var(--fs-small); }
.panel .body { min-height: 0; }
.col-8 { grid-column: span 8; } .col-7 { grid-column: span 7; } .col-6 { grid-column: span 6; } .col-5 { grid-column: span 5; } .col-4 { grid-column: span 4; } .col-3 { grid-column: span 3; } .col-9 { grid-column: span 9; } .col-12 { grid-column: span 12; }
.stack { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
.stack > .panel.fill { flex: 1; }

/* ---------- 상태 ---------- */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--lv0); flex: none; }
.dot.lv0 { background: var(--lv0); } .dot.lv1 { background: var(--lv1); } .dot.lv2 { background: var(--lv2); } .dot.lv3 { background: var(--lv3); } .dot.lv4 { background: var(--lv4); }
.dot.blocked { background: var(--blocked); } .dot.missing { background: var(--missing); }
.pill.lv0 { background: #e3f3e5; color: #124a1a; } .pill.lv1 { background: #eef7d9; color: #3d5a00; } .pill.lv2 { background: #fff4cc; color: #5c4300; }
.pill.lv3 { background: #ffe6d3; color: #6b2d00; } .pill.lv4 { background: #ffe1e1; color: #6a1014; }
.pill.blocked { background: #ececec; color: #3d3d3d; } .pill.missing { background: #f1f1f1; color: #4a4a4a; }

/* 재난 단계 */
.level-word { font-size: var(--fs-kpi); font-weight: 600; letter-spacing: 0; line-height: 1.1; }
.level-word small { font-size: 14px; font-weight: 400; color: var(--muted); margin-left: 8px; }
.level-bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 3px; margin: 12px 0 4px; }
.level-bar span { height: 10px; border-radius: 2px; background: var(--raised); }
.level-bar span.on.lv0 { background: var(--lv0); } .level-bar span.on.lv1 { background: var(--lv1); } .level-bar span.on.lv2 { background: var(--lv2); } .level-bar span.on.lv3 { background: var(--lv3); } .level-bar span.on.lv4 { background: var(--lv4); }
.level-names { display: grid; grid-template-columns: repeat(5, 1fr); font-size: 11px; color: var(--faint); margin-bottom: 16px; }
.level-names span.cur { color: var(--text); font-weight: 600; }
.crit { display: grid; grid-template-columns: 1fr auto; gap: 2px 12px; align-items: baseline; padding: 9px 0; }
.crit + .crit { border-top: 1px solid var(--rule); }
.crit .lbl { color: var(--muted); }
.crit .val { font-size: 18px; font-weight: 500; font-variant-numeric: tabular-nums; text-align: right; }
.crit .val small { font-size: 12px; color: var(--muted); font-weight: 400; margin-left: 2px; }
.crit .strip { grid-column: 1 / -1; }
.crit .next { grid-column: 1 / -1; font-size: var(--fs-small); color: var(--muted); }
.strip-svg { display: block; width: 100%; height: 14px; }

/* 조치 카드 */
.actions { display: grid; gap: 8px; }
.action { display: grid; grid-template-columns: 24px 1fr auto; gap: 12px; align-items: start; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius-control); }
.action .tick { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--control); display: inline-flex; align-items: center; justify-content: center; margin-top: 1px; }
.action .tick.done { background: var(--text); border-color: var(--text); color: #fff; }
.action .t { font-weight: 500; }
.action .d { color: var(--muted); font-size: var(--fs-small); margin-top: 2px; }
.action .when { color: var(--faint); font-size: var(--fs-small); white-space: nowrap; }
.vms { font-family: var(--mono); font-size: 13px; padding: 12px; background: var(--raised); border-radius: var(--radius-control); color: var(--text); }
.kma { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; }
.kma div { display: flex; justify-content: space-between; gap: 8px; }
.kma .k { color: var(--muted); }
.kma .warn { grid-column: 1 / -1; display: flex; gap: 6px; flex-wrap: wrap; }

/* 3D 트윈 */
.twin { position: relative; width: 100%; height: 100%; min-height: 360px; border-radius: 6px; overflow: hidden; background: #eef2f6; cursor: grab; }
.twin-canvas { display: block; }
.twin-overlay { position: absolute; inset: 0; pointer-events: none; }
.twin-zone { position: absolute; left: 0; top: 0; transform: translate(-50%, -100%); padding: 2px 6px; font-size: 11px; color: #3b4651; background: rgba(255,255,255,0.72); border-radius: 4px; white-space: nowrap; margin-left: -4px; }
.twin-tip { position: absolute; padding: 4px 8px; background: #15181c; color: #fff; font-size: 12px; border-radius: 4px; white-space: nowrap; transform: translateY(-100%); }
.twin-legend { position: absolute; left: 12px; bottom: 12px; display: flex; gap: 12px; padding: 8px 12px; background: rgba(255,255,255,0.86); border-radius: 6px; font-size: 11px; color: var(--muted); pointer-events: none; }
.twin-legend span { display: inline-flex; align-items: center; gap: 5px; }
.twin-sel { position: absolute; right: 12px; bottom: 12px; max-width: 46%; padding: 8px 12px; background: rgba(255,255,255,0.92); border: 1px solid var(--border); border-radius: 6px; pointer-events: auto; }
.twin-sel .n { font-weight: 500; display: flex; align-items: center; gap: 8px; }
.twin-sel .v { margin-top: 2px; color: var(--muted); font-size: var(--fs-small); display: flex; gap: 10px; align-items: center; }
.twin-sel .v b { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }
.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip { height: 28px; padding: 0 12px; border-radius: 6px; border: 1px solid var(--control); background: var(--surface); color: var(--muted); font-size: var(--fs-small); cursor: pointer; transition: background-color 140ms cubic-bezier(0.22, 1, 0.36, 1), color 140ms cubic-bezier(0.22, 1, 0.36, 1); }
.chip:hover { background: var(--raised); color: var(--text); }
.chip[aria-pressed="true"] { background: var(--active); color: var(--text); border-color: var(--text); }
.panel.twin-panel { padding: 12px 12px 12px; height: 484px; }
.row1 > .panel:not(.twin-panel) { height: 484px; }
.row2 { align-items: stretch; }
.row2 .loggers { grid-template-columns: repeat(2, 1fr); }
.recv { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 8px; }
.recv div { display: flex; flex-direction: column; }
.recv .k { color: var(--muted); font-size: var(--fs-small); }
.recv .v { font-weight: 500; font-variant-numeric: tabular-nums; }
.panel.twin-panel > header { padding: 4px 8px 0; margin-bottom: 10px; }
.panel.twin-panel .body { flex: 1; min-height: 0; }

/* 알람 목록 */
.alarm { display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: center; min-height: 44px; padding: 8px 0; }
.alarm + .alarm { border-top: 1px solid var(--rule); }
.alarm > div { min-width: 0; }   /* 이름 말줄임이 먹으려면 격자 칸이 줄어들 수 있어야 한다 */
.alarm .name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alarm .sub { color: var(--muted); font-size: var(--fs-small); margin-top: 1px; }
.alarm .val { text-align: right; font-variant-numeric: tabular-nums; }
.alarm .val .t { color: var(--faint); font-size: var(--fs-small); display: block; }
.alarm[aria-selected="true"] { background: var(--active); margin: 0 -12px; padding: 8px 12px; border-radius: 6px; }
.alarm[aria-selected="true"] + .alarm { border-top-color: transparent; }

.panel.sticky { position: sticky; top: 0; }
/* 수신 바 */
.stackbar { display: flex; height: 12px; border-radius: 3px; overflow: hidden; gap: 2px; margin: 8px 0 8px; }
.stackbar span { display: block; }
.loggers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.logger { display: flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px; border: 1px solid var(--border); border-radius: 5px; font-size: var(--fs-small); }
.logger b { font-weight: 500; font-family: var(--mono); font-size: 12px; }

/* 센서 목록 (상세 화면) */
.sensor-list { padding: 12px; }
.sensor-list .search { margin-bottom: 8px; }
.sensor-list .input { height: 32px; width: 100%; }
.sgroup { margin-top: 10px; }
.sgroup > button { width: 100%; display: flex; justify-content: space-between; align-items: center; height: 28px; padding: 0 6px; border: 0; background: none; color: var(--muted); font-size: var(--fs-small); cursor: pointer; }
.sgroup > button b { color: var(--text); font-weight: 500; font-size: 13px; }
.srow { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 6px; border-radius: 6px; color: var(--text); font-size: 13px; cursor: pointer; }
.srow:hover { background: var(--raised); }
.srow[aria-current="true"] { background: var(--active); }
.srow .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.srow .vv { margin-left: auto; color: var(--muted); font-variant-numeric: tabular-nums; font-size: 12px; white-space: nowrap; }
.value-big { font-size: var(--fs-kpi); font-weight: 500; letter-spacing: 0; line-height: 1.1; font-variant-numeric: tabular-nums; }
.value-big small { font-size: 14px; color: var(--muted); font-weight: 400; margin-left: 4px; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; }
.kv .k { color: var(--muted); white-space: nowrap; }
.gate { display: grid; gap: 6px; }
.gate div { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; min-height: 28px; }
.gate .k { color: var(--muted); white-space: nowrap; flex: none; padding-top: 3px; }
.gate .r { text-align: right; }
.gate .r { font-weight: 500; }
.gate .r.bad { color: var(--negative); }
.elev { width: 100%; height: auto; display: block; }
.hist { display: grid; grid-template-columns: 96px 1fr auto; gap: 8px 12px; align-items: baseline; }
.hist .d { color: var(--muted); font-variant-numeric: tabular-nums; }
.hist .w { color: var(--faint); font-size: var(--fs-small); }
.cite { padding: 12px; background: var(--raised); border-radius: var(--radius-control); font-size: 13px; line-height: 1.55; }
.cite .src { display: block; margin-top: 6px; color: var(--muted); font-size: var(--fs-small); }
.cite + .cite { margin-top: 8px; }

/* 어시스턴트 */
.chat { display: flex; flex-direction: column; min-height: 0; }
.chat .log { flex: 1; overflow: visible; display: flex; flex-direction: column; gap: 18px; padding: 4px 4px 12px; }
.msg { display: grid; grid-template-columns: 28px 1fr; gap: 10px; }
.msg.user { grid-template-columns: 1fr; justify-items: end; }
.msg.user .bubble { background: var(--raised); padding: 8px 12px; border-radius: 10px 10px 2px 10px; max-width: 70%; }
.msg .who { width: 28px; height: 28px; border-radius: 50%; background: var(--text); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; }
.msg .body { max-width: 72ch; line-height: 1.6; }
.msg .body p + p { margin-top: 8px; }
.msg .body .answer-num { font-weight: 600; font-variant-numeric: tabular-nums; }
.msg .evidence { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.msg .evidence button { height: 24px; padding: 0 8px; border-radius: 6px; border: 1px solid var(--control); background: var(--surface); font-size: var(--fs-small); color: var(--muted); cursor: pointer; }
.msg .evidence button[aria-pressed="true"] { border-color: var(--text); color: var(--text); }
.msg .caveat { margin-top: 8px; color: var(--faint); font-size: var(--fs-small); }
.composer { border-top: 1px solid var(--border); padding-top: 12px; }
.composer .suggest { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.composer form { display: flex; gap: 8px; }
.composer .input { flex: 1; }
.ev-table td, .ev-table th { padding: 6px 8px; font-size: 13px; }
.ev-table td:not(:first-child), .ev-table th:not(:first-child) { white-space: nowrap; }
.graph-path { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.graph-path .node { padding: 4px 8px; border: 1px solid var(--control); border-radius: 5px; font-size: 12px; background: var(--surface); }
.graph-path .node.hi { border-color: var(--text); font-weight: 500; }
.graph-path .edge { color: var(--faint); font-size: 11px; }

/* 품질 */
.matrix { display: grid; grid-template-columns: minmax(0, 1fr) repeat(5, 56px); gap: 0; font-size: 13px; }
.matrix .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.matrix .h { color: var(--muted); font-size: var(--fs-small); padding: 0 0 8px; text-align: right; }
.matrix .h:first-child { text-align: left; }
.matrix .c { height: 28px; min-width: 0; display: flex; align-items: center; justify-content: flex-end; border-top: 1px solid var(--rule); font-variant-numeric: tabular-nums; }
.matrix .c:nth-child(6n+1) { justify-content: flex-start; }
.matrix .c.bad { color: var(--negative); font-weight: 500; }
.scale { display: grid; grid-template-columns: repeat(12, 1fr); gap: 2px; margin: 8px 0 4px; }
.scale span { height: 14px; border-radius: 2px; opacity: 0.45; }
.scale span.cur { opacity: 1; outline: 2px solid var(--text); outline-offset: 1px; }
.scale-names { display: grid; grid-template-columns: repeat(12, 1fr); font-size: 11px; color: var(--faint); text-align: center; }
.doc { padding: 16px; background: var(--raised); border-radius: var(--radius-control); font-size: 13px; line-height: 1.6; }
.doc h4 { font-size: 14px; margin: 0 0 6px; }
.doc p + p { margin-top: 6px; }
.doc .sig { color: var(--muted); font-size: var(--fs-small); margin-top: 10px; }
.pga-bars { display: grid; gap: 10px; }
.pga { display: grid; grid-template-columns: 120px 1fr 72px; gap: 10px; align-items: center; }
.pga .track { position: relative; height: 16px; background: var(--raised); border-radius: 3px; }
.pga .fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--data); border-radius: 3px; }
.pga .tick { position: absolute; top: -4px; bottom: -4px; width: 1px; background: var(--control); }
.pga .tick i { position: absolute; top: -14px; left: -10px; font-style: normal; font-size: 10px; color: var(--faint); width: 20px; text-align: center; }
.pga .v { text-align: right; font-variant-numeric: tabular-nums; font-weight: 500; }
.pga .v small { color: var(--muted); font-weight: 400; }

/* 교축 위치 스트립 — 이 제품만의 요소 */
.axis-strip { display: block; width: 100%; height: 26px; }

/* 벽면 모드 */
body.wall .sidebar { display: none; }
body.wall .app { grid-template-columns: minmax(0, 1fr); }
body.wall .canvas { padding: 20px 28px; }

@media (max-width: 1180px) {
  .col-8, .col-7, .col-6, .col-5, .col-4, .col-3, .col-9 { grid-column: span 12; }
  .chat { height: auto; }
}

/* 벽면 모드 (65인치) */
body.wall { --fs-body: 16px; --fs-small: 13px; --fs-title: 30px; --fs-section: 18px; --fs-kpi: 38px; --card-pad: 24px; }
body.wall .panel.twin-panel, body.wall .row1 > .panel:not(.twin-panel) { height: 640px; }
body.wall .scenario, body.wall #phonebar { display: none; }
body.wall .level-word { font-size: 44px; }
body.wall .crit .val { font-size: 24px; }

/* 전화기 */
.phonebar { display: none; }
@media (max-width: 860px) {
  .phonebar { display: flex; align-items: center; gap: 8px; height: 48px; padding: 0 8px; border-bottom: 1px solid var(--border); background: var(--surface); position: sticky; top: 0; z-index: 10; }
  .phonebar .nm { font-weight: 600; }
  .app { height: auto; }
  .canvas { height: auto; }
  .title-row .right { flex-direction: column; align-items: flex-start; gap: 6px; }
  .scenario .lbl { display: none; }
  .twin { display: flex; flex-direction: column; }
  .twin-sel { order: 3; }
  .title-row h1 { font-size: 20px; }
  .panel.twin-panel, .row1 > .panel:not(.twin-panel) { height: auto; }
  .twin { height: 300px; min-height: 300px; }
  #layers { display: none; }
  .twin-legend { display: none; }
  .twin-sel { position: static; max-width: none; margin-top: 8px; }
  .panel.twin-panel .body { display: flex; flex-direction: column; }
  .recv { grid-template-columns: repeat(2, 1fr); }
  .matrix { grid-template-columns: minmax(0, 1fr) repeat(5, 40px); }
  .loggers { grid-template-columns: repeat(2, 1fr); }
  .panel.sticky { position: static; }
}

/* ---------- 2차 개정(11-05, 벤치마킹 반영) ---------- */
/* 알람 3종 꼬리표 */
.tag { display: inline-block; margin-right: 6px; padding: 0 6px; height: 18px; line-height: 18px; border-radius: 4px; font-size: 11px; font-weight: 500; vertical-align: 1px; background: var(--raised); color: var(--text); }
.tag.data { background: #ffe6d3; color: #6b2d00; } .tag.status { background: #ececec; color: #3d3d3d; } .tag.corr { background: #dfe9f5; color: #00336e; }
/* 이벤트 처리 체인(식별 → 오경보 필터 → 통보 → 보고서) */
.chain { list-style: none; margin: 0 0 12px; padding: 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.chain li { position: relative; padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface); min-width: 0; }
.chain li::before { content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px; border-radius: 2px; background: var(--control); }
.chain li.done::before { background: var(--lv0); }
.chain li b { display: block; font-weight: 500; font-size: 13px; }
.chain li span { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; line-height: 1.35; }
.chain.idle { display: block; padding: 8px 12px; border: 1px dashed var(--control); border-radius: var(--radius-control); color: var(--muted); font-size: var(--fs-small); }
/* 공공 기준 대조 */
.pub { margin-top: 8px; padding: 8px 10px; background: var(--raised); border-radius: var(--radius-control); font-size: 12px; line-height: 1.45; display: grid; gap: 4px; }
.pub div { display: grid; grid-template-columns: 96px 1fr; gap: 8px; }
.pub .k { color: var(--muted); white-space: nowrap; }
/* 조치 = 이슈 */
.action .iss { color: var(--faint); font-size: 12px; margin-top: 3px; }
.issue { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; margin-bottom: 8px; }
.issue div { display: flex; gap: 8px; justify-content: space-between; }
.issue .k { color: var(--muted); white-space: nowrap; }
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.btnrow .btn { height: 32px; padding: 0 12px; font-size: 13px; }
/* 품질 행렬 6검사 */
.matrix.six { grid-template-columns: minmax(0, 1fr) repeat(6, 52px); }
.matrix.six .h { font-size: 12px; }
.matrix.six .c:nth-child(6n+1) { justify-content: flex-end; }
.matrix.six .c:nth-child(7n+1) { justify-content: flex-start; }
.kv.calc a { color: var(--text); text-decoration: underline; text-underline-offset: 2px; }
/* 1행 높이: 공공 기준 두 줄이 들어가 36px 늘림 */
.panel.twin-panel, .row1 > .panel:not(.twin-panel) { height: 588px; }
.row1 .crit { padding: 8px 0; }
.pub { padding: 6px 10px; gap: 2px; line-height: 1.4; }
body.wall .panel.twin-panel, body.wall .row1 > .panel:not(.twin-panel) { height: 732px; }
.chain.narrow { grid-template-columns: 1fr 1fr; }
.kma .k { white-space: nowrap; }
@media (max-width: 860px) { .panel.twin-panel, .row1 > .panel:not(.twin-panel) { height: auto; } .chain { grid-template-columns: 1fr 1fr; } .matrix.six { grid-template-columns: minmax(0, 1fr) repeat(6, 36px); } .issue { grid-template-columns: 1fr; } }
/* P1(11-05): 변형 · 히트맵 조절줄 */
.chips-lbl { color: var(--faint); font-size: var(--fs-small); align-self: center; margin-right: 2px; }
#viz { align-items: center; }

table.compact td, table.compact th { white-space: nowrap; font-size: 13px; padding-left: 6px; padding-right: 6px; }

/* ---------- P2(11-05): 4D 재생 · 완전성 보드 · 안정화도 · 보고서 · 잔존수명 · 연결 ---------- */
.replay { display: flex; align-items: center; gap: 10px; padding: 6px 8px 10px; }
.replay .btn { height: 28px; padding: 0 12px; font-size: 13px; white-space: nowrap; }
.replay input[type="range"] { flex: 1; accent-color: var(--text); }
.replay .t { font-variant-numeric: tabular-nums; font-size: 13px; min-width: 150px; }
.replay .meta { white-space: nowrap; }
.cgrid { display: grid; gap: 2px; font-size: 12px; }
.cgrid .h { color: var(--muted); font-size: 11px; text-align: center; padding-bottom: 4px; }
.cgrid .h:first-child, .cgrid .nm { text-align: left; }
.cgrid .nm { padding-right: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); display: flex; align-items: center; }
.cgrid .c { height: 24px; border-radius: 3px; display: flex; align-items: center; justify-content: center; font-variant-numeric: tabular-nums; color: var(--muted); background: var(--surface); border: 1px solid var(--rule); }
.cgrid .c.q1 { background: #fff4cc; color: #5c4300; border-color: transparent; } .cgrid .c.q2 { background: #ffe6d3; color: #6b2d00; border-color: transparent; } .cgrid .c.q3 { background: #c4242a; color: #fff; border-color: transparent; }
.cgrid .c.today { outline: 2px solid var(--text); outline-offset: -2px; }
.stab { display: block; width: 100%; height: auto; }
.docpage { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-control); padding: 28px 32px; font-size: 13px; line-height: 1.6; max-width: 820px; }
.docpage h3 { font-size: 18px; margin: 0 0 4px; } .docpage h4 { font-size: 14px; margin: 18px 0 6px; }
.docpage table { margin-top: 6px; } .docpage .hdr { color: var(--muted); font-size: 12px; display: flex; justify-content: space-between; border-bottom: 1px solid var(--border); padding-bottom: 8px; margin-bottom: 12px; }
.docpage .sig { color: var(--muted); font-size: 12px; margin-top: 18px; border-top: 1px solid var(--rule); padding-top: 8px; }
.sched td .pill { margin-right: 4px; }
.sched .btn { white-space: nowrap; height: 28px; padding: 0 8px; font-size: 12px; }
.life .pill { margin-left: 6px; }
.srcs { display: grid; gap: 10px; }
.src { display: grid; grid-template-columns: 1fr auto; gap: 4px 16px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-control); }
.src .t { font-weight: 500; } .src .d { color: var(--muted); font-size: 13px; grid-column: 1 / -1; }
.src .kv { grid-column: 1 / -1; margin-top: 6px; font-size: 13px; row-gap: 3px; }
.src .res { grid-column: 1 / -1; font-size: 12px; color: var(--faint); margin-top: 4px; }
@media print {
  body.printing .sidebar, body.printing .title-row, body.printing .phonebar, body.printing .no-print { display: none !important; }
  body.printing .app { display: block; } body.printing .canvas { height: auto; overflow: visible; padding: 0; }
  body.printing .docpage { border: 0; max-width: none; padding: 0; }
}

/* ---------- P2-b(11-06): 3D 설명 표 · 거동 ---------- */
.twin-callouts { position: absolute; inset: 0; pointer-events: none; }
.twin-leaders { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.twin-leaders line { stroke: #c4242a; stroke-width: 1.5; }
.twin-leaders line.lv1 { stroke: #5a8a1a; } .twin-leaders line.lv2 { stroke: #b58a00; } .twin-leaders line.lv3 { stroke: #d1600e; } .twin-leaders line.lv4 { stroke: #c4242a; } .twin-leaders line.lv0 { stroke: #6b6b6b; }
.twin-callout { position: absolute; left: 0; top: 0; min-width: 152px; max-width: 240px; padding: 8px 12px; background: rgba(255,255,255,0.96); border: 1.5px solid #c4242a; border-radius: 6px; font-size: 12px; line-height: 1.3; box-shadow: 0 2px 8px rgba(0,0,0,0.12); }
.twin-callout b { display: block; font-weight: 500; color: #0e1116; }
.twin-callout span { display: block; color: #5a616b; margin-top: 1px; }
.twin-callout.lv1 { border-color: #8dc63f; } .twin-callout.lv2 { border-color: #e6b400; } .twin-callout.lv3 { border-color: #ee7a14; } .twin-callout.lv4 { border-color: #d1232a; } .twin-callout.lv0 { border-color: #9aa3ad; }
.twin-callout.blocked, .twin-callout.missing { border-color: #6b6b6b; border-style: dashed; }

/* ---------- P2-b(11-06): 상황실 메인 상황판 ---------- */
.wall-bar { display: flex; align-items: center; gap: 18px; height: 56px; margin: calc(-1 * var(--pad)) calc(-1 * var(--pad)) 12px; padding: 0 20px; background: var(--bisco-navy); color: #fff; }
.wall-bar .logo { display: inline-flex; align-items: center; height: 36px; padding: 0 10px; background: #fff; border-radius: 6px; }
.wall-bar .logo img { display: block; height: 24px; width: auto; }
.wall-bar .ttl h1 { display: block; font-size: 17px; font-weight: 500; letter-spacing: 0; margin: 0; color: #fff; line-height: 1.2; }
.wall-bar .ttl span { display: block; font-size: 12px; color: rgba(255,255,255,0.72); }
.wall-bar .clock { margin-left: auto; text-align: right; }
.wall-bar .clock b { display: block; font-size: 22px; font-weight: 500; font-variant-numeric: tabular-nums; line-height: 1.1; }
.wall-bar .clock span { font-size: 12px; color: rgba(255,255,255,0.72); }
.wall-bar .links { display: flex; gap: 4px; }
.wall-bar .links a { color: #fff; text-decoration: none; padding: 8px 12px; border-radius: 6px; font-size: 13px; background: rgba(255,255,255,0.1); }
.wall-bar .links a:hover { background: rgba(255,255,255,0.22); }
.wall-bar .scen { display: inline-flex; border: 1px solid rgba(255,255,255,0.35); border-radius: 6px; overflow: hidden; }
.wall-bar .scen button { height: 28px; padding: 0 12px; border: 0; background: transparent; color: rgba(255,255,255,0.8); font-size: 12px; cursor: pointer; }
.wall-bar .scen button[aria-pressed="true"] { background: #fff; color: var(--bisco-navy); font-weight: 500; }
.wall-main { display: grid; grid-template-columns: 300px minmax(0, 1fr) 340px; gap: var(--gap); height: calc(100svh - 56px - 12px - var(--pad)); min-height: 700px; }
.wall-col { display: grid; grid-template-rows: auto auto minmax(0, 1fr); gap: var(--gap); min-height: 0; }
.wall-col:last-child { grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) auto; }
.wall-center { display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: var(--gap); min-height: 0; }
.wall-main a.panel { color: inherit; text-decoration: none; display: flex; flex-direction: column; }
.wall-main a.panel:hover { outline: 2px solid var(--bisco-blue); outline-offset: -2px; }
.wall-main .panel { padding: 16px; min-height: 0; }
.wall-main .panel > header { margin-bottom: 8px; }
.wall-gauge .gauge { display: block; width: 100%; height: auto; max-height: 180px; margin: 0 auto; }
.wall-gauge .now { text-align: center; font-size: 15px; margin-top: -4px; } .wall-gauge .now .k { color: var(--muted); }
.wall-gauge .now b { font-size: 26px; font-weight: 600; margin-left: 8px; }
.wall-gauge .crits { display: grid; gap: 4px; margin-top: 10px; }
.wall-gauge .crits div { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; align-items: center; font-size: 13px; }
.wall-gauge .crits .k { color: var(--muted); }
.wall-gauge .crits b { font-variant-numeric: tabular-nums; font-weight: 500; } .wall-gauge .crits small { color: var(--muted); font-weight: 400; }
.wall-gauge .foot { padding-top: 8px; font-size: 12px; }
.wall-weather .big { display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: center; }
.wall-weather .big .t { font-size: 44px; font-weight: 600; letter-spacing: -0.02em; line-height: 1; }
.wall-weather .big .t small { font-size: 18px; color: var(--muted); font-weight: 400; margin-left: 2px; }
.wall-weather .wx { display: grid; gap: 2px; font-size: 13px; color: var(--muted); } .wall-weather .wx b { color: var(--text); font-weight: 500; margin-left: 4px; }
.wall-weather .rows { margin-top: 10px; display: grid; gap: 4px; font-size: 13px; }
.wall-weather .rows div { display: grid; grid-template-columns: 60px 1fr; gap: 8px; } .wall-weather .rows .k { color: var(--muted); }
.wall-weather .rows .warn { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.wall-forecast .pred { margin-top: 6px; font-size: 13px; line-height: 1.45; }
.wall-forecast .pred b { display: block; font-size: 14px; font-weight: 500; } .wall-forecast .pred span { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
.wall-twin { padding: 12px; }
.wall-twin .twin { height: 100%; min-height: 420px; }
.twin-top { position: absolute; left: 12px; top: 12px; display: flex; gap: 12px; align-items: center; padding: 8px 12px; background: rgba(255,255,255,0.9); border-radius: 6px; font-size: 12px; color: var(--muted); pointer-events: auto; }
.twin-top b { color: var(--text); font-weight: 500; }
.twin-motion { position: absolute; right: 12px; bottom: 12px; padding: 8px 12px; background: rgba(255,255,255,0.9); border-radius: 6px; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; pointer-events: none; }
.wall-rag .qa { display: grid; gap: 6px; font-size: 13px; }
.wall-rag .q { font-weight: 500; } .wall-rag .a { color: var(--text); line-height: 1.5; max-height: 72px; overflow: hidden; }
.wall-rag .a p + p { margin-top: 4px; } .wall-rag .answer-num { font-weight: 600; }
.wall-rag .ask { display: flex; gap: 8px; margin-top: 10px; } .wall-rag .ask .input { flex: 1; height: 38px; }
.wall-chart { padding: 12px 16px 8px; }
.wall-chart .chart { flex: 1; min-height: 0; }
.wall-bridges { padding: 8px 12px; } .wall-bridges td { padding: 7px 6px; font-size: 13px; }
body.wallmain .canvas { overflow: hidden; }
body.wall .wall-main { height: calc(100svh - 56px - 12px - 20px); } body.wall .wall-bar { margin: -20px -28px 12px; }
body.wall .wall-main { grid-template-columns: 380px minmax(0, 1fr) 420px; }
body.wall .wall-gauge .gauge { max-height: 240px; }
@media (max-width: 1180px) { .wall-main { grid-template-columns: 1fr; height: auto; } .wall-twin .twin { height: 420px; } }

.wall-rag .a { max-height: 92px; }
.wall-twin .twin-sel { display: none; }
.wall-main .twin-legend { left: 12px; bottom: 10px; }
.wall-main .twin-motion { right: 12px; bottom: 10px; max-width: 46%; }
.sidebar .brand .logo { display: block; height: 22px; width: auto; margin: 0 0 8px; }

.chips[hidden] { display: none; }
.twin-top span { display: none; }
@media (min-width: 1700px) { .twin-top span { display: inline; } }
@media (max-width: 1699px) { .wall-main .twin-motion { display: none; } }

/* ---------- P2-c(11-06): CCTV ---------- */
.cam { position: relative; display: block; background: #0e1116; border-radius: 6px; overflow: hidden; color: #fff; text-decoration: none; aspect-ratio: 16 / 9; min-height: 0; }
.cam iframe, .cam video, .cam img { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; object-fit: cover; display: block; }
.cam .cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 5px 8px; background: linear-gradient(transparent, rgba(0,0,0,0.65)); font-size: 11px; display: flex; justify-content: space-between; gap: 8px; align-items: baseline; } /* taste-skill-ignore: 영상 위 중립 스크림 */
.cam .cap b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cam .cap span { white-space: nowrap; color: rgba(255,255,255,0.85); }
.cam .live { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: #e53935; margin-right: 4px; animation: camblink 1.2s infinite; }
@keyframes camblink { 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .cam .live { animation: none; } }
.cam-ph { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; color: #aab4be; font-size: 12px; text-align: center; padding: 10px; background: #1a1f26; }
.cam-ph small { font-size: 11px; color: #8f9aa5; }
.cam-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.cam-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.cam.big { aspect-ratio: 16 / 9; }
.cam-list { display: grid; gap: 2px; }
.cam-row { display: grid; grid-template-columns: auto 1fr auto; gap: 8px; align-items: center; padding: 8px; border-radius: 6px; color: var(--text); text-decoration: none; font-size: 13px; }
.cam-row:hover { background: var(--raised); } .cam-row.on { background: var(--active); }
.cam-row .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .cam-row .st { color: var(--muted); font-size: 12px; }
.wall-bottom { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--gap); min-height: 0; }
.wall-cctv .cam-strip { grid-template-columns: repeat(2, 1fr); gap: 6px; }
.wall-cctv .cam .cap { font-size: 11px; padding: 4px 8px; }
body.wall .wall-cctv .cam-strip { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1180px) { .cam-strip, .cam-grid { grid-template-columns: repeat(2, 1fr); } .wall-bottom { grid-template-columns: 1fr; } }

/* ---------- P2-c(11-06): 상황판 반응형 — 패드(≤1180) 2열, 전화기(≤860) 1열 핵심만 ---------- */
.wall-rag .ask .btn { white-space: nowrap; }
.wall-main a.panel.wall-alarms { display: none; }
.wall-alarms .alarm { min-height: 40px; padding: 6px 0; }
@media (max-width: 1699px) { .wall-bottom { grid-template-columns: 1fr; } .wall-cctv .cam-strip { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 1180px) {
  .wall-main { display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: auto; height: auto; min-height: 0; }
  .wall-center { grid-column: 1 / -1; order: -1; }
  .wall-twin .twin { height: 400px; min-height: 0; }
  .wall-col { display: grid; grid-template-rows: none; grid-auto-rows: auto; }
  .wall-main a.panel.wall-alarms { display: flex; }
  .wall-col:last-child .wall-chart .chart { min-height: 140px; }
  .wall-bar .links { display: none; }
  body.wallmain .canvas { overflow: auto; }
}
@media (max-width: 700px) {
  .wall-bar { height: auto; padding: 8px 16px; gap: 12px; flex-wrap: wrap; margin: -16px -16px 12px; }
  .wall-bar .logo { height: 30px; padding: 0 6px; } .wall-bar .logo img { height: 18px; }
  .wall-bar .ttl h1 { font-size: 14px; } .wall-bar .ttl span { display: none; }
  .wall-bar .clock { margin-left: auto; } .wall-bar .clock b { font-size: 16px; } .wall-bar .clock span { display: none; }
  .wall-bar .scen { order: 9; flex-basis: 100%; justify-content: stretch; } .wall-bar .scen button { flex: 1; }
  .wall-main { display: flex; flex-direction: column; gap: 10px; }
  .wall-col, .wall-center { display: contents; }
  /* 핵심만: 단계 · 알람 · 3D(작게) · CCTV 1 · 기상 · 3교량 · AI. 추이 그래프 · 예측 그래프는 숨긴다 */
  .wall-main .wall-gauge { order: 1; } .wall-main a.panel.wall-alarms { order: 2; display: flex; } .wall-main .wall-twin { order: 3; } .wall-bottom { order: 4; display: contents; } .wall-main .wall-cctv { order: 4; } .wall-main .wall-weather { order: 5; } .wall-main .wall-bridges { order: 6; } .wall-main .wall-forecast { order: 7; } .wall-main .wall-rag { order: 8; }
  .wall-main a.panel.wall-chart { display: none; }
  .wall-forecast .chart { display: none; }
  .wall-gauge .gauge { max-height: 132px; }
  .wall-gauge .now b { font-size: 22px; }
  .wall-twin .twin { height: 240px; min-height: 0; }
  .twin-top, .wall-main .twin-legend { display: none; }
  .twin-callout { max-width: 180px; font-size: 11px; }
  .wall-cctv .cam-strip { grid-template-columns: 1fr; }
  .wall-cctv .cam:not(.pub) { display: none; }
  .wall-weather .big .t { font-size: 32px; }
  .wall-rag .a { max-height: 60px; }
  .canvas { padding: 16px; }
}

/* ---------- P2-d(11-06): 출처 표기 · 시연 순환 · 큰 화면 CCTV 2×2 · 전화기 운영 관제 ---------- */
.twin-credit { position: absolute; right: 12px; top: 12px; max-width: 70%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 4px 8px; background: rgba(255,255,255,0.78); border-radius: 4px; font-size: 11px; line-height: 1.3; color: #5a616b; pointer-events: none; text-align: right; }
.wall-main .twin-credit { top: 12px; right: 12px; max-width: 50%; }
@media (max-width: 700px) { .twin-credit { display: none; } }
.demo-badge { margin-left: 8px; padding: 4px 8px; border-radius: 6px; background: rgba(255,255,255,0.16); color: #fff; font-size: 11px; white-space: nowrap; }
@media (min-width: 1700px) { .wall-bottom { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); } body.wall .wall-cctv .cam-strip, .wall-cctv .cam-strip { grid-template-columns: repeat(2, 1fr); gap: 8px; } }
/* PC(1181~1699): 3D 아래 한 줄에 AI | CCTV(공개 라이브 1 타일만) — 높이가 AI 와 맞아 상황판이 한 화면에 든다 */
@media (max-width: 1699px) and (min-width: 1181px) { .wall-bottom { grid-template-columns: 1fr; } .wall-cctv .cam-strip { grid-template-columns: 1fr; } .wall-cctv .cam { aspect-ratio: auto; height: 118px; } .wall-cctv .cam:nth-child(n+2) { display: none; } .wall-twin .twin { min-height: 300px; } .wall-rag .a { max-height: 60px; } }
/* 패드(701~1180): 가운데가 전체 폭이라 4 타일 한 줄 */
@media (max-width: 1180px) and (min-width: 701px) { .wall-cctv .cam-strip { grid-template-columns: repeat(4, 1fr); } }
body.wallmain .canvas { overflow: auto; }
@media (max-width: 700px) {
  /* 운영 관제도 전화기에서는 3D · 재난 단계 · 알람만 */
  .panel.twin-panel > header .chips, #layers, #viz, #replay { display: none !important; }
  .panel.twin-panel .twin { height: 260px; min-height: 260px; }
  .row2 > .panel:first-child, .row2 > .panel:last-child, .panel.col-12[aria-label="CCTV"] { display: none; }
  .title-row .finding { font-size: 13px; }
}

@media (max-width: 700px) { .segmented button, .wall-bar .scen button { white-space: nowrap; font-size: 12px; padding: 0 8px; } }

/* ---------- 마무리 손질(unslop, 11-06): 무게 · 자간 · 모서리 · 상태 ---------- */
b, strong { font-weight: 600; }
.panel h2, .title-row h1 { font-weight: 500; }
.title-row h1 { letter-spacing: 0; }
.kpi-value { letter-spacing: 0; }
.pill { border-radius: 6px; }
.docpage h3 { font-weight: 500; }
.cam .cap b { font-weight: 500; }
.wall-bridges td b { font-weight: 500; }
.cgrid .c.q3 { font-weight: 500; }
.btn:active { transform: scale(0.98); }
.chip:active { transform: scale(0.98); }
.chip:focus-visible, .btn:focus-visible, .card-link:focus-visible, .nav-item:focus-visible { outline: 2px solid var(--bisco-blue); outline-offset: 2px; }

/* 상황판 추이 그래프: 광안은 남색(강조), 남항 · 영도는 중립 단계 — 한 그래프에 강조 하나 */
.wall-main .chart, .wall-forecast .chart { --chart-1: var(--bisco-navy); --chart-2: #8a95a0; --chart-3: #c3cad1; }
@media (max-width: 1699px) and (min-width: 1181px) { .wall-gauge .gauge { max-height: 156px; } .wall-gauge .crits { margin-top: 8px; } .wall-forecast .pred span { font-size: 12px; } }
