/*! RelScope 0.18.1 | (c) 이용우 · All rights reserved — LICENSE | lucide icons (ISC) · Feather (MIT) — relscope.LICENSES.txt */
/* relscope — 관계도·구조도 뷰어. 색·간격·글꼴은 전부 --rm-* 변수(01 §6).
   🔴 우선순위 계약: 아래 «기본값» 선언은 전부 :where() 로 감싸 명시도 0 — 사이트의 `.relscope { --rm-*: var(--사이트토큰) }` 이
   어느 순서로 불러와도 이긴다. 인라인 style·<style> 주입 없이 이 파일 하나로 동작한다(CSP default-src 'self'). */

/* ── 기본 테마(라이트) — 필수 연결 토큰 ── */
:where(.relscope, .rm-defaults) {
  --rm-bg: #ffffff; --rm-surface: #ffffff; --rm-surface-2: #f2f4f7;
  --rm-border: #d9dee5; --rm-border-strong: #c9d0d8;
  --rm-text: #111827; --rm-text-muted: #5b6574;
  --rm-accent: #2457d6; --rm-on-accent: #ffffff;
  --rm-ok: #157347; --rm-ok-soft: #e8f5ee; --rm-warn: #8a5a00; --rm-warn-soft: #fff6e0;
  --rm-fail: #c42b2b; --rm-fail-soft: #fdecec; --rm-idle: #5b6574; --rm-idle-soft: #eef0f3;
  --rm-up: #9a3412; --rm-up-soft: #fde7d6; --rm-down: #1c45ab; --rm-down-soft: #dbe6fb;
  --rm-font: system-ui, -apple-system, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif;
  --rm-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --rm-fs: 13px; --rm-fs-sm: 12px;
  --rm-sp-1: 4px; --rm-sp-2: 8px; --rm-sp-3: 12px; --rm-sp-4: 16px;
  --rm-radius: 10px; --rm-radius-sm: 6px;
  --rm-focus-ring: 0 0 0 3px rgba(36, 87, 214, .35);
  --rm-dur: 160ms;
}
/* ── 파생 토큰(필수 토큰에서 계산 — 연결하지 않아도 사이트를 따라간다) ── */
:where(.relscope) {
  --rm-group-bg: var(--rm-surface-2);
  --rm-frame-line: color-mix(in srgb, var(--rm-text-muted) 45%, var(--rm-border));
  --rm-edge: color-mix(in srgb, var(--rm-text-muted) 80%, var(--rm-bg));
  --rm-edge-strong: var(--rm-text-muted);
  --rm-dim-opacity: .28;
  --rm-stage-bg: var(--rm-bg);
  --rm-grid: color-mix(in srgb, var(--rm-border) 55%, transparent);
}
/* ── 기본 테마(다크) — 사이트가 연결하지 않은 독립 실행에서만 보인다 ── */
@media (prefers-color-scheme: dark) {
  :where(:root:not([data-theme="light"])) :where(.relscope, .rm-defaults) {
    --rm-bg: #0f1420; --rm-surface: #161c2a; --rm-surface-2: #1d2536;
    --rm-border: #2b3447; --rm-border-strong: #3a4559;
    --rm-text: #e6eaf2; --rm-text-muted: #a3adbf;
    --rm-accent: #7aa2ff; --rm-on-accent: #0b1020;
    --rm-ok: #4cc38a; --rm-ok-soft: #10291e; --rm-warn: #e0b04a; --rm-warn-soft: #2c230c;
    --rm-fail: #ff7b7b; --rm-fail-soft: #3a1517; --rm-idle: #a3adbf; --rm-idle-soft: #232b3b;
    --rm-up: #f5a06b; --rm-up-soft: #3a2416; --rm-down: #7aa2ff; --rm-down-soft: #17233d;
    --rm-focus-ring: 0 0 0 3px rgba(122, 162, 255, .5);
  }
}
:where(:root[data-theme="dark"]) :where(.relscope, .rm-defaults) {
  --rm-bg: #0f1420; --rm-surface: #161c2a; --rm-surface-2: #1d2536;
  --rm-border: #2b3447; --rm-border-strong: #3a4559;
  --rm-text: #e6eaf2; --rm-text-muted: #a3adbf;
  --rm-accent: #7aa2ff; --rm-on-accent: #0b1020;
  --rm-ok: #4cc38a; --rm-ok-soft: #10291e; --rm-warn: #e0b04a; --rm-warn-soft: #2c230c;
  --rm-fail: #ff7b7b; --rm-fail-soft: #3a1517; --rm-idle: #a3adbf; --rm-idle-soft: #232b3b;
  --rm-up: #f5a06b; --rm-up-soft: #3a2416; --rm-down: #7aa2ff; --rm-down-soft: #17233d;
  --rm-focus-ring: 0 0 0 3px rgba(122, 162, 255, .5);
}

/* ── 틀 ── */
.relscope {
  display: block; position: relative; box-sizing: border-box; max-width: 100%; min-width: 0;
  container-type: inline-size;
  font-family: var(--rm-font); font-size: var(--rm-fs); line-height: 1.5; color: var(--rm-text);
  background: var(--rm-bg); border: 1px solid var(--rm-border); border-radius: var(--rm-radius);
  overflow: hidden; transition: background-color var(--rm-dur), color var(--rm-dur);
}
.relscope *, .relscope *::before, .relscope *::after { box-sizing: border-box; }
.relscope [hidden] { display: none !important; }
.rm-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.rm-head { padding: var(--rm-sp-3) var(--rm-sp-4) var(--rm-sp-2); border-bottom: 1px solid var(--rm-border); }
.rm-title { margin: 0; font-size: calc(var(--rm-fs) * 1.15); font-weight: 700; overflow-wrap: anywhere; }
.rm-summary { margin: 2px 0 0; color: var(--rm-text-muted); font-size: var(--rm-fs-sm); overflow-wrap: anywhere; }
.rm-meta { display: flex; flex-wrap: wrap; gap: var(--rm-sp-1) var(--rm-sp-3); margin-top: var(--rm-sp-1); color: var(--rm-text-muted); font-size: var(--rm-fs-sm); }
.rm-meta-err { color: var(--rm-fail); font-weight: 600; }
.rm-audience { font-weight: 600; border: 1px solid currentColor; border-radius: 999px; padding: 0 var(--rm-sp-2); }

