diff --git a/viewer/index.html b/viewer/index.html
index 423c2f4..ffcfe8f 100644
--- a/viewer/index.html
+++ b/viewer/index.html
@@ -149,7 +149,7 @@ h2 { font-size: var(--prism-type-body-sm); line-height: var(--prism-lh-title); f
/* 버튼 — primary 화면당 1개 (BT-1), 히트 영역 44px (HT-1) */
button {
font: inherit; font-size: var(--prism-type-body-sm); font-weight: 500; line-height: 1.2;
- min-height: 2.75rem; padding: var(--prism-space-050) var(--prism-space-100); white-space: nowrap;
+ min-height: 2.25rem; padding: var(--prism-space-050) var(--prism-space-100); white-space: nowrap;
border: var(--prism-stroke-hairline) solid var(--prism-border-default); border-radius: var(--prism-radius-md);
background: var(--prism-bg-card); color: var(--prism-text-body); cursor: pointer;
}
@@ -420,11 +420,22 @@ let selected = null, isolate = false;
const hiddenSel = new Set();
let world = null;
+// 지보패턴별 색: 패턴 순번(측점 순)마다 dv 토큰을 쓰고, 7번째부터는 배경과 50% 혼합한 명도 차로 구분
+const patIdx = {};
+function patCss(p) { const k = patIdx[p] ?? 0; return 'color-mix(in srgb, var(--prism-dv-' + (k % 6 + 1) + ') ' + (k >= 6 ? 50 : 100) + '%, var(--prism-bg-canvas))'; }
+function patColor(p) {
+ const k = patIdx[p] ?? 0;
+ const c = new THREE.Color(tok('--prism-dv-' + (k % 6 + 1)));
+ if (k >= 6) c.lerp(new THREE.Color(tok('--prism-bg-canvas')), 0.5);
+ return c;
+}
+
function refreshColors() {
scene.background = new THREE.Color(tok('--prism-bg-canvas'));
for (const m of meshes) {
- const p = PART[m.userData.group];
- m.material.color.set(tok(p ? p.token : '--prism-text-subtle'));
+ const u = m.userData, p = PART[u.group];
+ if (u.group === '라이닝' && u.pattern) m.material.color.copy(patColor(u.pattern));
+ else m.material.color.set(tok(p ? p.token : '--prism-text-subtle'));
}
if (selected) selected.material.emissive.set(tok('--prism-text-heading'));
}
@@ -563,11 +574,16 @@ Promise.all([
refreshColors();
// 지보패턴 체크박스
- const pats = [...new Set(meta.components.filter((x) => x.pattern).map((x) => x.pattern))];
+ const firstFrom = {};
+ for (const c of meta.components) if (c.pattern && c.from_sta != null) firstFrom[c.pattern] = Math.min(firstFrom[c.pattern] ?? Infinity, c.from_sta);
+ const pats = Object.keys(firstFrom).sort((a, b) => firstFrom[a] - firstFrom[b]);
+ pats.forEach((p, i) => { patIdx[p] = i; });
+ refreshColors();
for (const p of pats) {
patternOn[p] = true;
const lab = document.createElement('label'); lab.className = 'opt';
const cb = document.createElement('input'); cb.type = 'checkbox'; cb.checked = true;
+ cb.style.accentColor = patCss(p);
cb.addEventListener('change', () => { patternOn[p] = cb.checked; applyVisibility(); });
const span = document.createElement('span'); span.textContent = p;
lab.append(cb, span); $('pats').appendChild(lab);