/* 패턴 화면 — 왼쪽은 밝은 «설비», 오른쪽은 어두운 «모델». 그 대비가 뼈대다. */

:root {
  font-family: Pretendard, "Noto Sans KR", "Malgun Gothic", system-ui, sans-serif;
  color: #253b48; background: #f3f6f7;
  --edge: #e0e6e9; --teal: #168c85;
  --run: #63bfad; --wait: #b597d3; --rr: #e0996a; --call: #8fb6d8;
}
* { box-sizing: border-box }
body { margin: 0 }
button, select, input { font: inherit }
button { cursor: pointer; color: inherit; border: 1px solid #d8e1e5; background: #fff; border-radius: 8px }
button:hover:not(:disabled) { border-color: #87b8b9 }
button:disabled { opacity: .5; cursor: not-allowed }
a { color: inherit; text-decoration: none }
ol, ul { margin: 0; padding: 0 }
[hidden] { display: none !important }
:focus-visible { outline: 3px solid #e5a845; outline-offset: 3px }
.sr-only { position: absolute; clip: rect(0,0,0,0); width: 1px; height: 1px; overflow: hidden }

/* ── 머리 ───────────────────────────────────────────────────────────── */
/* 페이지 머리 — 레인 안의 <header> 까지 잡히지 않도록 반드시 body 바로 아래로 한정한다. */
body > header {
  height: 62px; padding: 0 24px; gap: 20px; display: flex; align-items: center;
  background: #fff; border-bottom: 1px solid var(--edge);
}
.brand { display: flex; align-items: center; gap: 13px; white-space: nowrap }
.brand > b { font-size: 25px; letter-spacing: -2px }
.brand > b span { color: #19a59a }
.brand > span { font-size: 13px; font-weight: 650 }
#pat-nav { display: flex; gap: 4px; margin-right: auto; flex-wrap: wrap }
#pat-nav a {
  font-size: 12px; padding: 7px 11px; border-radius: 20px;
  border: 1px solid transparent; color: #6d828d;
}
#pat-nav a:hover { border-color: #cfdde0; color: #29444d }
#pat-nav a[aria-current] { background: #e6f4f1; border-color: #8ec4bc; color: #12786f; font-weight: 600 }
.header-actions { display: flex; align-items: center; gap: 10px; font-size: 11px }
.header-actions button { padding: 7px 10px }
.demo-badge {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font-size: 11px; color: #8a5a10; background: #fdf2dd; padding: 7px 11px; border-radius: 20px;
}
.demo-badge i { width: 5px; height: 5px; background: #d9922a; border-radius: 50% }

/* 상단 소개 띠는 없앴다 — 제목·부제·규칙 한 줄이 3D 가 설 자리를 그만큼 먹었다.
   규칙 한 줄은 아래 「왜 이렇게 적는가」의 머리글로 내렸다. */
.rule-tag {
  font-size: 10px; color: #1c7d72; border: 1px solid #a6cfc8; border-radius: 5px;
  padding: 3px 7px; white-space: nowrap;
}
.rule-lead {
  display: flex; gap: 11px; align-items: baseline; margin: -8px 0 18px;
  background: #f1f7f6; border: 1px solid #cde3df; border-radius: 10px; padding: 12px 15px;
}
.rule-lead b { font-size: 13.5px; line-height: 1.7; font-weight: 600; word-break: keep-all }

/* ── 도구줄 ─────────────────────────────────────────────────────────── */
.toolbar {
  min-height: 56px; padding: 10px 24px; gap: 12px;
  display: flex; align-items: center; justify-content: space-between; background: #f8fafb;
}
.interaction-hint { display: flex; align-items: center; gap: 16px; font-size: 12px; min-width: 0 }
.interaction-hint b { font-weight: 600; white-space: nowrap }
.interaction-hint span { font-size: 11px; color: #7a8b95 }
.camera-tools { display: flex; gap: 6px }
.camera-tools button { height: 32px; padding: 0 11px; font-size: 12px }
.camera-tools button[aria-pressed=true] { background: #e2f2ef; border-color: #6eaca6 }

/* ── 두 화면 ────────────────────────────────────────────────────────── */
#views {
  position: relative; display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.18fr);
  height: 66vh; min-height: 470px; overflow: hidden;
}
.pane { position: relative; min-width: 0; overflow: hidden }
.pane.physical { background: #eef3f5 }
.pane.logical { background: #132433; color: #d8e7ee }
#scene-host { position: absolute; inset: 0 }
.pane-heading {
  position: absolute; top: 18px; left: 22px; right: 22px; pointer-events: none; z-index: 2;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
}
.pane-heading span:first-child { font-size: 10px; letter-spacing: 2px; color: #7d969f }
.logical .pane-heading span:first-child { color: #7f9cb2 }
.pane-heading h2 { font-size: 18px; font-weight: 600; letter-spacing: -.5px; margin: 7px 0 0 }
.physical .pane-heading > div { text-shadow: 0 1px 5px #eef3f5, 0 0 14px #eef3f5, 0 0 22px #eef3f5 }
.pane-chip { border: 1px solid #ccdadd; border-radius: 20px; padding: 5px 9px; font-size: 10px; color: #647d86; white-space: nowrap }
.logical .pane-chip { border-color: #3b5062; color: #a8bfce }
.pane-note {
  position: absolute; bottom: 12px; left: 22px; right: 22px; gap: 10px; z-index: 2;
  display: flex; justify-content: space-between; font-size: 10px; color: #667e8b; pointer-events: none;
}
.pane-note small { font-size: 9px; color: #8295a0 }
.logical .pane-note { color: #8aa4b8 }
.logical .pane-note small { color: #6d869b }

/* 물리 */
.readings { position: absolute; left: 22px; top: 86px; display: flex; gap: 7px; flex-wrap: wrap; max-width: calc(100% - 44px); z-index: 2; pointer-events: none }
.readings > span {
  border: 1px solid #d8e5e5; background: #ffffffe0; border-radius: 6px;
  font-size: 11px; padding: 7px 10px; display: flex; gap: 7px; align-items: center;
}
.readings i, .sensor-bar i { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: #9db0b7 }
.on i { background: #159b86 !important; box-shadow: 0 0 0 3px #159b8614 }
.readings b { font-weight: 600 }
#pins { position: absolute; inset: 0; pointer-events: none; z-index: 2 }
.device-pin {
  position: absolute; padding: 8px 12px; background: #fffffff2; border: 1px solid #d5e0e2;
  box-shadow: 0 6px 20px #173c4810; pointer-events: auto; transform: translate(-50%, -50%);
  border-radius: 9px; text-align: left; white-space: nowrap;
}
.device-pin small { display: block; font-size: 8px; letter-spacing: 1.6px; color: #7d949c }
.device-pin b { display: block; font-size: 12.5px; margin-top: 3px }
.device-pin.selected { border-color: #169c91; box-shadow: 0 0 0 3px #179c9117 }
.sensor-bar { position: absolute; bottom: 42px; left: 22px; display: flex; align-items: center; gap: 7px; z-index: 2; flex-wrap: wrap }
.sensor-bar > span { font-size: 10px; color: #67828c; margin-right: 3px }
.sensor-bar > div {
  display: flex; align-items: center; gap: 6px; background: #ffffffe0;
  font-size: 10px; padding: 7px 9px; border: 1px solid #d8e1e5; border-radius: 8px;
}
.sensor-bar b { font-size: 9px; color: #8a999e; font-weight: 600 }
.sensor-bar .on b { color: #178d79 }
.scene-note {
  position: absolute; left: 22px; right: 22px; top: 50%; transform: translateY(-50%); z-index: 3;
  text-align: center; font-size: 12px; line-height: 1.8; color: #5d7681;
  background: #ffffffe8; border: 1px solid #d8e5e5; border-radius: 10px;
  padding: 13px 17px; word-break: keep-all; max-width: 400px; margin: 0 auto;
}
.scene-note[data-tone=fail] { color: #8a4a2a; border-color: #ecd0be; background: #fff6f0f2 }

/* ── 오른쪽 논리 (2D) ───────────────────────────────────────────────── */
.logic-host { position: absolute; inset: 62px 18px 38px; overflow-x: hidden; overflow-y: auto }
#logic-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 0 }
.link { fill: none }
.call-link { stroke: var(--call); stroke-width: 1.4; stroke-dasharray: 4 4; opacity: .55; marker-end: url(#m-call) }
.call-link.live { opacity: 1; stroke-width: 2.2; stroke-dasharray: none }
.call-link.past { opacity: .8; stroke-dasharray: none }
.aux-link { stroke: var(--wait); stroke-width: 1.8; opacity: .6; marker-end: url(#m-aux) }
.aux-link.met { opacity: 1; stroke-width: 2.4; stroke: #d9c3ee }
.rr-link { stroke: var(--rr); stroke-width: 1.8; stroke-dasharray: 6 4; opacity: .85; marker-end: url(#m-rr) }
.group-box { fill: #4a729810; stroke: #60829a; stroke-width: 1; stroke-dasharray: 5 6 }
.group-label { fill: #90afc2; font-size: 10px; font-family: inherit }

.logic-stage { position: relative; display: flex; flex-direction: column; gap: 15px; z-index: 1; padding-bottom: 4px }
.lane { border: 1px solid #2c4358; border-radius: 11px; padding: 8px 11px 10px; background: #16293a80 }
.lane-passive { background: #10202ec0; border-color: #35516a }
.lane-head { display: flex; align-items: baseline; gap: 8px; margin: 0 0 7px; padding: 0; height: auto; background: none; border: 0; flex-wrap: wrap }
.lane-head b { font-size: 13px; color: #dbe8f1 }
.role { font-size: 9px; letter-spacing: 1.2px; padding: 3px 7px; border-radius: 4px; border: 1px solid }
.role-active { color: #7fe0c4; border-color: #35705f; background: #16352e }
.role-passive { color: #9dbbd6; border-color: #3a5670; background: #16293a }
.lane-head small { font-size: 10px; color: #7b98ad }
/* Flow 가 많으면 가로로 넘친다. 넘치느니 아래로 접는다 — 가로 스크롤은 읽기를 끊는다. */
.lane-flows { display: flex; gap: 18px 20px; align-items: flex-start; flex-wrap: wrap }
.flow { min-width: 0 }
.flow-name { font-size: 9.5px; color: #8fb0c6; margin-bottom: 5px; white-space: nowrap }
/* Work 는 가로로 세운다. 그래야 ACTIVE 한 줄 · PASSIVE 한 줄이 한 화면에 들어온다. */
.flow-works { display: flex; flex-direction: row; align-items: stretch; gap: 0 }
.work-slot { display: flex; align-items: stretch }
.start-tick { font-size: 9px; color: #6f8ea6; letter-spacing: .4px; display: flex; align-items: center; padding: 0 7px; white-space: nowrap; min-height: 34px }
.start-tick.rel-start::after { content: " →"; margin-left: 3px }
.start-tick.rel-group { color: #9fc0d6 }
.start-tick.rel-none { padding: 0 5px }
.call-tick { font-size: 9px; color: #6f8ea6; text-align: center; padding: 3px 0; letter-spacing: .4px }

.work {
  border: 1px solid #45637c; border-radius: 9px; background: #1b3041; padding: 7px 8px;
  cursor: pointer; width: 142px; flex: none; align-self: flex-start;
}
.work:hover { border-color: #6e93ad }
.work.selected { border-color: #88d6d3; box-shadow: 0 0 0 3px #85ddd21f }
.work[data-state=run] { background: #14424a; border-color: var(--run) }
.work[data-state=done] { background: #1d3640; border-color: #4e7f7c }
.work[data-state=wait] { border-style: dashed }
.work-head { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap }
.work-head small { font-size: 8px; letter-spacing: 1.3px; color: #89a8bd }
.work-head b { font-size: 12.5px; font-weight: 600; color: #dceaf3 }
.work-state { font-style: normal; font-size: 9px; color: #8ea2b4; margin-left: auto; white-space: nowrap }
.work[data-state=run] .work-state { color: #9ce1cc }
.work[data-state=done] .work-state { color: #94c3b3 }
.work-dur { font-size: 9px; color: #7e9bb0; margin-top: 3px; font-variant-numeric: tabular-nums }
.calls { margin-top: 6px; display: flex; flex-direction: column }
.call {
  display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
  padding: 6px 8px; border: 1px solid #3f5a70; border-radius: 6px; background: #223a4c; color: #d8e6ee;
}
.call-name { font-size: 11px; white-space: nowrap }
.call .act { font-style: normal; font-size: 8px; color: #93aec4; border: 1px solid #3f5a70; border-radius: 3px; padding: 1px 4px }
.call-state { margin-left: auto; font-size: 8.5px; color: #9cb0c0; white-space: nowrap }
.call[data-state=wait] { border-style: dashed }
.call[data-state=run] { background: #155453; border-color: var(--run) }
.call[data-state=done] { background: #233f40; border-color: #528581 }
.call[data-state=run] .call-state, .call[data-state=done] .call-state { color: #9ce1cc }
.call.selected { outline: 2px solid #b1efdf; outline-offset: 2px }

.view-divider { position: absolute; top: 0; bottom: 0; left: 0; width: 1px; background: #7d9ca966; z-index: 3; pointer-events: none }
.view-divider span { display: none }
#loading, #fallback {
  position: absolute; inset: 0; z-index: 10; background: #f2f7f8;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
}
#loading > span { width: 24px; height: 24px; border-radius: 50%; border: 2px solid #d3e3e2; border-top-color: #249a8f; animation: spin 1s linear infinite }
@keyframes spin { to { transform: rotate(360deg) } }
#fallback p { padding: 0 24px; text-align: center; font-size: 13px; color: #5d7681; max-width: 460px }

/* ── 대응 설명 ──────────────────────────────────────────────────────── */
.inspector { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); background: #fff; border-top: 1px solid var(--edge); min-height: 84px }
.inspector > div { display: flex; gap: 13px; padding: 15px 24px; align-items: flex-start; min-width: 0 }
.inspector .logical-detail { background: #edf3f5; border-left: 1px solid var(--edge) }
.detail-kicker { font-size: 10px; color: #358680; border: 1px solid #bfd9d5; padding: 4px 7px; border-radius: 5px; white-space: nowrap; margin-top: 1px }
.logical-detail .detail-kicker { color: #4c6b87; border-color: #c2d2e0 }
.inspector b { font-size: 13px; font-weight: 600; line-height: 1.5 }
.inspector p { font-size: 11px; line-height: 1.7; margin: 5px 0 0; color: #6c818c; word-break: keep-all }
.inspector .because { font-size: 10px; color: #7e6ba0; margin-top: 6px }
.inspector .because span { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px }
.inspector #clear { margin-left: auto; width: 28px; height: 28px; flex-shrink: 0; font-size: 18px }

/* ── 재생 ───────────────────────────────────────────────────────────── */
.transport { min-height: 84px; display: flex; align-items: center; gap: 24px; padding: 12px 24px; border-top: 1px solid var(--edge); background: #f8fafb }
.play-controls { display: flex; gap: 6px }
.play-controls button { height: 40px; padding: 0 13px }
.play-controls #play { background: #193f48; color: #fff; border-color: #193f48; min-width: 116px; display: flex; gap: 9px; align-items: center; justify-content: center; font-size: 12px }
.play-controls #restart { font-size: 19px; padding: 0 12px }
.timeline { flex: 1; min-width: 130px }
.timeline nav { display: flex; justify-content: space-between; gap: 6px }
.timeline nav button { background: none; border: none; font-size: 11px; color: #87949d; padding: 2px 0 6px; white-space: nowrap }
.timeline nav button[aria-current] { color: #16877e; font-weight: 700 }
.timeline input { width: 100%; accent-color: #248d85; cursor: pointer; height: 14px; margin: 2px 0 0 }
.play-options { display: flex; gap: 12px; align-items: center; font-size: 11px }
.play-options > span { color: #79909a; font-variant-numeric: tabular-nums; width: 30px }
.play-options label { display: flex; gap: 6px; align-items: center; color: #7d8c95 }
.play-options select { border: 0; background: transparent; color: #496671; padding: 6px 2px }
.play-options button { padding: 7px 10px; font-size: 11px }
.play-options button[aria-pressed=true] { background: #e0f0ec; color: #137f73; border-color: #8bbdb6 }

/* ── 왜 이렇게 적는가 ───────────────────────────────────────────────── */
.rule-detail { padding: 30px 24px 44px; background: #fff; border-top: 1px solid var(--edge) }
.rule-detail h3 { font-size: 15px; margin: 0 0 18px; letter-spacing: -.3px }
#rule-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 18px; counter-reset: r; list-style: none }
#rule-list li { border-left: 3px solid #d4e5e2; padding-left: 14px; counter-increment: r }
#rule-list li b { display: block; font-size: 13px; font-weight: 650; margin-bottom: 6px; line-height: 1.55; word-break: keep-all }
#rule-list li b::before { content: counter(r) ". "; color: var(--teal) }
#rule-list li p { margin: 0; font-size: 12px; line-height: 1.85; color: #63777f; word-break: keep-all }
.pager { display: flex; justify-content: space-between; gap: 12px; margin-top: 30px; font-size: 12.5px }
.pager a { padding: 10px 14px; border: 1px solid #d8e1e5; border-radius: 9px; color: #3d6e78 }
.pager a:hover { border-color: #87b8b9 }
.pager a:only-child { margin-left: auto }

/* ── 모델 정보 ──────────────────────────────────────────────────────── */
dialog { width: min(600px, calc(100vw - 32px)); padding: 32px; border: 1px solid #cbdade; border-radius: 16px; max-height: 86vh; color: #29444d; box-shadow: 0 25px 100px #06192366 }
dialog::backdrop { background: #0d202b80 }
#about-close { float: right; font-size: 22px; border: 0 }
dialog .eyebrow { font-size: 10px; color: #358f87; letter-spacing: 2px }
dialog h2 { font-size: 22px; line-height: 1.5; margin: 12px 0 16px }
dialog p { font-size: 12.5px; line-height: 1.9; color: #617a85; word-break: keep-all }
dialog dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 11.5px; margin: 18px 0 }
dialog dt { color: #46707c; white-space: nowrap }
dialog dd { margin: 0; color: #617a85; word-break: break-all }
dialog .links { display: flex; gap: 14px; margin-top: 18px; font-size: 12px; color: #17857a; flex-wrap: wrap }

/* ── 좁은 화면 ──────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  body > header, .toolbar, .rule-detail { padding-left: 16px; padding-right: 16px }
  .intro { grid-template-columns: minmax(0,1fr); gap: 16px }
  .interaction-hint { flex-direction: column; align-items: flex-start; gap: 4px }
  .pane-heading, .pane-note, .readings, .sensor-bar { left: 16px; right: 16px }
  .logic-host { inset: 62px 14px 38px }
  .inspector > div { padding: 13px 16px; gap: 10px }
  .transport { padding: 12px 16px; gap: 16px }
}
@media (max-width: 860px) {
  body > header { height: auto; flex-wrap: wrap; padding-top: 10px; padding-bottom: 10px; gap: 10px }
  #pat-nav { order: 3; flex-basis: 100% }
  #views { grid-template-columns: minmax(0,1fr); height: auto; min-height: 0 }
  .pane { height: 56vh; min-height: 330px }
  .view-divider { left: 0; right: 0; top: 56vh; bottom: auto; width: auto; height: 1px }
  .inspector { grid-template-columns: minmax(0,1fr) }
  .inspector .logical-detail { border-left: 0; border-top: 1px solid var(--edge) }
  .transport { flex-wrap: wrap; gap: 10px }
  .play-controls { order: 1 }
  .play-options { order: 2; margin-left: auto; gap: 8px }
  .play-options label > span, .play-options button span, .camera-tools button span { display: none }
  .camera-tools button { width: 31px; height: 31px; padding: 0 }
  .timeline { order: 3; flex-basis: 100% }
}
/* 좁은 화면 — Work 를 가로로 세우면 넘친다. 세로로 세우고 화살표도 아래로 돌린다. */
@media (max-width: 560px) {
  .flow-works { flex-direction: column; align-items: stretch }
  .work-slot { flex-direction: column; align-items: stretch }
  .work { width: auto; align-self: stretch }
  .start-tick { min-height: 0; padding: 4px 0; justify-content: center }
  .start-tick.rel-start::after { content: "" }
  .start-tick.rel-start::before { content: "↓ "; margin-right: 3px }
  .lane-flows { flex-direction: column; gap: 12px }
  .flow { width: 100% }
}
@media (max-width: 430px) {
  .intro h1 { font-size: 19px }
  #pat-nav a { font-size: 11px; padding: 6px 9px }
}
@media (prefers-reduced-motion: reduce) { #loading > span { animation: none } }


/* ═══ 데모 전용 — 양쪽 다 3D, 카드는 형상 자리에 붙는다 ═══════════════ */
#views { grid-template-columns: minmax(0,1fr) minmax(0,1fr); height: 64vh; min-height: 460px }
#canvas-host { position: absolute; inset: 0; z-index: 0; pointer-events: none }
#orbit { position: absolute; inset: 0; z-index: 1; touch-action: none; cursor: grab }
#orbit:active { cursor: grabbing }
.pane { position: relative; z-index: 2; pointer-events: none; background: none }
.pane.logical { background: none; color: #d8e7ee }
.pane .pane-heading, .pane .pane-note, .readings, .sensor-bar { pointer-events: none }

/* 근거 줄은 3D 바로 위에 앉는다. 강조 고리처럼 밝은 것이 지나가면 글자 테두리만으로는
   대비가 무너진다 — 아래쪽에 바탕색 막을 옅게 깔아 글자를 띄운다.
   3D 가 어두운 자리에서는 막이 거의 보이지 않고, 밝아진 자리에서만 일한다. */
.pane::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 46px;
  pointer-events: none; z-index: 1;
  background: linear-gradient(to top, #eef3f5 10%, rgba(238, 243, 245, 0) 100%);
}
.pane.logical::after { background: linear-gradient(to top, #0e1a24 10%, rgba(14, 26, 36, 0) 100%) }
.device-pin, .work-card, .call, .work-head, .cond-notes button { pointer-events: auto }

/* 왼쪽 이름표는 픽셀 좌표로 놓는다(projectPart 가 픽셀을 준다) */
#pins { position: absolute; inset: 0; pointer-events: none; z-index: 3 }
.device-pin { position: absolute; transform: translate(-50%, -50%) }

/* 오른쪽 — 형상 자리에 붙는 Work 카드 */
#logic-cards { position: absolute; inset: 0; pointer-events: none; z-index: 3 }
.work-card {
  position: absolute; width: 168px; padding: 8px 9px;
  border: 1px solid #4f7189; border-radius: 11px; background: #142739d8;
  box-shadow: 0 10px 26px #09152233; backdrop-filter: blur(3px);
}
/* 카드가 여럿이면 더 작고 더 비치게 — 윤곽이 이 화면의 내용이다. */
.pane.logical[data-cards="many"] .work-card { width: 150px; padding: 7px 8px; background: #142739c8 }
.pane.logical[data-cards="many"] .work-head b { font-size: 12px }
.pane.logical[data-cards="many"] .call { padding: 5px 7px }
.pane.logical[data-cards="many"] .call > span { font-size: 10.5px }
/* 카드가 많으면 이름이 먼저다 — 보조 표시(Action 종류)는 접고 상태는 기호만 남긴다. */
.pane.logical[data-cards="many"] .call > i { display: none }
.work-card .call > small em { font-style: normal }
.work-card .call > small .mk { margin-right: 4px }
/* 좁을 때는 표식만 남긴다 — 표식이 사라지면 상태를 읽을 길이 없다. */
.pane.logical[data-cards="many"] .call > small .wd { display: none }
.pane.logical[data-cards="many"] .call > small .mk { margin-right: 0; font-size: 11px }
.work-card.selected { border-color: #88d6d3; box-shadow: 0 0 0 3px #85ddd21f, 0 12px 30px #0915223d }
.work-card[data-state=run] { background: #11414ae0; border-color: var(--run) }
.work-card[data-state=done] { background: #1b3540cc; border-color: #4e7f7c }
.work-head {
  display: flex; align-items: center; justify-content: space-between; gap: 6px; width: 100%;
  background: none; border: 0; padding: 0 0 9px; text-align: left; color: #d3e2ed;
}
.work-head span { display: flex; flex-direction: column; gap: 3px; min-width: 0 }
.work-head small { font-size: 8px; letter-spacing: 1.4px; color: #89a8bd }
.work-head b { font-size: 13px; font-weight: 600 }
.work-head em { font-style: normal; font-size: 9px; color: #8ea2b4; white-space: nowrap }
.work-card[data-state=run] .work-head em { color: #9ce1cc }
.work-card .call {
  display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 7px;
  margin-bottom: 0; padding: 7px 9px; white-space: nowrap;
}
.work-card .call > span { font-size: 11.5px; overflow: hidden; text-overflow: ellipsis }
.work-card .call > i {
  font-style: normal; font-size: 8px; color: #9fbdd2;
  border: 1px solid #3f5a70; border-radius: 3px; padding: 1px 4px;
}
.work-card .call > i:empty { display: none }
.work-card .call > small { font-size: 8.5px; color: #9cb0c0 }
.call-tick { font-size: 9px; color: #85a9bd; text-align: center; padding: 5px 0 }

#logic-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2; overflow: visible }
.lead { fill: none; stroke: #5fd2c4; stroke-width: 1.2; stroke-dasharray: 3 4; opacity: .75 }
.lead-dot { fill: #5fd2c4; stroke: #0f2430; stroke-width: 1.5 }
/* Work 사이의 연결 — 고른 Work 의 것만 나온다. 나가는 선은 또렷하게, 들어오는 선은 옅게. */
.rel { fill: none }
.rel-out { stroke: #7fe3d2; stroke-width: 1.8 }
.rel-in { stroke: #e8b07a; stroke-width: 1.6; stroke-dasharray: 5 4 }
.rel-group { stroke-dasharray: 5 5 }
.rel-rr { stroke-dasharray: 6 4 }
.rel-tag { font-size: 9px; font-family: ui-monospace, monospace; text-anchor: middle }
text.rel-out { fill: #7fe3d2; stroke: none }
text.rel-in { fill: #e8b07a; stroke: none }

.cond-wrap { position: absolute; left: 20px; right: 20px; bottom: 40px; z-index: 3 }
.cond-notes { display: flex; gap: 8px }
.cond-notes button {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; text-align: left;
  padding: 9px 10px; background: #14273aE0; border: 1px solid #36506a; border-radius: 8px;
  font-size: 10px; color: #b9c6d7;
}
.cond-notes i { width: 5px; height: 5px; border-radius: 50%; background: #77678f; flex-shrink: 0 }
.cond-notes b { margin-left: auto; font-size: 9px; white-space: nowrap; color: #8195ad; font-weight: 500 }
.cond-notes .met i { background: #d4b1ed; box-shadow: 0 0 9px #ce9fff55 }
.cond-notes .met b { color: #d4b1ed }
.cond-notes .selected { outline: 2px solid #b1efdf; outline-offset: 2px }

.logical .pane-heading > div { text-shadow: 0 1px 6px #101f2c, 0 0 16px #101f2c }
/* 아래 근거 줄은 3D 위에 그대로 얹힌다. 강조 고리가 지나가면 넓고 옅은 그림자로는
   대비가 무너진다 — 바탕색으로 **바짝 붙은 테두리**를 둘러 글자를 떼어 낸다. */
.pane.logical .pane-note { color: #9ab6cb; text-shadow: 0 0 2px #0e1a24, 0 0 4px #0e1a24, 0 1px 9px #0e1a24 }
.pane.logical .pane-note small { text-shadow: 0 0 2px #0e1a24, 0 0 4px #0e1a24 }
.physical .pane-heading > div { text-shadow: 0 1px 5px #eef3f5, 0 0 14px #eef3f5 }
.pane:not(.logical) .pane-note { text-shadow: 0 0 2px #eef3f5, 0 0 4px #eef3f5, 0 1px 9px #eef3f5 }

.sync-badge {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font-size: 11px; color: #21706d; background: #ecf7f4; padding: 7px 11px; border-radius: 20px;
}
.sync-badge i { width: 5px; height: 5px; background: #17a18e; border-radius: 50% }
.sync-badge small { border-left: 1px solid #c5deda; padding-left: 8px; color: #648a89; font-size: 10px }
#pat-nav button {
  font-size: 12px; padding: 7px 11px; border-radius: 20px; border: 1px solid transparent;
  color: #6d828d; background: none;
}
#pat-nav button:hover { border-color: #cfdde0; color: #29444d }
#pat-nav button[aria-current=true] { background: #e6f4f1; border-color: #8ec4bc; color: #12786f; font-weight: 600 }
.view-divider { left: 50%; top: 0; bottom: 0; width: 1px; background: #7d9ca955 }
.view-divider span { display: grid; top: 50%; left: 0 }
dialog #about-models section { margin-top: 20px; border-top: 1px solid #e0ecee; padding-top: 14px }
dialog #about-models h3 { font-size: 13px; margin: 0 0 8px; color: #2b5560 }
dialog .foot { margin-top: 20px; font-size: 11.5px; color: #7d9298 }

@media (max-width: 860px) {
  #views { grid-template-columns: minmax(0,1fr); grid-template-rows: 1fr 1fr; height: 108vh; min-height: 620px }
  .pane { height: auto }
  .view-divider { left: 0; right: 0; top: 50%; bottom: auto; width: auto; height: 1px }
  .cond-wrap { left: 14px; right: 14px; bottom: 34px }
  .work-card { width: 152px }
}


/* ═══ 진행이 한눈에 보이게 ════════════════════════════════════════════ */

/* 「지금」 — 왼쪽 맨 위에 크게. 작은 글씨를 읽지 않아도 알 수 있어야 한다. */
.now-bar {
  position: absolute; left: 22px; top: 84px; z-index: 3; pointer-events: none;
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  background: #ffffffe8; border: 1px solid #cfe0dd; border-radius: 10px; padding: 9px 13px;
  box-shadow: 0 6px 18px #173c4810; max-width: calc(100% - 44px);
}
.now-tag {
  font-size: 9px; letter-spacing: 1.6px; color: #12786f;
  border: 1px solid #a6cfc8; border-radius: 4px; padding: 3px 6px; white-space: nowrap;
}
.now-bar b { font-size: 15px; font-weight: 700; letter-spacing: -.3px; color: #14424a }
.now-wait { font-size: 10.5px; color: #9aa9b0; white-space: nowrap }
.now-wait[data-on=yes] { color: #8a5a10 }
.now-wait[data-on=yes]::before { content: "⏳ "; }
.readings { top: 142px }

/* 단계 — 번호를 붙이고, 지난 단계는 채운다 */
.timeline nav { gap: 2px; align-items: stretch }
.timeline nav button.step {
  display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0;
  background: none; border: 0; padding: 2px 4px 7px; color: #8c99a2; font-size: 11px;
}
.timeline nav button.step i {
  font-style: normal; width: 17px; height: 17px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center; font-size: 9.5px; font-weight: 700;
  background: #e5ebee; color: #8c99a2; border: 1px solid #d5dee2;
}
.timeline nav button.step span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.timeline nav button.step[data-narrow=yes] span { display: none }
.timeline nav button.step[data-done=yes] i { background: #cfe8e2; border-color: #9fcbc2; color: #2b7d70 }
.timeline nav button.step[aria-current] { color: #14877e; font-weight: 700 }
.timeline nav button.step[aria-current] i { background: #17877e; border-color: #17877e; color: #fff }
/* 진행 막대 — **단계마다 한 칸**이다. 단계 단추와 같은 폭·같은 간격으로 선다.
   지금 단계는 통째로 그려진 채 깜빡인다: 「어디까지 왔나」가 아니라 「무엇을 하는 중인가」다. */
.rail { height: 4px; display: flex; gap: 2px; margin: 0 0 4px }
.rail span { flex: 1; min-width: 0; border-radius: 3px; background: #e2e9ec }
.rail span[data-state=done] { background: #17877e }
.rail span[data-state=now] { background: #17877e; animation: rail-blink 1.15s ease-in-out infinite }
@keyframes rail-blink { 0%, 100% { opacity: 1 } 50% { opacity: .28 } }
@media (prefers-reduced-motion: reduce) { .rail span[data-state=now] { animation: none; opacity: .7 } }

/* 카드·Call 상태 — 기호를 앞에 붙이고 색을 세게 준다 */
.work-card[data-state=run] { box-shadow: 0 0 0 2px #63bfad66, 0 14px 34px #0915223d }
/* «시작 전» 도 읽혀야 한다. 흐리게만 하면 밝은 윤곽 위에서 글자가 사라진다. */
.work-card[data-state=idle] { opacity: .82 }
.work-head em { font-variant-numeric: tabular-nums }
.work-card[data-state=wait] .work-head em { color: #e6c07a }
.work-card .call[data-state=idle] { opacity: .55 }
.work-card .call[data-state=wait] { border-color: #8a7350; background: #2b2a24 }
.work-card .call[data-state=wait] > small { color: #e6c07a }
.work-card .call[data-state=run] { box-shadow: 0 0 0 2px #63bfad55 }
.work-card .call[data-state=done] > small { color: #86c5b3 }

.cond-notes button { transition: background .15s, border-color .15s }
.cond-notes .met { background: #1d3a3aE0; border-color: #4f8b7f }

@media (max-width: 860px) {
  .now-bar { left: 14px; top: 76px; padding: 8px 11px }
  .now-bar b { font-size: 13px }
  .readings { top: 128px }
  .timeline nav button.step span { display: none }
  .timeline nav button.step { flex: 0 0 auto }
}


/* ═══ 3D 가 없는 자리 — 모델은 계속 읽힌다 ═══════════════════════════ */
.pane.logical[data-no3d="yes"] { background: #101f2c }
.pane.logical[data-no3d="yes"] #logic-cards {
  position: absolute; inset: 62px 18px 92px; pointer-events: auto;
  display: flex; flex-wrap: wrap; align-content: flex-start; gap: 10px; overflow: auto;
}
.pane.logical[data-no3d="yes"] .work-card { position: static; width: 168px; background: #142739 }
.pane.logical[data-no3d="yes"] #logic-links { display: none }

/* 형상 자리에 붙일 자리가 없을 때의 물러섬 — 3D 는 그대로 두고 카드만 한 줄로 흘린다. */
.pane.logical[data-flow="yes"] #logic-cards {
  position: absolute; inset: 60px 14px 88px; pointer-events: auto;
  display: flex; flex-wrap: wrap; align-content: flex-start; gap: 8px; overflow: auto;
}
.pane.logical[data-flow="yes"] .work-card { position: static; width: 148px; background: #142739f2 }
.pane.logical[data-flow="yes"] #logic-links { display: none }
#fallback[hidden] { display: none !important }

#fallback.nogl { padding: 0 18px }
#fallback.nogl h2 { font-size: 17px; text-align: center }
#fallback.nogl p { font-size: 12px }
@media (max-width: 860px) { #fallback.nogl { right: 0 !important; bottom: 50% } }