/* 툴바 */
.rm-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--rm-sp-2) var(--rm-sp-3); padding: var(--rm-sp-3); border-bottom: 1px solid var(--rm-border); background: var(--rm-surface); }
.rm-btn, .rm-select, .rm-input {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 32px; min-width: 32px; padding: 0 10px;
  font: inherit; font-size: var(--rm-fs-sm); color: var(--rm-text); background: var(--rm-surface);
  border: 1px solid var(--rm-border); border-radius: var(--rm-radius-sm); cursor: pointer;
  /* 사이트 전역 «input, select, textarea { width: 100%; margin … }» 가 끼어들지 않게 크기·여백을 직접 선언한다(api_system 실측) */
  width: auto; max-width: 100%; margin: 0; box-sizing: border-box; line-height: normal;
}
.rm-btn:hover { background: var(--rm-surface-2); }
.rm-btn:focus-visible, .rm-select:focus-visible, .rm-input:focus-visible { outline: none; box-shadow: var(--rm-focus-ring); border-color: var(--rm-accent); }
.rm-btn[aria-pressed="true"] { background: var(--rm-accent); color: var(--rm-on-accent); border-color: var(--rm-accent); }
/* 세 상태 토글(흐름) — 글자로 상태를 말하고, 실제로 켜졌으면 테두리·점으로 한 번 더 */
.rm-btn-state[data-on="true"] { border-color: var(--rm-accent); color: var(--rm-accent); }
.rm-btn-state[data-on="true"]::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--rm-ok); }
.rm-btn-state[data-state="off"] { color: var(--rm-text-muted); }
.rm-btn[disabled] { opacity: .5; cursor: not-allowed; }
.rm-btn svg, .rm-icon-inline { width: 16px; height: 16px; }
.rm-input { cursor: text; width: 9em; min-width: 0; padding: 0 8px; justify-content: flex-start; }
.rm-select { padding: 0 8px; }
.rm-search { display: inline-flex; align-items: center; gap: var(--rm-sp-2); min-width: 0; }
/* 버튼 묶음 공통 — 버튼끼리 붙지 않게(오너 2026-10-01 «버튼들 사이 여백») */
.rm-btn-row { display: flex; flex-wrap: wrap; gap: var(--rm-sp-2); margin-top: var(--rm-sp-2); }
.rm-search-count { font-size: var(--rm-fs-sm); color: var(--rm-text-muted); min-width: 3em; }
.rm-spacer { flex: 1 1 auto; }
.rm-more { position: relative; }
.rm-menu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 5; min-width: 180px; padding: 4px;
  background: var(--rm-surface); border: 1px solid var(--rm-border); border-radius: var(--rm-radius-sm); box-shadow: 0 8px 24px rgba(0, 0, 0, .14);
}
.rm-menu { display: grid; gap: 2px; }
.rm-menu .rm-btn { width: 100%; justify-content: flex-start; border: 0; }
.rm-toolbar-note { font-size: var(--rm-fs-sm); color: var(--rm-text-muted); order: 99; flex-basis: 100%; }   /* 안내 문구는 버튼 줄을 밀지 않게 자기 줄에 */
.rm-toolbar-note:empty { display: none; }
.rm-toolbar-note.rm-bad { color: var(--rm-fail); font-weight: 600; }

/* 본문 */
.rm-body { display: flex; min-width: 0; }
.rm-stage {
  position: relative; flex: 1 1 auto; min-width: 0; overflow: hidden; background: var(--rm-stage-bg);
  touch-action: pan-y; user-select: none; cursor: grab;
}
.rm-stage.rm-dragging { cursor: grabbing; }
.rm-stage:focus-visible { outline: none; box-shadow: inset var(--rm-focus-ring); }
.rm-svg { display: block; width: 100%; height: 100%; }
/* 마우스로 누르면 SVG 자체가 포커스를 받아 브라우저 기본 테두리(outline: auto)가 그려진다 — 끌기 중 넓혀 그린 SVG 위로 «검은 사각형»이 보이던 것(오너 지적).
   키보드 포커스 표시는 노드(.rm-node:focus-visible)와 무대(.rm-stage:focus-visible)가 따로 맡는다 */
.relscope .rm-svg:focus, .relscope .rm-stage:focus:not(:focus-visible) { outline: none; }
.rm-hint {
  position: absolute; left: 50%; top: 12px; transform: translateX(-50%); padding: 6px 10px; border-radius: 999px;
  background: var(--rm-text); color: var(--rm-bg); font-size: var(--rm-fs-sm); pointer-events: none; opacity: 0; transition: opacity var(--rm-dur);
}
.rm-hint.rm-show { opacity: .92; }

/* 노드 */
.rm-node { cursor: pointer; outline: none; }
.rm-node-bg { fill: var(--rm-surface); stroke: var(--rm-border-strong); stroke-width: 1.25; transition: stroke var(--rm-dur), fill var(--rm-dur); }
.rm-node:hover .rm-node-bg { stroke: var(--rm-accent); }
.rm-node:focus-visible .rm-node-bg, .rm-group-head:focus-visible .rm-group-chevron { stroke: var(--rm-accent); stroke-width: 3; }
.rm-node.rm-selected .rm-node-bg { stroke: var(--rm-accent); stroke-width: 2.5; fill: color-mix(in srgb, var(--rm-accent) 8%, var(--rm-surface)); }
.rm-node-label { font-family: var(--rm-font); font-size: var(--rm-fs); font-weight: 600; fill: var(--rm-text); }
.rm-node-sub { font-family: var(--rm-font); font-size: var(--rm-fs-sm); fill: var(--rm-text-muted); }
.rm-icon { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.rm-node-icon { color: var(--rm-accent); }
.rm-shape-dashed .rm-node-bg, .rm-k-external .rm-node-bg { stroke-dasharray: 5 4; }
.rm-k-decision .rm-node-bg { fill: var(--rm-surface-2); }
.rm-k-initial .rm-node-bg, .rm-k-start .rm-node-bg { fill: color-mix(in srgb, var(--rm-accent) 12%, var(--rm-surface)); }
.rm-k-failure .rm-node-bg { stroke: var(--rm-fail); }
.rm-k-final .rm-node-bg, .rm-k-end .rm-node-bg { stroke-width: 2.5; }
.rm-tone-up .rm-node-bg { fill: var(--rm-up-soft); stroke: var(--rm-up); }
.rm-tone-down .rm-node-bg { fill: var(--rm-down-soft); stroke: var(--rm-down); }
.rm-node-group .rm-node-bg { fill: var(--rm-group-bg); stroke-dasharray: 3 3; }

/* 상태 덧칠 — 상태는 색만으로 구분하지 않는다(표지 + 글자) */
.rm-status-label { font-family: var(--rm-font); font-size: var(--rm-fs-sm); fill: var(--rm-text-muted); }
.rm-status-mark circle { stroke-width: 0; }
.rm-s-ok .rm-node-bg { stroke: var(--rm-ok); stroke-width: 2; }
.rm-s-warn .rm-node-bg { stroke: var(--rm-warn); stroke-width: 2; fill: var(--rm-warn-soft); }
.rm-s-fail .rm-node-bg { stroke: var(--rm-fail); stroke-width: 2.5; fill: var(--rm-fail-soft); }
.rm-s-idle .rm-node-bg { stroke: var(--rm-idle); stroke-width: 1.5; }
.rm-s-ok .rm-status-label { fill: var(--rm-ok); }
.rm-s-warn .rm-status-label { fill: var(--rm-warn); }
.rm-s-fail .rm-status-label { fill: var(--rm-fail); font-weight: 700; }
.rm-status-b { font-weight: 700; } .rm-status-i { font-style: italic; }   /* 재는 쪽(instance.js RM_ROLE_CLASS statusB·I)이 쓰는 같은 글꼴 */
.rm-mark-ok { fill: var(--rm-ok); } .rm-mark-warn { fill: var(--rm-warn); } .rm-mark-fail { fill: var(--rm-fail); } .rm-mark-idle { fill: var(--rm-idle); }
.rm-mark-glyph { fill: none; stroke: var(--rm-bg); stroke-width: 2; stroke-linecap: round; }
.rm-fresh-mark { fill: none; stroke: var(--rm-text-muted); stroke-width: 1.5; }
.rm-f-stale .rm-node-bg { stroke-dasharray: 5 3; }
.rm-f-stale .rm-status-label, .rm-f-untimed .rm-status-label, .rm-f-skewed .rm-status-label { fill: var(--rm-text-muted); font-style: italic; }

/* 간선 */
.rm-edge-hit { fill: none; stroke: transparent; stroke-width: 12; cursor: pointer; }
.rm-edge-line { fill: none; stroke: var(--rm-edge); stroke-width: 1.6; transition: stroke var(--rm-dur), opacity var(--rm-dur); }
.rm-edge-arrow { fill: var(--rm-edge); stroke: none; }
.rm-edge-flow { fill: none; stroke: none; }
.rm-ek-async .rm-edge-line, .rm-ek-depends .rm-edge-line { stroke-dasharray: 6 4; }
.rm-ek-data .rm-edge-line { stroke-width: 2.2; }
.rm-ek-control .rm-edge-line { stroke-dasharray: 2 3; }
/* 구조 트리(0.14.0) — 부모·자식 꺾은선은 일반 간선 색 그대로·조금 가늘게(관계가 아니라 «포함»), 접기 단추·감춘 수.
   단추 테두리는 조작 요소라 바탕 대비 3:1 이상(--rm-text-muted) — 옅은 테두리색(--rm-border-strong)은 1.6 이라 못 쓴다 */
.rm-ek-tree .rm-edge-line { stroke-width: 1.4; }
.rm-tree-toggle { cursor: pointer; }
.rm-tree-toggle-bg { fill: var(--rm-surface); stroke: var(--rm-text-muted); stroke-width: 1.2; }
.rm-tree-toggle:hover .rm-tree-toggle-bg { stroke: var(--rm-accent); }
.rm-tree-toggle-mark { stroke: var(--rm-text-muted); stroke-width: 1.6; stroke-linecap: round; fill: none; }
.rm-tree-collapsed .rm-tree-toggle-bg { fill: color-mix(in srgb, var(--rm-accent) 12%, var(--rm-surface)); stroke: var(--rm-accent); }
.rm-tree-more { font-family: var(--rm-font); font-size: var(--rm-fs-sm); fill: var(--rm-text-muted); }
/* 이정표·기간(0.16.0) — 행 띠·눈금·오늘 선·마름모·기간 막대. 막대·마름모는 노드 안이라 상태색이 붙는다 */
.rm-tl-row { fill: var(--rm-surface-2); opacity: .55; }
.rm-tl-row-alt { opacity: .25; }
.rm-tl-row-label { font-family: var(--rm-font); font-size: var(--rm-fs-sm); font-weight: 600; fill: var(--rm-text-muted); }
.rm-tl-tick { stroke: var(--rm-border); stroke-width: 1; stroke-dasharray: 2 4; }
.rm-tl-tick-label { font-family: var(--rm-font); font-size: var(--rm-fs-sm); fill: var(--rm-text-muted); }
.rm-tl-today { stroke: var(--rm-accent); stroke-width: 1.6; }
.rm-tl-today-label { font-family: var(--rm-font); font-size: var(--rm-fs-sm); font-weight: 600; fill: var(--rm-accent); }
.rm-tl-point { fill: var(--rm-accent); stroke: var(--rm-surface); stroke-width: 1.5; }
.rm-tl-span { fill: var(--rm-accent); opacity: .85; }
.rm-s-ok .rm-tl-point, .rm-s-ok .rm-tl-span { fill: var(--rm-ok); }
.rm-s-warn .rm-tl-point, .rm-s-warn .rm-tl-span { fill: var(--rm-warn); }
.rm-s-fail .rm-tl-point, .rm-s-fail .rm-tl-span { fill: var(--rm-fail); }
.rm-s-idle .rm-tl-point, .rm-s-idle .rm-tl-span { fill: var(--rm-idle); }
.rm-ek-feedback .rm-edge-line { stroke-dasharray: 7 4; }
.rm-tone-up .rm-edge-line { stroke: var(--rm-up); } .rm-tone-up .rm-edge-arrow { fill: var(--rm-up); }
.rm-tone-down .rm-edge-line { stroke: var(--rm-down); } .rm-tone-down .rm-edge-arrow { fill: var(--rm-down); }
.rm-edge-label-bg { fill: var(--rm-bg); stroke: var(--rm-border); stroke-width: 1; }
.rm-edge-label-text { font-family: var(--rm-font); font-size: var(--rm-fs-sm); fill: var(--rm-text-muted); }
.rm-edge:hover .rm-edge-line, .rm-edge.rm-hot .rm-edge-line { stroke: var(--rm-edge-strong); stroke-width: 2.4; }
.rm-edge.rm-hot .rm-edge-arrow { fill: var(--rm-edge-strong); }
.rm-es-fail .rm-edge-line { stroke: var(--rm-fail); } .rm-es-fail .rm-edge-arrow { fill: var(--rm-fail); }
.rm-es-warn .rm-edge-line { stroke: var(--rm-warn); } .rm-es-warn .rm-edge-arrow { fill: var(--rm-warn); }
.rm-edge-break { fill: var(--rm-bg); stroke: var(--rm-fail); stroke-width: 2; }
.rm-es-idle .rm-edge-line { stroke: var(--rm-idle); } .rm-es-idle .rm-edge-arrow { fill: var(--rm-idle); }
.rm-es-stale .rm-edge-line { stroke: var(--rm-idle); stroke-dasharray: 3 4; } .rm-es-stale .rm-edge-arrow { fill: var(--rm-idle); }
.rm-legend-flow { flex-basis: 100%; }

/* 상태 선택 상자(흐름·추적) — 아이콘 + 고르기, 켜졌으면 점 */
.rm-state { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 4px 0 10px; border: 1px solid var(--rm-border); border-radius: var(--rm-radius-sm); background: var(--rm-surface); color: var(--rm-text-muted); }
.rm-state[data-on="true"] { border-color: var(--rm-accent); color: var(--rm-accent); }
.rm-state[data-on="true"]::after { content: ""; width: 6px; height: 6px; margin-right: 6px; border-radius: 50%; background: var(--rm-ok); }
.rm-state:focus-within { box-shadow: var(--rm-focus-ring); }
.rm-state .rm-state-select { border: 0; height: 30px; padding: 0 4px; background: transparent; color: var(--rm-text); }
.rm-state .rm-state-select:focus-visible { box-shadow: none; }

/* 들어옴·나감 — 줄 = 위치로 이동, 오른쪽 «선택» */
.rm-conn-head { display: flex; align-items: center; gap: 6px; margin: 12px 0 4px; font-weight: 700; font-size: var(--rm-fs-sm); color: var(--rm-text-muted); }
.rm-conn-head svg { width: 14px; height: 14px; }
.rm-conn-head.rm-conn-in svg { transform: rotate(180deg); }
.rm-count { display: inline-flex; min-width: 20px; justify-content: center; padding: 0 6px; border-radius: 999px; background: var(--rm-surface-2); color: var(--rm-text); font-weight: 600; }
.rm-panel ul.rm-conn-list { margin: 0 0 4px; padding: 0; border: 1px solid var(--rm-border); border-radius: var(--rm-radius-sm); overflow: hidden; }
.rm-conn-list li { display: flex; align-items: center; gap: 6px; padding: 2px 4px 2px 0; border-top: 1px solid var(--rm-border); }
.rm-conn-list li:first-child { border-top: 0; }
.rm-panel li button.rm-conn-go { all: unset; box-sizing: border-box; flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: pointer; color: var(--rm-text); font-size: var(--rm-fs-sm); border-radius: 4px; }
.rm-panel li button.rm-conn-go:hover { background: var(--rm-surface-2); }
.rm-panel li button.rm-conn-go:focus-visible { box-shadow: var(--rm-focus-ring); }
.rm-conn-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.rm-conn-name { max-width: 100%; font-weight: 600; word-break: keep-all; overflow-wrap: anywhere; }
.rm-conn-label { max-width: 100%; padding: 0 6px; border-radius: 999px; background: var(--rm-surface-2); color: var(--rm-text-muted); font-size: calc(var(--rm-fs-sm) * .92); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-sizing: border-box; }
.rm-conn-dot { flex: 0 0 8px; width: 8px; height: 8px; margin-top: .45em; align-self: flex-start; border-radius: 50%; background: var(--rm-border-strong); }
.rm-dot-ok { background: var(--rm-ok); } .rm-dot-warn { background: var(--rm-warn); } .rm-dot-fail { background: var(--rm-fail); } .rm-dot-idle { background: var(--rm-idle); }
.rm-panel .rm-conn-pick { height: 26px; padding: 0 8px; flex: 0 0 auto; }
.rm-peek .rm-node-bg { stroke: var(--rm-accent); stroke-width: 3; }
.rm-located .rm-node-bg { animation: rm-locate 1.4s ease-out 1; }
@keyframes rm-locate { 0%, 40% { stroke: var(--rm-accent); stroke-width: 7; } 100% { stroke-width: 2; } }

/* 반응 속도 — 움직이는 동안·화면 밖·큰 도식 */
.rm-moving .rm-edge-flow, .rm-offscreen .rm-edge-flow { animation-play-state: paused !important; }
.rm-moving *, .rm-large .rm-node-bg, .rm-large .rm-edge-line, .rm-large .rm-dimmed { transition: none !important; }
.rm-svg { transform-origin: 0 0; will-change: auto; }
.rm-moving .rm-svg { will-change: transform; }

/* 묶음 */
.rm-group-bg { fill: var(--rm-group-bg); stroke: var(--rm-border); stroke-width: 1; }
.rm-group-head { cursor: pointer; outline: none; }
.rm-frame-tab { fill: var(--rm-surface); stroke: var(--rm-frame-line); stroke-width: 1; }
/* 시퀀스 블록(loop·opt·alt) 테두리 — 일반 묶음보다 진하게(옅으면 블록 경계가 안 보인다, 오너 지적). 사이트 글자색에서 파생해 테마를 따른다 */
.rm-frame .rm-group-bg, .rm-branch-sep { stroke: var(--rm-frame-line); }
/* 시퀀스 배경 구역(rect, 0.13.0) — 테두리 없이 옅은 색으로 메시지 묶음을 구분한다(Mermaid rect rgb(...) 의 쓰임). 색은 사이트 토큰에서 */
.rm-frame-rect .rm-group-bg { stroke: none; fill: color-mix(in srgb, var(--rm-accent) 9%, transparent); }
.rm-frame-rect.rm-tint-ok .rm-group-bg { fill: color-mix(in srgb, var(--rm-ok) 11%, transparent); }
.rm-frame-rect.rm-tint-warn .rm-group-bg { fill: color-mix(in srgb, var(--rm-warn) 12%, transparent); }
.rm-frame-rect.rm-tint-fail .rm-group-bg { fill: color-mix(in srgb, var(--rm-fail) 9%, transparent); }
.rm-frame-rect.rm-tint-muted .rm-group-bg { fill: color-mix(in srgb, var(--rm-text-muted) 9%, transparent); }
/* 메모 노드(kind note, 0.13.0) — 점선 테두리·옅은 노랑 바탕(글자 모양은 그대로 — 크기 계산과 어긋나지 않게): «구성 요소»가 아니라 설명이라는 것을 모양으로 */
.rm-k-note .rm-node-bg { stroke-dasharray: 4 3; fill: color-mix(in srgb, var(--rm-warn) 10%, var(--rm-surface)); }
.rm-group-label { font-family: var(--rm-font); font-size: var(--rm-fs); font-weight: 700; fill: var(--rm-text-muted); }
.rm-group-chevron { color: var(--rm-text-muted); }

/* 강조·흐림·검색 */
.rm-dimmed { opacity: var(--rm-dim-opacity); transition: opacity var(--rm-dur); }
.rm-match .rm-node-bg { stroke: var(--rm-accent); stroke-width: 2.5; }
.rm-trace .rm-node-bg { stroke: var(--rm-accent); stroke-width: 2; }
.rm-edge.rm-trace .rm-edge-line { stroke: var(--rm-accent); stroke-width: 2.4; }
.rm-edge.rm-trace .rm-edge-arrow { fill: var(--rm-accent); }

/* 흐름 움직임(02 §4-5) — 상태와 묶인다: ok 흐름 · 나머지 정지 */
.rm-motion .rm-edge.rm-flowing .rm-edge-flow {
  stroke: var(--rm-accent); stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: 2 14;
  animation: rm-flow 1.1s linear infinite;
}
.rm-motion .rm-edge.rm-flowing.rm-es-ok .rm-edge-flow { stroke: var(--rm-ok); }
@keyframes rm-flow { to { stroke-dashoffset: -16; } }
.rm-pulse .rm-node-bg { animation: rm-pulse 900ms ease-out 1; }
.rm-pulse.rm-s-fail .rm-node-bg { animation-iteration-count: 2; }
@keyframes rm-pulse { 0% { stroke-width: 6; } 100% { stroke-width: 2; } }

/* 상세 패널 */
.rm-panel { flex: 0 0 300px; max-width: 300px; min-width: 0; border-left: 1px solid var(--rm-border); background: var(--rm-surface); padding: var(--rm-sp-3) var(--rm-sp-4); overflow: auto; }
.rm-panel h3 { margin: 0 0 4px; font-size: calc(var(--rm-fs) * 1.1); overflow-wrap: anywhere; }
.rm-panel p { margin: 4px 0; overflow-wrap: anywhere; }
.rm-panel dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 2px 10px; margin: 8px 0; font-size: var(--rm-fs-sm); }
.rm-panel dt { color: var(--rm-text-muted); }
.rm-panel dd { margin: 0; overflow-wrap: anywhere; }
.rm-panel ul { margin: 4px 0 8px; padding-left: 0; list-style: none; }
.rm-panel li button:not(.rm-btn):not(.rm-conn-go) { all: unset; cursor: pointer; color: var(--rm-accent); font-size: var(--rm-fs-sm); }
.rm-panel li button:not(.rm-btn):not(.rm-conn-go):focus-visible { box-shadow: var(--rm-focus-ring); border-radius: 3px; }
.rm-panel .rm-panel-close { float: right; }
.rm-card { margin: 8px 0; padding: 8px 10px; border: 1px solid var(--rm-border); border-radius: var(--rm-radius-sm); background: var(--rm-surface-2); font-size: var(--rm-fs-sm); }
.rm-chip { display: inline-flex; align-items: center; gap: 4px; padding: 0 8px; border-radius: 999px; font-size: var(--rm-fs-sm); font-weight: 600; }
.rm-chip-ok { background: var(--rm-ok-soft); color: var(--rm-ok); } .rm-chip-warn { background: var(--rm-warn-soft); color: var(--rm-warn); }
.rm-chip-fail { background: var(--rm-fail-soft); color: var(--rm-fail); } .rm-chip-idle { background: var(--rm-idle-soft); color: var(--rm-idle); }
.rm-panel a.rm-btn { text-decoration: none; margin-top: var(--rm-sp-2); }
.rm-panel > .rm-btn:not(.rm-panel-close) { margin-top: var(--rm-sp-2); }

/* 범례·목록 */
.rm-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: var(--rm-sp-2) var(--rm-sp-4); border-top: 1px solid var(--rm-border); color: var(--rm-text-muted); font-size: var(--rm-fs-sm); }
.rm-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.rm-legend-swatch { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.rm-sw-ok { background: var(--rm-ok); } .rm-sw-warn { background: var(--rm-warn); } .rm-sw-fail { background: var(--rm-fail); } .rm-sw-idle { background: var(--rm-idle); }
.rm-sw-up { background: var(--rm-up); } .rm-sw-down { background: var(--rm-down); }
.rm-list { border-top: 1px solid var(--rm-border); padding: var(--rm-sp-3) var(--rm-sp-4); }
.rm-list h4 { margin: 8px 0 4px; font-size: var(--rm-fs); }
.rm-table-wrap { overflow-x: auto; max-width: 100%; }
.rm-table-wrap:focus-visible { outline: none; box-shadow: var(--rm-focus-ring); }
.rm-table { border-collapse: collapse; width: 100%; font-size: var(--rm-fs-sm); }
.rm-table th, .rm-table td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--rm-border); white-space: nowrap; }
.rm-table th { color: var(--rm-text-muted); font-weight: 600; }

/* 오류 패널 */
.rm-errors { padding: var(--rm-sp-3) var(--rm-sp-4); }
.rm-errors h3 { margin: 0 0 6px; color: var(--rm-fail); font-size: var(--rm-fs); }
.rm-errors ol { margin: 0; padding-left: 1.4em; }
.rm-errors li { margin: 4px 0; overflow-wrap: anywhere; }
.rm-errors > .rm-btn { margin-top: var(--rm-sp-3); }
.rm-errors code { font-family: var(--rm-font-mono); font-size: var(--rm-fs-sm); background: var(--rm-surface-2); padding: 0 4px; border-radius: 4px; }
.rm-warn-li { color: var(--rm-warn); }

/* 미니맵 */
.rm-minimap { position: absolute; right: 8px; bottom: 8px; width: 160px; height: 110px; border: 1px solid var(--rm-border); border-radius: var(--rm-radius-sm); background: var(--rm-surface); opacity: .95; cursor: pointer; }
.rm-minimap svg { display: block; width: 100%; height: 100%; }
.rm-mm-node { fill: var(--rm-border-strong); }
.rm-mm-node.rm-s-fail { fill: var(--rm-fail); } .rm-mm-node.rm-s-warn { fill: var(--rm-warn); } .rm-mm-node.rm-s-ok { fill: var(--rm-ok); }
.rm-mm-view { fill: color-mix(in srgb, var(--rm-accent) 12%, transparent); stroke: var(--rm-accent); stroke-width: 2; vector-effect: non-scaling-stroke; }

/* 안내 이야기·발표 */
.rm-story { display: flex; align-items: center; gap: var(--rm-sp-3); padding: var(--rm-sp-2) var(--rm-sp-4); border-top: 1px solid var(--rm-border); background: var(--rm-surface-2); }
.rm-story-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.rm-story-step { color: var(--rm-text-muted); font-size: var(--rm-fs-sm); }
.relscope.rm-presenting { border-radius: 0; display: flex; flex-direction: column; }
.relscope.rm-presenting .rm-toolbar, .relscope.rm-presenting .rm-legend { display: none; }
.relscope.rm-presenting .rm-body { flex: 1 1 auto; }
.relscope.rm-presenting .rm-story-text { font-size: calc(var(--rm-fs) * 1.4); }

/* 대화상자(도움말) */
.rm-dialog-backdrop { position: absolute; inset: 0; background: rgba(15, 20, 32, .45); display: flex; align-items: center; justify-content: center; z-index: 10; padding: 16px; }
.rm-dialog { max-width: 420px; width: 100%; max-height: 100%; overflow: auto; background: var(--rm-surface); color: var(--rm-text); border-radius: var(--rm-radius); padding: var(--rm-sp-4); box-shadow: 0 16px 40px rgba(0, 0, 0, .3); }
.rm-dialog h3 { margin: 0 0 8px; }
.rm-dialog kbd { font-family: var(--rm-font-mono); font-size: var(--rm-fs-sm); padding: 0 5px; border: 1px solid var(--rm-border); border-radius: 4px; background: var(--rm-surface-2); }
.rm-dialog table { border-collapse: collapse; width: 100%; font-size: var(--rm-fs-sm); }
.rm-dialog > .rm-btn { margin-top: var(--rm-sp-3); }
.rm-dialog td { padding: 3px 6px; border-bottom: 1px solid var(--rm-border); }

/* 표현 프리셋 — 색은 토큰만, 바꾸는 것은 선·격자·여백·그림자 */
.relscope[data-rm-preset="blueprint"] {
  --rm-stage-bg: var(--rm-bg);
}
.relscope[data-rm-preset="blueprint"] .rm-stage {
  background-image: linear-gradient(var(--rm-grid) 1px, transparent 1px), linear-gradient(90deg, var(--rm-grid) 1px, transparent 1px);
  background-size: 24px 24px;
}
.relscope[data-rm-preset="blueprint"] .rm-node-bg { fill: var(--rm-bg); stroke-width: 1; }
.relscope[data-rm-preset="blueprint"] .rm-group-bg { fill: none; stroke-dasharray: 4 4; }
.relscope[data-rm-preset="signal"] { --rm-stage-bg: var(--rm-surface-2); }
.relscope[data-rm-preset="signal"] .rm-edge-line { stroke-width: 2.2; }
.relscope[data-rm-preset="signal"] .rm-motion .rm-edge.rm-flowing .rm-edge-flow { stroke-width: 3.2; stroke-dasharray: 3 11; }
.relscope[data-rm-preset="signal"] .rm-node-bg { stroke-width: 1.6; }
.relscope[data-rm-preset="editorial"] .rm-title { font-size: calc(var(--rm-fs) * 1.5); letter-spacing: -.01em; }
.relscope[data-rm-preset="editorial"] .rm-head { padding: var(--rm-sp-4) var(--rm-sp-4) var(--rm-sp-3); }
.relscope[data-rm-preset="editorial"] .rm-node-bg { stroke-width: 1; }
.relscope[data-rm-preset="editorial"] .rm-group-bg { fill: none; stroke: none; }
.relscope[data-rm-preset="editorial"] .rm-group-label { text-transform: none; font-size: calc(var(--rm-fs) * 1.05); fill: var(--rm-text); }

/* 좁은 폭(컴포넌트 기준) */
@container (max-width: 767px) {
  .rm-body { flex-direction: column; }
  .rm-panel { flex: 0 0 auto; max-width: none; width: 100%; border-left: 0; border-top: 1px solid var(--rm-border); max-height: 50vh; }
  .rm-input { width: 8em; }
  .rm-minimap { display: none; }
  .rm-wide-only { display: none; }
}

/* 움직임 줄이기 — 정보는 그대로, 움직임만 0 */
@media (prefers-reduced-motion: reduce) {
  .relscope *, .relscope *::before, .relscope *::after { animation: none !important; transition: none !important; }
  .rm-motion .rm-edge.rm-flowing .rm-edge-flow { stroke-dasharray: 2 6; }
  .rm-pulse .rm-node-bg { stroke-width: 4; }
}
.relscope.rm-no-motion *, .relscope.rm-no-motion *::before, .relscope.rm-no-motion *::after { animation: none !important; transition: none !important; }

/* ── 확장 8종(2026-10-02, docs/DIAGRAM_TYPES.md) — 같은 뜻은 같은 모양·색, 색은 기존 토큰에서만 ── */
/* 노드 안의 줄: ERD 열 · «키: 값» */
.rm-node-divider { fill: none; stroke: var(--rm-border); stroke-width: 1; }
.rm-row-band { fill: color-mix(in srgb, var(--rm-surface-2) 70%, transparent); stroke: none; }
.rm-field-name { font-family: var(--rm-font); font-size: var(--rm-fs-sm); fill: var(--rm-text); }
.rm-field-type { font-family: var(--rm-font-mono); font-size: var(--rm-fs-sm); fill: var(--rm-text-muted); }
.rm-field-key { font-weight: 700; }
.rm-field-flag { font-family: var(--rm-font); font-size: 10px; font-weight: 700; fill: var(--rm-text-muted); }
.rm-flag-bg { fill: var(--rm-surface-2); stroke: var(--rm-border); stroke-width: 1; }
.rm-flag-pk .rm-flag-bg { fill: var(--rm-warn-soft); stroke: var(--rm-warn); } .rm-flag-pk .rm-field-flag { fill: var(--rm-warn); }
.rm-flag-fk .rm-flag-bg { fill: var(--rm-down-soft); stroke: var(--rm-down); } .rm-flag-fk .rm-field-flag { fill: var(--rm-down); }
/* NULL 은 글꼴을 바꾸지 않는다(재는 글꼴 = flag 역할과 같아야 한다) — 점선 테두리로 구분 */
.rm-flag-null .rm-flag-bg { stroke-dasharray: 2 2; }
.rm-shape-table .rm-node-bg { stroke-width: 1.5; }
.rm-k-view .rm-node-bg { stroke-dasharray: 5 3; }
.rm-k-enum .rm-node-bg, .rm-k-collection .rm-node-bg { fill: var(--rm-surface-2); }
/* 대기열·이벤트 */
.rm-shape-queue .rm-node-bg { fill: var(--rm-surface-2); }
.rm-k-dlq .rm-node-bg { stroke: var(--rm-fail); stroke-width: 2; }
.rm-k-retry .rm-node-bg, .rm-k-delay .rm-node-bg { stroke: var(--rm-warn); stroke-dasharray: 5 3; }
.rm-k-dlq .rm-node-icon { color: var(--rm-fail); }
/* 네트워크·배포 */
.rm-k-internet .rm-node-bg, .rm-k-cdn .rm-node-bg, .rm-k-dns .rm-node-bg { fill: var(--rm-surface-2); }
.rm-k-firewall .rm-node-bg, .rm-k-waf .rm-node-bg { stroke: var(--rm-up); stroke-width: 2; }
.rm-k-firewall .rm-node-icon, .rm-k-waf .rm-node-icon, .rm-k-vpn .rm-node-icon { color: var(--rm-up); }
.rm-k-lb .rm-node-bg, .rm-k-gateway .rm-node-bg, .rm-k-router .rm-node-bg { stroke-width: 2; }
/* C4 · 컴포넌트 · 파이프라인 */
.rm-k-person .rm-node-bg, .rm-k-input .rm-node-bg { fill: color-mix(in srgb, var(--rm-accent) 10%, var(--rm-surface)); }
.rm-k-system .rm-node-bg { stroke-width: 2.25; }
.rm-k-interface .rm-node-bg { fill: var(--rm-surface-2); }
.rm-k-validation .rm-node-bg { stroke-dasharray: 2 3; stroke-width: 1.75; }
/* 간선: ERD 관계 · 구현 */
.rm-edge-card { fill: none; stroke: var(--rm-edge); stroke-width: 1.6; stroke-linecap: round; }
.rm-edge-card-o { fill: var(--rm-stage-bg); }   /* 0 허용 원 — 바탕으로 채워 선이 원을 가로지르지 않게 */
.rm-edge:hover .rm-edge-card, .rm-edge.rm-hot .rm-edge-card { stroke: var(--rm-edge-strong); }
.rm-edge.rm-trace .rm-edge-card { stroke: var(--rm-accent); }
.rm-es-fail .rm-edge-card { stroke: var(--rm-fail); } .rm-es-warn .rm-edge-card { stroke: var(--rm-warn); } .rm-es-idle .rm-edge-card, .rm-es-stale .rm-edge-card { stroke: var(--rm-idle); }
.rm-ek-implements .rm-edge-line { stroke-dasharray: 6 4; }
.rm-ek-implements .rm-edge-arrow { fill: var(--rm-bg); stroke: var(--rm-edge); stroke-width: 1.4; }
.rm-edge.rm-trace.rm-ek-implements .rm-edge-arrow { fill: var(--rm-bg); stroke: var(--rm-accent); }
/* 묶음 종류(경계) — 배치는 같고 테두리·옅은 바탕만 다르다 */
.rm-group-kind { color: var(--rm-text-muted); }
.rm-gk-environment .rm-group-bg { stroke: var(--rm-border-strong); stroke-width: 2; }
.rm-gk-region .rm-group-bg { fill: none; stroke: var(--rm-border-strong); stroke-dasharray: 8 4; }
.rm-gk-host .rm-group-bg { fill: var(--rm-surface); stroke: var(--rm-border-strong); stroke-width: 1.5; }
.rm-gk-cluster .rm-group-bg, .rm-gk-container .rm-group-bg { stroke: var(--rm-border-strong); stroke-dasharray: 3 3; }
/* 레인(0.17.0) — 띠 전체를 옅게 칠하고 테두리는 띠 경계만(둥글림 작게) */
.rm-gk-lane .rm-group-bg { fill: color-mix(in srgb, var(--rm-surface-2) 70%, var(--rm-bg)); stroke: var(--rm-border); stroke-width: 1; }
.rm-gk-lane .rm-group-label { font-weight: 700; }
.rm-gk-vpc .rm-group-bg { fill: color-mix(in srgb, var(--rm-accent) 3%, var(--rm-bg)); stroke: var(--rm-accent); stroke-width: 1.5; stroke-dasharray: 10 5; }
.rm-gk-vpc .rm-group-kind { color: var(--rm-accent); }
.rm-gk-subnet .rm-group-bg { fill: var(--rm-surface-2); stroke: var(--rm-border-strong); }
.rm-gk-public .rm-group-bg { fill: color-mix(in srgb, var(--rm-ok) 7%, var(--rm-bg)); stroke: color-mix(in srgb, var(--rm-ok) 55%, var(--rm-border)); }
.rm-gk-private .rm-group-bg { fill: color-mix(in srgb, var(--rm-accent) 6%, var(--rm-bg)); stroke: color-mix(in srgb, var(--rm-accent) 45%, var(--rm-border)); }
.rm-gk-data .rm-group-bg { fill: color-mix(in srgb, var(--rm-warn) 7%, var(--rm-bg)); stroke: color-mix(in srgb, var(--rm-warn) 50%, var(--rm-border)); }
.rm-gk-boundary .rm-group-bg, .rm-gk-system .rm-group-bg { fill: none; stroke: var(--rm-text-muted); stroke-width: 1.5; stroke-dasharray: 7 4; }
.rm-gk-module .rm-group-bg, .rm-gk-layer .rm-group-bg { fill: var(--rm-surface-2); }
/* 머리의 유형 표지 · 상세 패널의 줄 목록 */
.rm-type { font-weight: 600; }
.rm-panel-sub { margin: var(--rm-sp-2) 0 var(--rm-sp-1); font-size: var(--rm-fs-sm); color: var(--rm-text-muted); }
.rm-field-list { margin: 0; padding-left: 1.1em; font-size: var(--rm-fs-sm); overflow-wrap: anywhere; }
