feat(테마): 그림 전용 값 --draw-* — 종단 · 횡단 · 이정표 SVG · 지도 계획선 · CAD 바탕 · 3D 바탕 색을 화면 테마와 떼어 지금 색 고정 (PLAN 551-2)
- ui_template_theme.css 끝 블록 = --draw-* 17 개 · 밝음 / 어두움 / 시스템 어두움 글자 hex - B05 · B06 · B08 그림 CSS stroke · fill 125 줄 · --b06-tag = --draw-* - 캔버스 · 3D 읽기 = B05 노선 편집 지도 · 노선 추천 지도 · 3D 바탕 · B04 3D 바탕 · 지도 MC 글 · D03 고른 측점 · CAD 바탕 · 격자 - 지킴 시험 test_551_2_draw_tokens(화면 변수를 모두 바꿔도 그림 풀린 색 같음) - 기존 시험 7 개 = 그림 줄이 옛 --color-* 이름을 잡던 단정을 --draw-* 로 고침(값 같음) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -468,7 +468,7 @@ export function bindSurfaceViewerTheme(
|
||||
return;
|
||||
}
|
||||
const surfaceRaised = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue("--color-surface-raised")
|
||||
.getPropertyValue("--draw-surface-raised")
|
||||
.trim();
|
||||
applyBackground(
|
||||
surfaceRaised && CSS.supports("color", surfaceRaised)
|
||||
|
||||
@@ -330,9 +330,9 @@ export function drawStationTicks(
|
||||
context.translate(-lx, -ly);
|
||||
}
|
||||
// 배경을 깔아 등고선 위에서도 읽히게 한다.
|
||||
context.fillStyle = mc ? themeColor("--color-canvas", "#ffffff") : "rgba(255, 255, 255, 0.78)";
|
||||
context.fillStyle = mc ? themeColor("--draw-canvas", "#ffffff") : "rgba(255, 255, 255, 0.78)";
|
||||
context.fillRect(lx - half, ly - 8, width, 16);
|
||||
context.fillStyle = mc ? themeColor("--color-warning", "#b8860b") : "#222222";
|
||||
context.fillStyle = mc ? themeColor("--draw-warning", "#b8860b") : "#222222";
|
||||
context.fillText(label, lx, ly);
|
||||
context.restore();
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export function createRecommendMap(box: HTMLElement): RecommendMap {
|
||||
context.lineJoin = "round";
|
||||
const styles: Record<MapLayer["kind"], () => void> = {
|
||||
expected: () => {
|
||||
context.strokeStyle = themeColor("--color-text-secondary", "#9ca3af");
|
||||
context.strokeStyle = themeColor("--draw-text-secondary", "#9ca3af");
|
||||
context.lineWidth = 1.5;
|
||||
context.setLineDash([5, 4]);
|
||||
},
|
||||
@@ -129,7 +129,7 @@ export function createRecommendMap(box: HTMLElement): RecommendMap {
|
||||
context.setLineDash([]);
|
||||
},
|
||||
preview: () => {
|
||||
context.strokeStyle = themeColor("--color-primary", "#6d28d9");
|
||||
context.strokeStyle = themeColor("--draw-primary", "#6d28d9");
|
||||
context.lineWidth = 3;
|
||||
context.setLineDash([]);
|
||||
},
|
||||
|
||||
@@ -169,7 +169,7 @@ export function drawRouteEditScene(context: CanvasRenderingContext2D, scene: Rou
|
||||
const style = getComputedStyle(document.documentElement);
|
||||
const line = scene.plannedLine.length ? scene.plannedLine : scene.planned;
|
||||
context.clearRect(0, 0, view.width, view.height);
|
||||
context.fillStyle = style.getPropertyValue("--color-surface") || "#111";
|
||||
context.fillStyle = style.getPropertyValue("--draw-surface") || "#111";
|
||||
context.fillRect(0, 0, view.width, view.height);
|
||||
|
||||
// 여기서부터 **그림 전체**가 돈다 — 글자도 함께 돈다(CAD 도면과 같은 방식, 사용자 지시 ⑯).
|
||||
@@ -246,7 +246,7 @@ export function drawRouteEditScene(context: CanvasRenderingContext2D, scene: Rou
|
||||
toScreen,
|
||||
scene.expected,
|
||||
[6, 5],
|
||||
style.getPropertyValue("--color-text-secondary") || "#9ca3af",
|
||||
style.getPropertyValue("--draw-text-secondary") || "#9ca3af",
|
||||
1.6,
|
||||
);
|
||||
// 곡선 시작·끝점 — 잡아서 직선 각도와 R 을 함께 바꾸는 손잡이(2026-09-07 사용자 지시).
|
||||
@@ -307,7 +307,7 @@ export function drawRouteEditScene(context: CanvasRenderingContext2D, scene: Rou
|
||||
const bad = (scene.nodeInfo[index]?.violations?.length ?? 0) > 0;
|
||||
// 고정한 점은 고정 색 — 기준 미달(붉음)이 먼저다.
|
||||
context.fillStyle = bad
|
||||
? style.getPropertyValue("--color-danger") || "#dc2626"
|
||||
? style.getPropertyValue("--draw-danger") || "#dc2626"
|
||||
: scene.locked[index]
|
||||
? lockedColor
|
||||
: style.getPropertyValue("--map-route-node") || "#15803d";
|
||||
@@ -367,7 +367,7 @@ function drawContourLabels(
|
||||
style.getPropertyValue("--map-sheet-contour") || "#a5b4fc",
|
||||
scene.contourStepM,
|
||||
scene.uprightRad,
|
||||
style.getPropertyValue("--color-surface") || "#111", // 바탕칠과 같은 색 — 어두움에서 흰 상자 안 생김
|
||||
style.getPropertyValue("--draw-surface") || "#111", // 바탕칠과 같은 색 — 어두움에서 흰 상자 안 생김
|
||||
);
|
||||
if (scene.pickedContour >= 0) drawPickedContourLabel(context, scene, scene.view);
|
||||
context.restore();
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
|
||||
/* 비정규 측점(구조물)은 그래프에서도 파선 세로선으로 구분해 규칙 측점과 헷갈리지 않게 한다. */
|
||||
.b05-route-profile .b06-chart__station-line--irregular {
|
||||
stroke: var(--color-royal-amethyst, rgb(139 92 246));
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1.4;
|
||||
stroke-dasharray: 5 3;
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@
|
||||
|
||||
.b05-routeedit__cross-ground {
|
||||
fill: none;
|
||||
stroke: var(--color-text-secondary, #94a3b8);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1.6;
|
||||
vector-effect: non-scaling-stroke;
|
||||
}
|
||||
@@ -357,7 +357,7 @@
|
||||
}
|
||||
|
||||
.b05-routeedit__cross-key {
|
||||
fill: var(--color-text-secondary, #94a3b8);
|
||||
fill: var(--draw-text-secondary);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
|
||||
@@ -503,13 +503,13 @@
|
||||
|
||||
.b05-routerec__profile .is-ground {
|
||||
fill: none;
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
|
||||
.b05-routerec__profile .is-plan {
|
||||
fill: none;
|
||||
stroke: var(--color-primary);
|
||||
stroke: var(--draw-primary);
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@
|
||||
|
||||
.b05-profile-runmark__line {
|
||||
fill: none;
|
||||
stroke: var(--color-danger, #d64545);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 3;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
@@ -340,7 +340,7 @@
|
||||
|
||||
/* 구간 경계(라운드 시·종점) 세로 표식 — 어디까지 함께 움직이는지 알린다. */
|
||||
.b05-profile-runmark__edge {
|
||||
stroke: var(--color-danger, #d64545);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 3 3;
|
||||
opacity: 0.5;
|
||||
@@ -356,26 +356,26 @@
|
||||
}
|
||||
|
||||
.b05-profile-freemark__band {
|
||||
fill: color-mix(in srgb, var(--color-primary) 10%, transparent);
|
||||
fill: color-mix(in srgb, var(--draw-primary) 10%, transparent);
|
||||
}
|
||||
|
||||
.b05-profile-freemark__edge {
|
||||
stroke: var(--color-primary);
|
||||
stroke: var(--draw-primary);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
|
||||
/* 범위 「시작–끝 · 길이」 글 — [직선화] · [자유지정] 실시간 띠 위(271-2 · 3). */
|
||||
.b05-profile-freemark__span {
|
||||
fill: var(--color-primary);
|
||||
fill: var(--draw-primary);
|
||||
font-size: var(--text-caption);
|
||||
paint-order: stroke;
|
||||
stroke: var(--color-surface);
|
||||
stroke: var(--draw-surface);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
/* 지나온 선 · 미리 보기 · 점 = 녹색(367-4) — 범위 띠 · 경계는 보라 그대로. */
|
||||
.b05-profile-freemark__line {
|
||||
stroke: var(--color-success);
|
||||
stroke: var(--draw-success);
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: 6 4;
|
||||
}
|
||||
@@ -385,25 +385,25 @@
|
||||
}
|
||||
|
||||
.b05-profile-freemark__line.is-over {
|
||||
stroke: var(--color-danger, #d64545);
|
||||
stroke: var(--draw-danger);
|
||||
}
|
||||
|
||||
.b05-profile-freemark__dot {
|
||||
fill: var(--color-surface);
|
||||
stroke: var(--color-success);
|
||||
fill: var(--draw-surface);
|
||||
stroke: var(--draw-success);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
|
||||
.b05-profile-freemark__grade {
|
||||
fill: var(--color-text);
|
||||
fill: var(--draw-text);
|
||||
font-size: var(--text-caption);
|
||||
paint-order: stroke;
|
||||
stroke: var(--color-surface);
|
||||
stroke: var(--draw-surface);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.b05-profile-freemark__grade.is-over {
|
||||
fill: var(--color-danger, #d64545);
|
||||
fill: var(--draw-danger);
|
||||
}
|
||||
|
||||
.b05-profile-edit {
|
||||
|
||||
@@ -121,7 +121,7 @@ export function createRouteViewer(): RouteViewer {
|
||||
return;
|
||||
}
|
||||
const surfaceRaised = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue("--color-surface-raised")
|
||||
.getPropertyValue("--draw-surface-raised")
|
||||
.trim();
|
||||
scene.background = new THREE.Color(
|
||||
surfaceRaised && CSS.supports("color", surfaceRaised)
|
||||
|
||||
@@ -205,25 +205,25 @@
|
||||
|
||||
.b06-diag__ground {
|
||||
fill: none;
|
||||
stroke: var(--color-text-muted);
|
||||
stroke: var(--draw-text-muted);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 3 2;
|
||||
}
|
||||
|
||||
.b06-diag__road {
|
||||
fill: none;
|
||||
stroke: var(--color-text-body);
|
||||
stroke: var(--draw-text-body);
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.b06-diag__center {
|
||||
stroke: var(--color-royal-amethyst, rgb(109 40 217));
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 4 3;
|
||||
}
|
||||
|
||||
.b06-diag__tick {
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
@@ -244,12 +244,12 @@
|
||||
}
|
||||
|
||||
.b06-diag__label {
|
||||
fill: var(--color-text-body);
|
||||
fill: var(--draw-text-body);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.b06-diag__label-sm {
|
||||
fill: var(--color-text-secondary);
|
||||
fill: var(--draw-text-secondary);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
/* Y축 중심고 상자 색(379-3) — 원지반 = 원지반선 · 계획 = 설계선. */
|
||||
.b06-chart__center-tag--ground {
|
||||
--b06-tag: var(--color-chart-1);
|
||||
--b06-tag: var(--draw-chart-1);
|
||||
}
|
||||
|
||||
.b06-chart__center-tag--design {
|
||||
--b06-tag: var(--color-royal-amethyst);
|
||||
--b06-tag: var(--draw-accent);
|
||||
}
|
||||
|
||||
/* 면적 강조 밴드 — 평소엔 클릭 대상으로만 남고, 켜질 때만 채워진다. */
|
||||
@@ -30,34 +30,34 @@
|
||||
|
||||
/* 밴드 색은 위 면적표 글자색과 짝을 맞춘다 — 어느 숫자를 켰는지 색으로 바로 읽히게. */
|
||||
.b06-chart__area--cut_soil.is-active > polygon {
|
||||
fill: color-mix(in srgb, var(--color-chart-2) 28%, transparent);
|
||||
stroke: var(--color-chart-2);
|
||||
fill: color-mix(in srgb, var(--draw-chart-2) 28%, transparent);
|
||||
stroke: var(--draw-chart-2);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
/* 암반 밴드는 하나지만 색은 암종을 따라간다 — 표의 RR/BR 글자색과 같아야 짝이 읽힌다. */
|
||||
.b06-chart__area--cut_rr.is-active > polygon {
|
||||
fill: color-mix(in srgb, var(--color-success) 28%, transparent);
|
||||
stroke: var(--color-success);
|
||||
fill: color-mix(in srgb, var(--draw-success) 28%, transparent);
|
||||
stroke: var(--draw-success);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
.b06-chart__area--cut_br.is-active > polygon {
|
||||
fill: color-mix(in srgb, var(--color-chart-3) 28%, transparent);
|
||||
stroke: var(--color-chart-3);
|
||||
fill: color-mix(in srgb, var(--draw-chart-3) 28%, transparent);
|
||||
stroke: var(--draw-chart-3);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
.b06-chart__area--fill.is-active > polygon {
|
||||
fill: color-mix(in srgb, var(--color-chart-0) 28%, transparent);
|
||||
stroke: var(--color-chart-0);
|
||||
fill: color-mix(in srgb, var(--draw-chart-0) 28%, transparent);
|
||||
stroke: var(--draw-chart-0);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
/* 횡단 표준단면 설계선 오버레이. 기본은 실선. */
|
||||
.b06-chart__design-cross {
|
||||
fill: none;
|
||||
stroke: var(--color-royal-amethyst);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1.8;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
@@ -80,7 +80,7 @@
|
||||
/* 마우스 올림 = 고른 모양(379-1) · 고름은 누를 때만 */
|
||||
.b06-chart__design-hit:hover,
|
||||
.b06-chart__design-hit.is-active {
|
||||
stroke: color-mix(in srgb, var(--color-royal-amethyst) 45%, transparent);
|
||||
stroke: color-mix(in srgb, var(--draw-accent) 45%, transparent);
|
||||
stroke-width: 7;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
/* 원지반 십자선(413) = 원지반선 색 · 계획 십자선 아래(먼저 그림) */
|
||||
.b06-chart__ground-center-marker {
|
||||
stroke: var(--color-chart-1);
|
||||
stroke: var(--draw-chart-1);
|
||||
stroke-width: 2.5;
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@
|
||||
}
|
||||
|
||||
.b06-chart__center-hit.is-active {
|
||||
fill: color-mix(in srgb, var(--color-royal-amethyst) 18%, transparent);
|
||||
stroke: var(--color-royal-amethyst);
|
||||
fill: color-mix(in srgb, var(--draw-accent) 18%, transparent);
|
||||
stroke: var(--draw-accent);
|
||||
cursor: ew-resize;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
|
||||
.b06-chart__toe-hit:hover,
|
||||
.b06-chart__toe-hit.is-active {
|
||||
fill: var(--color-royal-amethyst);
|
||||
fill: var(--draw-accent);
|
||||
stroke: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -125,7 +125,7 @@
|
||||
/* 암 경계선 고름(370-3) — 점선 위 투명 판정 선 · 고르면 경고색 띠 · 세로 끌기. */
|
||||
.b06-chart__design-hit.b06-chart__rock-hit:hover,
|
||||
.b06-chart__design-hit.b06-chart__rock-hit.is-active {
|
||||
stroke: color-mix(in srgb, var(--color-warning) 40%, transparent);
|
||||
stroke: color-mix(in srgb, var(--draw-warning) 40%, transparent);
|
||||
}
|
||||
|
||||
.b06-chart__design-hit.b06-chart__rock-hit.is-active {
|
||||
@@ -134,21 +134,21 @@
|
||||
|
||||
/* 차도·노견 경계 짧은 수직 틱(N-4-2) — 설계선과 같은 계열, 얇게. */
|
||||
.b06-chart__carriageway-tick {
|
||||
stroke: var(--color-royal-amethyst);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
/* 노견 바깥 끝 틱(2026-09-12) — 차도 틱보다 짧고 옅다. 차도 틱과 이 틱 사이가 노견이라,
|
||||
노면이 넓어졌을 때 차도가 늘었는지 노견이 늘었는지 눈으로 바로 갈린다. */
|
||||
.b06-chart__shoulder-tick {
|
||||
stroke: var(--color-royal-amethyst);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
/* 노폭 라벨(2026-09-06) — 차도 위 가운데. 확폭이 걸린 측점을 눈으로 가려내는 표기다. */
|
||||
.b06-chart__carriageway-label {
|
||||
fill: var(--color-royal-amethyst);
|
||||
fill: var(--draw-accent);
|
||||
font-size: 11px;
|
||||
text-anchor: middle;
|
||||
pointer-events: none;
|
||||
@@ -157,7 +157,7 @@
|
||||
/* 암 경계선(설계선 복사 + 오프셋): 리핑암·발파암 구간 점선 */
|
||||
.b06-chart__rock-boundary {
|
||||
fill: none;
|
||||
stroke: var(--color-warning);
|
||||
stroke: var(--draw-warning);
|
||||
stroke-width: 1.6;
|
||||
stroke-dasharray: 6 4;
|
||||
stroke-linejoin: round;
|
||||
@@ -166,31 +166,31 @@
|
||||
|
||||
/* 포장층 박스: 노면 양 끝점 기준 두께만큼 하향 채움 */
|
||||
.b06-chart__pavement {
|
||||
fill: color-mix(in srgb, var(--color-text-secondary) 30%, transparent);
|
||||
stroke: var(--color-text-secondary);
|
||||
fill: color-mix(in srgb, var(--draw-text-secondary) 30%, transparent);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
/* 고른 노면공의 포장층(152-5) — 범위 카드마다 · 무늬 채움은 inline 이라 무늬 없는 층만 채움이 바뀌고 테두리로 강조 */
|
||||
.b06-chart__pavement.is-active {
|
||||
fill: color-mix(in srgb, var(--color-danger) 30%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 30%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2.2;
|
||||
}
|
||||
|
||||
/* 노면공 포장사양 무늬(88): 포장 박스 채움 = 바탕 + 무늬 — 콘크리트 빗금 · 아스콘 점 · 쇄석 돌 */
|
||||
.b06-chart__pave-bg {
|
||||
fill: color-mix(in srgb, var(--color-text-secondary) 30%, transparent);
|
||||
fill: color-mix(in srgb, var(--draw-text-secondary) 30%, transparent);
|
||||
}
|
||||
|
||||
.b06-chart__pave-mark {
|
||||
fill: none;
|
||||
stroke: color-mix(in srgb, var(--color-text-body) 70%, transparent);
|
||||
stroke: color-mix(in srgb, var(--draw-text-body) 70%, transparent);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.b06-chart__pave-mark--dot {
|
||||
fill: color-mix(in srgb, var(--color-text-body) 70%, transparent);
|
||||
fill: color-mix(in srgb, var(--draw-text-body) 70%, transparent);
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
@@ -214,13 +214,13 @@
|
||||
/* 물넘이포장(287-2 · 287-4): 노면공 포장층(노견까지) + 월류 높이 점선 */
|
||||
.b06-chart__ford-deck-plan {
|
||||
fill: none;
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 5 4;
|
||||
}
|
||||
|
||||
.b06-chart__ford-pavement {
|
||||
stroke: var(--color-text-body);
|
||||
stroke: var(--draw-text-body);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
@@ -303,14 +303,14 @@
|
||||
}
|
||||
|
||||
.b06-chart__culvert-revet.is-active {
|
||||
fill: color-mix(in srgb, var(--color-danger) 45%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 45%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2.2;
|
||||
}
|
||||
|
||||
/* 흙막이 · 옹벽 덮개(66-5) — 벽 안으로 지나가는 다른 선을 바탕색으로 가림. */
|
||||
.b06-chart__wall-cover {
|
||||
fill: var(--color-surface-raised);
|
||||
fill: var(--draw-surface-raised);
|
||||
stroke: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -333,15 +333,15 @@
|
||||
(2026-08-30 사용자: 선택해도 하이라이트가 없었다). 색은 기슭막이·집수정 강조와
|
||||
같은 계열이되, 면이 넓어 채도를 낮춘다. */
|
||||
.b06-chart__box-hit.is-active {
|
||||
fill: color-mix(in srgb, var(--color-danger) 16%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 16%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 1.6;
|
||||
stroke-dasharray: 4 3;
|
||||
}
|
||||
|
||||
.b06-chart__culvert-apron {
|
||||
fill: color-mix(in srgb, var(--color-text-secondary) 22%, transparent);
|
||||
stroke: var(--color-text-secondary);
|
||||
fill: color-mix(in srgb, var(--draw-text-secondary) 22%, transparent);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 3 2; /* 지반 아래 매설부 — 점선으로 구분 */
|
||||
}
|
||||
@@ -349,7 +349,7 @@
|
||||
.b06-chart__culvert-label {
|
||||
font-size: 9px;
|
||||
font-weight: var(--font-weight-medium);
|
||||
fill: var(--color-text-secondary);
|
||||
fill: var(--draw-text-secondary);
|
||||
}
|
||||
|
||||
/* 관 정보 글(관매설 · 세월교 · 267-1) — 노폭 라벨(`.b06-chart__carriageway-label`)과 같은 글 크기 */
|
||||
@@ -359,7 +359,7 @@
|
||||
|
||||
/* 유입 보호공 공간 확보 절토선 — 말단에서 표준단면 절토경사로 지반까지 */
|
||||
.b06-chart__culvert-cut {
|
||||
stroke: var(--color-warning);
|
||||
stroke: var(--draw-warning);
|
||||
stroke-width: 1.4;
|
||||
stroke-dasharray: 5 3;
|
||||
}
|
||||
@@ -374,7 +374,7 @@
|
||||
|
||||
/* 옹벽 물빼기 파이프 단면(73-2) — 두 줄 평행선 · 밝음 · 어두움 토큰을 따름. */
|
||||
.b06-chart__wall-drain line {
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
@@ -388,8 +388,8 @@
|
||||
|
||||
/* 집수정 선택 강조(2026-08-22 사용자) — 기슭막이와 같은 규칙. */
|
||||
.b06-chart__culvert-basin.is-active {
|
||||
fill: color-mix(in srgb, var(--color-danger) 45%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 45%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2.2;
|
||||
}
|
||||
|
||||
@@ -404,8 +404,8 @@
|
||||
|
||||
/* 도수로 · 돌붙임 띠 고름(152-4) — 관 고름과 같은 강조 · 판정면은 굵은 투명 테두리로 여유 */
|
||||
.b06-chart__culvert-pitching.is-active {
|
||||
fill: color-mix(in srgb, var(--color-danger) 30%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 30%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2.2;
|
||||
stroke-dasharray: none;
|
||||
}
|
||||
@@ -452,8 +452,8 @@
|
||||
/* 세월교 구체(2026-08-25) — 바닥판은 콘크리트. 측벽은 ㄴ형 집수정 형상을 그대로
|
||||
쓰므로 `.b06-chart__culvert-basin` 색을 공유한다. */
|
||||
.b06-chart__ford-slab {
|
||||
fill: color-mix(in srgb, var(--color-text-secondary) 30%, transparent);
|
||||
stroke: var(--color-text-secondary);
|
||||
fill: color-mix(in srgb, var(--draw-text-secondary) 30%, transparent);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1.2;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
@@ -461,15 +461,15 @@
|
||||
/* 세월교 본체(바닥판 · 관) 선택 강조(66-1) — 측벽 강조와 같은 색. */
|
||||
.b06-chart__ford-slab.is-active,
|
||||
.b06-chart__culvert-pipe.is-active {
|
||||
fill: color-mix(in srgb, var(--color-danger) 30%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 30%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2.2;
|
||||
}
|
||||
|
||||
/* BOX암거 내공(유로) — 면은 비우고 윤곽만. 물이 지나는 빈 공간이라 채우지 않는다. */
|
||||
.b06-chart__box-barrel {
|
||||
fill: none;
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
stroke-dasharray: 4 3;
|
||||
stroke-linejoin: round;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SVG 차트 색상은 테마 토큰만 사용한다. */
|
||||
.b06-chart__bg {
|
||||
fill: var(--color-surface-raised);
|
||||
fill: var(--draw-surface-raised);
|
||||
}
|
||||
|
||||
/* 세로 창을 변환으로 옮기는 겹(2026-09-04) — 세로로 눌리거나 늘어나도 선 굵기·점선 간격은
|
||||
@@ -10,19 +10,19 @@
|
||||
}
|
||||
|
||||
.b06-chart__grid {
|
||||
stroke: var(--color-border);
|
||||
stroke: var(--draw-grid);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.b06-chart__axis {
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.b06-chart__tick,
|
||||
.b06-chart__station-label,
|
||||
.b06-chart__axis-label {
|
||||
fill: var(--color-text-secondary);
|
||||
fill: var(--draw-text-secondary);
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
.b06-chart__station-label--mc {
|
||||
font-size: 12px;
|
||||
font-weight: var(--font-weight-bold);
|
||||
fill: var(--color-warning);
|
||||
fill: var(--draw-warning);
|
||||
}
|
||||
|
||||
.b06-station--mc {
|
||||
@@ -47,7 +47,7 @@
|
||||
/* 중심고 Y축 라벨(318-2) — 눈금과 같은 10px · 둥근 상자 · 축선 앞에서 멈춤 ·
|
||||
바탕 = 불투명 섞음(겹친 눈금 글을 위에서 가림 · 319-1) · 색 = 원지반선 · 설계선(379-3 · `--b06-tag` = _Cross_Areas.css) */
|
||||
.b06-chart__center-box {
|
||||
fill: color-mix(in srgb, var(--b06-tag) 14%, var(--color-surface-raised));
|
||||
fill: color-mix(in srgb, var(--b06-tag) 14%, var(--draw-surface-raised));
|
||||
stroke: var(--b06-tag);
|
||||
stroke-width: 1;
|
||||
}
|
||||
@@ -60,7 +60,7 @@
|
||||
/* 겹쳐 위 단으로 올린 측점 이름(407-4) — 선 · 지반선 위라 바탕색 테두리로 읽히게. */
|
||||
.b06-chart__station-label--lifted {
|
||||
paint-order: stroke;
|
||||
stroke: var(--color-surface-raised);
|
||||
stroke: var(--draw-surface-raised);
|
||||
stroke-width: 3px;
|
||||
stroke-linejoin: round;
|
||||
pointer-events: none;
|
||||
@@ -74,14 +74,14 @@
|
||||
}
|
||||
|
||||
.b06-chart__axis-label {
|
||||
fill: var(--color-text-body);
|
||||
fill: var(--draw-text-body);
|
||||
font-size: var(--text-caption);
|
||||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
|
||||
.b06-chart__profile {
|
||||
fill: none;
|
||||
stroke: var(--color-chart-0);
|
||||
stroke: var(--draw-chart-0);
|
||||
stroke-width: 2.5;
|
||||
}
|
||||
|
||||
@@ -93,14 +93,14 @@
|
||||
|
||||
.b06-chart__cross-profile {
|
||||
fill: none;
|
||||
stroke: var(--color-chart-1);
|
||||
stroke: var(--draw-chart-1);
|
||||
stroke-width: 2.4;
|
||||
}
|
||||
|
||||
/* 종단 계획선(시공계획고): 지반선과 구분되도록 파선 + 강조색 */
|
||||
.b06-chart__design-profile {
|
||||
fill: none;
|
||||
stroke: var(--color-royal-amethyst);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 2.2;
|
||||
stroke-dasharray: 8 4;
|
||||
}
|
||||
@@ -119,7 +119,7 @@
|
||||
}
|
||||
|
||||
.b06-chart__balance-boundary {
|
||||
stroke: var(--color-royal-amethyst);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1.2;
|
||||
stroke-dasharray: 3 3;
|
||||
opacity: 0.55;
|
||||
@@ -148,42 +148,42 @@
|
||||
.b06-chart__station-line--bp,
|
||||
.b06-chart__station-line--regular,
|
||||
.b06-chart__station-line--curve {
|
||||
stroke: var(--color-warning);
|
||||
stroke: var(--draw-warning);
|
||||
}
|
||||
|
||||
.b06-chart__station-line--ep {
|
||||
stroke: var(--color-accent);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-dasharray: 4 3;
|
||||
}
|
||||
|
||||
/* 비정규 측점(구조물)은 종단면도에서도 자수정색 파선으로 구분한다(B05 종단 규칙과 정합).
|
||||
미선택 시 stroke 미정의로 세로선이 안 그려지던 문제 해소. */
|
||||
.b06-chart__station-line--irregular {
|
||||
stroke: var(--color-royal-amethyst, rgb(139 92 246));
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 1.4;
|
||||
stroke-dasharray: 5 3;
|
||||
}
|
||||
|
||||
/* 추가 측점(368-3) = 일반측점 색 점선 */
|
||||
.b06-chart__station-line--plus {
|
||||
stroke: var(--color-warning);
|
||||
stroke: var(--draw-warning);
|
||||
stroke-dasharray: 5 3;
|
||||
}
|
||||
|
||||
.b06-chart__station-line--selected,
|
||||
.b06-chart__center-marker {
|
||||
stroke: var(--color-danger);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2.5;
|
||||
}
|
||||
|
||||
/* 십자선이 계획 노선(계획고) 위치를 가리킬 때: 종단 계획선과 동일 색으로 대응시킨다 */
|
||||
.b06-chart__center-marker--design {
|
||||
stroke: var(--color-royal-amethyst);
|
||||
stroke: var(--draw-accent);
|
||||
}
|
||||
|
||||
.b06-chart__station--selected .b06-chart__station-label,
|
||||
.b06-chart__station-label--selected {
|
||||
fill: var(--color-danger);
|
||||
fill: var(--draw-danger);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
.b06-detail__pick-outline path {
|
||||
fill: none;
|
||||
stroke: var(--color-danger);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2;
|
||||
stroke-linecap: square;
|
||||
}
|
||||
@@ -144,19 +144,19 @@
|
||||
|
||||
/* 그림 강조 한 벌 = 붉은 계통(164-2 · 카드 색은 그대로) — 띠 · 판정 선 · 중심 십자 · 사토장 */
|
||||
.b06-detail__cad .b06-chart__area.is-active > polygon {
|
||||
fill: color-mix(in srgb, var(--color-danger) 35%, transparent);
|
||||
stroke: var(--color-danger);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 35%, transparent);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.b06-detail__cad .b06-chart__design-hit.is-active {
|
||||
stroke: color-mix(in srgb, var(--color-danger) 70%, transparent);
|
||||
stroke: color-mix(in srgb, var(--draw-danger) 70%, transparent);
|
||||
stroke-width: 9;
|
||||
}
|
||||
|
||||
.b06-detail__cad .b06-chart__ground-center.is-active line,
|
||||
.b06-detail__cad .b06-chart__center.is-active line {
|
||||
stroke: var(--color-danger);
|
||||
stroke: var(--draw-danger);
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
@@ -206,11 +206,11 @@
|
||||
/* 구조물 선 묶음(295-3) — 나뉜 조각 위 한 줄 · 걸치면 선 하나로 비침 */
|
||||
.b06-detail__piece:hover,
|
||||
.b06-detail__piece-group:hover {
|
||||
stroke: color-mix(in srgb, var(--color-accent) 25%, transparent);
|
||||
stroke: color-mix(in srgb, var(--draw-accent) 25%, transparent);
|
||||
}
|
||||
|
||||
.b06-detail__piece.is-selected {
|
||||
stroke: color-mix(in srgb, var(--color-danger) 55%, transparent);
|
||||
stroke: color-mix(in srgb, var(--draw-danger) 55%, transparent);
|
||||
stroke-width: 6;
|
||||
}
|
||||
|
||||
@@ -223,11 +223,11 @@
|
||||
}
|
||||
|
||||
.b06-detail__face:hover {
|
||||
fill: color-mix(in srgb, var(--color-accent) 8%, transparent);
|
||||
fill: color-mix(in srgb, var(--draw-accent) 8%, transparent);
|
||||
}
|
||||
|
||||
.b06-detail__face.is-selected {
|
||||
fill: color-mix(in srgb, var(--color-danger) 22%, transparent);
|
||||
fill: color-mix(in srgb, var(--draw-danger) 22%, transparent);
|
||||
}
|
||||
|
||||
/* 고른 것 값(카드 179-1 꼴) · [칸에 넣기] — [+ − ⤢] 왼쪽 */
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
--cad-text-muted: var(--color-text-muted);
|
||||
--cad-accent: var(--color-accent);
|
||||
--cad-hover: var(--color-mist-violet);
|
||||
--cad-canvas: var(--color-canvas);
|
||||
--cad-canvas: var(--draw-canvas);
|
||||
}
|
||||
|
||||
* {
|
||||
|
||||
@@ -339,7 +339,7 @@ export class ScreenCanvasDrawController implements DrawController {
|
||||
this.context.fillStyle = themeColor('--cad-canvas', CANVAS_BACKGROUND_FALLBACK);
|
||||
this.context.fillRect(0, 0, this.canvasSize?.x, this.canvasSize?.y);
|
||||
if (getGridEnabled()) {
|
||||
this.context.strokeStyle = themeColor('--color-mist', '#242b35');
|
||||
this.context.strokeStyle = themeColor('--draw-grid', '#242b35');
|
||||
this.context.lineWidth = 1;
|
||||
this.context.setLineDash([]);
|
||||
this.context.beginPath();
|
||||
|
||||
@@ -179,22 +179,22 @@
|
||||
|
||||
.b08-hydro__pipe text {
|
||||
font-size: var(--text-caption);
|
||||
fill: var(--color-text-secondary);
|
||||
fill: var(--draw-text-secondary);
|
||||
}
|
||||
|
||||
.b08-hydro__water {
|
||||
fill: color-mix(in srgb, var(--color-chart-0) 30%, transparent);
|
||||
fill: color-mix(in srgb, var(--draw-chart-0) 30%, transparent);
|
||||
}
|
||||
|
||||
.b08-hydro__wall {
|
||||
fill: none;
|
||||
stroke: var(--color-text-body);
|
||||
stroke: var(--draw-text-body);
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.b08-hydro__line {
|
||||
fill: none;
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,41 +81,41 @@
|
||||
}
|
||||
|
||||
.b08-milestone__line {
|
||||
stroke: var(--color-text-secondary);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
|
||||
.b08-milestone__box rect {
|
||||
fill: var(--color-surface);
|
||||
stroke: var(--color-text-secondary);
|
||||
fill: var(--draw-surface);
|
||||
stroke: var(--draw-text-secondary);
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
.b08-milestone__box text {
|
||||
fill: var(--color-text);
|
||||
fill: var(--draw-text);
|
||||
}
|
||||
|
||||
/* 153 상자 색 — 공사지(시점 · 중점) = 강조색 · 기준점 = 경고색 · 거래처 = 성공색 · 옅은 채움 + 테두리(테마 변수 · 밝음 · 어두움 같이) */
|
||||
.b08-milestone__box.is-site rect {
|
||||
fill: color-mix(in srgb, var(--color-accent) 7%, var(--color-surface));
|
||||
stroke: var(--color-accent);
|
||||
fill: color-mix(in srgb, var(--draw-accent) 7%, var(--draw-surface));
|
||||
stroke: var(--draw-accent);
|
||||
stroke-dasharray: 4 3;
|
||||
}
|
||||
|
||||
.b08-milestone__box.is-start rect,
|
||||
.b08-milestone__box.is-mid rect {
|
||||
fill: color-mix(in srgb, var(--color-accent) 16%, var(--color-surface));
|
||||
stroke: var(--color-accent);
|
||||
fill: color-mix(in srgb, var(--draw-accent) 16%, var(--draw-surface));
|
||||
stroke: var(--draw-accent);
|
||||
}
|
||||
|
||||
.b08-milestone__box.is-base rect {
|
||||
fill: color-mix(in srgb, var(--color-warning) 18%, var(--color-surface));
|
||||
stroke: var(--color-warning);
|
||||
fill: color-mix(in srgb, var(--draw-warning) 18%, var(--draw-surface));
|
||||
stroke: var(--draw-warning);
|
||||
}
|
||||
|
||||
.b08-milestone__box.is-route rect {
|
||||
fill: color-mix(in srgb, var(--color-success) 14%, var(--color-surface));
|
||||
stroke: var(--color-success);
|
||||
fill: color-mix(in srgb, var(--draw-success) 14%, var(--draw-surface));
|
||||
stroke: var(--draw-success);
|
||||
}
|
||||
|
||||
.b08-milestone__box.is-route,
|
||||
@@ -125,15 +125,15 @@
|
||||
|
||||
.b08-milestone__box.is-route:hover rect,
|
||||
.b08-milestone__box.is-route:focus-visible rect {
|
||||
stroke: var(--color-accent);
|
||||
stroke: var(--draw-accent);
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.b08-milestone__km {
|
||||
fill: var(--color-text);
|
||||
fill: var(--draw-text);
|
||||
font-size: 12px;
|
||||
paint-order: stroke;
|
||||
stroke: var(--color-surface);
|
||||
stroke: var(--draw-surface);
|
||||
stroke-width: 4px;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
@@ -173,13 +173,13 @@
|
||||
|
||||
/* 거래처 상자 윗줄 = 항목(244-6) · 글 크기 = 거래처 이름(254) */
|
||||
.b08-milestone__items {
|
||||
fill: var(--color-text-secondary);
|
||||
fill: var(--draw-text-secondary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 상자 작은 글씨 = 주소 · 좌표(244-12) */
|
||||
.b08-milestone__note {
|
||||
fill: var(--color-text-secondary);
|
||||
fill: var(--draw-text-secondary);
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
@@ -228,8 +228,8 @@
|
||||
|
||||
/* 154 연결 점 ● — 거래처 · 기준점 상자 왼쪽 위 안쪽(254) · 끌어 기준점 · 공사지에 놓으면 연결 */
|
||||
.b08-milestone__connect {
|
||||
fill: var(--color-success);
|
||||
stroke: var(--color-surface);
|
||||
fill: var(--draw-success);
|
||||
stroke: var(--draw-surface);
|
||||
stroke-width: 2;
|
||||
cursor: crosshair;
|
||||
opacity: 0.85;
|
||||
@@ -240,7 +240,7 @@
|
||||
}
|
||||
|
||||
.b08-milestone__wire {
|
||||
stroke: var(--color-success);
|
||||
stroke: var(--draw-success);
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: 6 4;
|
||||
pointer-events: none;
|
||||
|
||||
@@ -248,7 +248,7 @@ export function createPlanMap(events: PlanMapEvents): PlanMap {
|
||||
context.beginPath();
|
||||
context.arc(at[0], at[1], 7, 0, Math.PI * 2);
|
||||
context.lineWidth = 2.5;
|
||||
context.strokeStyle = themeColor("--color-primary", "#6d28d9");
|
||||
context.strokeStyle = themeColor("--draw-primary", "#6d28d9");
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,9 +105,9 @@ def test_모달_배선_단추_칸_비율():
|
||||
def test_강조_붉은_한_벌_고름_hover_다름_빈칸():
|
||||
css = _read("B06_Section_UI_Style_Cross_Detail.css")
|
||||
for selector in (
|
||||
".b06-detail__cad .b06-chart__area.is-active > polygon {\n fill: color-mix(in srgb, var(--color-danger)",
|
||||
".b06-detail__cad .b06-chart__design-hit.is-active {\n stroke: color-mix(in srgb, var(--color-danger)",
|
||||
".b06-detail__cad .b06-chart__ground-center.is-active line,\n.b06-detail__cad .b06-chart__center.is-active line {\n stroke: var(--color-danger);",
|
||||
".b06-detail__cad .b06-chart__area.is-active > polygon {\n fill: color-mix(in srgb, var(--draw-danger)",
|
||||
".b06-detail__cad .b06-chart__design-hit.is-active {\n stroke: color-mix(in srgb, var(--draw-danger)",
|
||||
".b06-detail__cad .b06-chart__ground-center.is-active line,\n.b06-detail__cad .b06-chart__center.is-active line {\n stroke: var(--draw-danger);",
|
||||
".b06-detail__qtable .is-picked {\n background: color-mix(in srgb, var(--color-danger) 18%",
|
||||
".b06-detail__qtable [data-key][data-empty] {\n cursor: default;",
|
||||
):
|
||||
|
||||
@@ -180,14 +180,14 @@ def _css_rule(css: str, selector: str) -> str:
|
||||
|
||||
|
||||
def test_자유지정_녹색_넘음_빨강_띠_보라():
|
||||
# 367-4 선 · 미리 보기 · 점 = --color-success · 넘음 빨강 · 범위 띠 · 경계 보라 그대로
|
||||
# 367-4 선 · 미리 보기 · 점 = --draw-success · 넘음 빨강 · 범위 띠 · 경계 보라 그대로
|
||||
css = _read("B05_Profile/B05_Profile_UI_Style_Table.css")
|
||||
assert "stroke: var(--color-success);" in _css_rule(css, ".b05-profile-freemark__line")
|
||||
assert "stroke: var(--color-success);" in _css_rule(css, ".b05-profile-freemark__dot")
|
||||
assert "var(--color-danger" in _css_rule(css, ".b05-profile-freemark__line.is-over")
|
||||
assert "var(--color-danger" in _css_rule(css, ".b05-profile-freemark__grade.is-over")
|
||||
assert "--color-primary" in _css_rule(css, ".b05-profile-freemark__band")
|
||||
assert "--color-primary" in _css_rule(css, ".b05-profile-freemark__edge")
|
||||
assert "stroke: var(--draw-success);" in _css_rule(css, ".b05-profile-freemark__line")
|
||||
assert "stroke: var(--draw-success);" in _css_rule(css, ".b05-profile-freemark__dot")
|
||||
assert "var(--draw-danger" in _css_rule(css, ".b05-profile-freemark__line.is-over")
|
||||
assert "var(--draw-danger" in _css_rule(css, ".b05-profile-freemark__grade.is-over")
|
||||
assert "--draw-primary" in _css_rule(css, ".b05-profile-freemark__band")
|
||||
assert "--draw-primary" in _css_rule(css, ".b05-profile-freemark__edge")
|
||||
# 밝음 · 어두움(명시 · OS 자동) 모두 success · danger 토큰 있음
|
||||
theme = _read("ui_template/ui_template_theme.css")
|
||||
auto = theme[theme.index("@media (prefers-color-scheme: dark)") :]
|
||||
|
||||
@@ -84,9 +84,9 @@ def test_153_지도_보기_유지_상자_색_끌어_옮김():
|
||||
) # 처음 한 번만 맞춤 · 그 뒤 줌 그대로
|
||||
css = _read("B08_Quantity/B08_Quantity_UI_Milestone.css")
|
||||
for kind, var in (
|
||||
("is-site", "--color-accent"),
|
||||
("is-base", "--color-warning"),
|
||||
("is-route", "--color-success"),
|
||||
("is-site", "--draw-accent"),
|
||||
("is-base", "--draw-warning"),
|
||||
("is-route", "--draw-success"),
|
||||
):
|
||||
block = css[css.index(f".b08-milestone__box.{kind} rect {{") :]
|
||||
assert var in block[: block.index("}")], kind
|
||||
|
||||
@@ -186,7 +186,7 @@ def test_배선():
|
||||
css = _read("B05_Profile/B05_Profile_UI_Style_Table.css")
|
||||
rule = css[css.index(".b05-profile-freemark__span {") :]
|
||||
rule = rule[: rule.index("}")]
|
||||
assert "--color-primary" in rule and "--color-surface" in rule # 밝음 · 어두움 토큰
|
||||
assert "--draw-primary" in rule and "--draw-surface" in rule # 밝음 · 어두움 토큰
|
||||
|
||||
|
||||
def test_줄_수():
|
||||
|
||||
@@ -159,7 +159,7 @@ def test_two_crosshairs(result: dict) -> None:
|
||||
assert cross["design_only_ground"] is None # 설계 없음 = 십자 하나(지반 폴백)
|
||||
assert cross["scaled"] == cross["want_scaled"] # 둘 다 자기 중심에서 배율 되돌림
|
||||
areas = _src("B06_Section", "B06_Section_UI_Style_Cross_Areas.css")
|
||||
assert "var(--color-chart-1)" in _rule(areas, ".b06-chart__ground-center-marker")
|
||||
assert "var(--draw-chart-1)" in _rule(areas, ".b06-chart__ground-center-marker")
|
||||
|
||||
|
||||
def test_draft_detail_profile_is_draft(result: dict) -> None:
|
||||
@@ -192,8 +192,8 @@ def test_css_layout() -> None:
|
||||
box = _rule(css, ".b06-chart__center-box")
|
||||
assert "var(--b06-tag)" in box # 색 = 갈래 변수(379-3)
|
||||
areas = _src("B06_Section", "B06_Section_UI_Style_Cross_Areas.css")
|
||||
assert "var(--color-chart-1)" in _rule(areas, ".b06-chart__center-tag--ground") # 원지반선
|
||||
assert "var(--color-royal-amethyst)" in _rule(areas, ".b06-chart__center-tag--design") # 설계선
|
||||
assert "var(--draw-chart-1)" in _rule(areas, ".b06-chart__center-tag--ground") # 원지반선
|
||||
assert "var(--draw-accent)" in _rule(areas, ".b06-chart__center-tag--design") # 설계선
|
||||
assert "font-size" not in _rule(css, ".b06-chart__center-text") # 글자 크기 = 눈금 그대로
|
||||
|
||||
|
||||
|
||||
@@ -65,11 +65,17 @@ def test_b08_b09_earthwork_station_mc() -> None:
|
||||
|
||||
|
||||
def test_b05_b06_screen_mc_emphasis() -> None:
|
||||
css = _src("B06_Section/B06_Section_UI_Style_Cross.css") + _src("B06_Section/B06_Section_UI_Style_Cross_Chart.css")
|
||||
css = _src("B06_Section/B06_Section_UI_Style_Cross.css") + _src(
|
||||
"B06_Section/B06_Section_UI_Style_Cross_Chart.css"
|
||||
)
|
||||
assert "header strong.b06-station--mc {" in css # 카드 머리 strong 규칙을 이김
|
||||
for rule in ("\n.b06-chart__station-label--mc {", "\n.b06-station--mc {"):
|
||||
# 그림 글 = 그림 전용 값(551-2) · 카드 머리 글 = 화면 경고색
|
||||
for rule, warn in (
|
||||
("\n.b06-chart__station-label--mc {", "var(--draw-warning)"),
|
||||
("\n.b06-station--mc {", "var(--color-warning)"),
|
||||
):
|
||||
body = css[css.index(rule) : css.index("}", css.index(rule))]
|
||||
assert "var(--color-warning)" in body
|
||||
assert warn in body
|
||||
assert "var(--font-weight-bold)" in body
|
||||
# 고름 빨강이 MC 색을 이김 — 뒤에 섬
|
||||
assert css.index(".b06-chart__station-label--mc {") < css.index(
|
||||
@@ -84,7 +90,7 @@ def test_b05_b06_screen_mc_emphasis() -> None:
|
||||
assert '${mc ? " b06-station--mc" : ""}' in cross
|
||||
ticks = _src("B04_PreProcess/B04_PreProcess_UI_MapOverlays.ts")
|
||||
assert 'mc ? "bold 13px' in ticks
|
||||
assert 'themeColor("--color-warning"' in ticks
|
||||
assert 'themeColor("--draw-warning"' in ticks
|
||||
swap = _src("B06_Section/logic/B06_Section_Station_Swap.ts")
|
||||
assert 'formatStation(station.chainageM) + (kind === "curve" ? " (MC)" : "")' in swap
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
"""551-2 그림 전용 값(--draw-*) 지킴 — 화면 테마 변수(--color-*)를 바꿔도 그림 색은 그대로.
|
||||
|
||||
- `ui_template_theme.css` 끝 블록의 --draw-* 는 밝음 · 어두움 · 시스템 어두움 모두 글자 hex.
|
||||
- 그림 CSS(B05 · B06 · B08 SVG)의 stroke · fill 은 --color-* 를 쓰지 않음.
|
||||
- 지도 · 3D · CAD 캔버스가 읽는 바탕 · 선 색은 --draw-*.
|
||||
- 옛 변수 값을 일부러 바꿔도 그림 선언의 풀린 색이 같음(밝음 · 어두움 · 시스템 어두움).
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
THEME = ROOT / "ui_template" / "ui_template_theme.css"
|
||||
|
||||
DRAW_CSS = [
|
||||
"B05_Profile/B05_Profile_UI_Style.css",
|
||||
"B05_Profile/B05_Profile_UI_Style_RouteEdit.css",
|
||||
"B05_Profile/B05_Profile_UI_Style_RouteRecommend.css",
|
||||
"B05_Profile/B05_Profile_UI_Style_Table.css",
|
||||
"B06_Section/B06_Section_UI_Style.css",
|
||||
"B06_Section/B06_Section_UI_Style_Cross_Areas.css",
|
||||
"B06_Section/B06_Section_UI_Style_Cross_Chart.css",
|
||||
"B06_Section/B06_Section_UI_Style_Cross_Detail.css",
|
||||
"B08_Quantity/B08_Quantity_UI_Hydro.css",
|
||||
"B08_Quantity/B08_Quantity_UI_Milestone.css",
|
||||
]
|
||||
|
||||
# 캔버스 · 3D 가 읽는 그림 색 — (파일, 꼭 있어야 할 글)
|
||||
DRAW_READS = [
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_Render.ts", '"--draw-surface"'),
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_Render.ts", '"--draw-text-secondary"'),
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_Render.ts", '"--draw-danger"'),
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_Recommend_Map.ts", '"--draw-primary"'),
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_Recommend_Map.ts", '"--draw-text-secondary"'),
|
||||
("B05_Profile/B05_Profile_UI_Viewer.ts", '"--draw-surface-raised"'),
|
||||
("B04_PreProcess/B04_PreProcess_UI_Camera.ts", '"--draw-surface-raised"'),
|
||||
("D03_PlanAnalysis/D03_PlanAnalysis_UI_Map.ts", '"--draw-primary"'),
|
||||
("B04_PreProcess/B04_PreProcess_UI_MapOverlays.ts", '"--draw-warning"'),
|
||||
("B04_PreProcess/B04_PreProcess_UI_MapOverlays.ts", '"--draw-canvas"'),
|
||||
("B07_DesignDetail/openwebcad/src/App.css", "--cad-canvas: var(--draw-canvas);"),
|
||||
(
|
||||
"B07_DesignDetail/openwebcad/src/drawControllers/screenCanvas.drawController.ts",
|
||||
"themeColor('--draw-grid'",
|
||||
),
|
||||
]
|
||||
NO_COLOR_READS = [
|
||||
"B05_Profile/B05_Profile_UI_RouteEdit_Render.ts",
|
||||
"B05_Profile/B05_Profile_UI_RouteEdit_Recommend_Map.ts",
|
||||
"B05_Profile/B05_Profile_UI_Viewer.ts",
|
||||
"B07_DesignDetail/openwebcad/src/drawControllers/screenCanvas.drawController.ts",
|
||||
]
|
||||
|
||||
DECL = re.compile(r"^\s*(stroke|fill|stop-color|--b06-tag)\s*:(.*);", re.M)
|
||||
VAR = re.compile(r"var\((--[a-z0-9-]+)(?:\s*,\s*([^()]*(?:\([^()]*\))?[^()]*))?\)")
|
||||
HEX = re.compile(r"#[0-9a-f]{6}")
|
||||
|
||||
|
||||
def _blocks(css: str) -> dict[str, dict[str, str]]:
|
||||
"""밝음 · 어두움 · 시스템 어두움 블록의 --변수 정의(뒤 블록이 앞을 덮음)."""
|
||||
css = re.sub(r"/\*.*?\*/", "", css, flags=re.S)
|
||||
out: dict[str, dict[str, str]] = {"light": {}, "dark": {}, "auto": {}}
|
||||
|
||||
def walk(text: str, media: bool) -> None:
|
||||
i = 0
|
||||
while True:
|
||||
open_at = text.find("{", i)
|
||||
if open_at < 0:
|
||||
return
|
||||
head = text[i:open_at].strip().split("}")[-1].strip()
|
||||
depth, j = 1, open_at + 1
|
||||
while depth:
|
||||
depth += {"{": 1, "}": -1}.get(text[j], 0)
|
||||
j += 1
|
||||
body = text[open_at + 1 : j - 1]
|
||||
if head.startswith("@media (prefers-color-scheme: dark)"):
|
||||
walk(body, True)
|
||||
else:
|
||||
mode = None
|
||||
if head == ":root":
|
||||
mode = "light"
|
||||
elif head == ':root[data-theme="dark"]':
|
||||
mode = "dark"
|
||||
elif media and head == ':root:not([data-theme="light"])':
|
||||
mode = "auto"
|
||||
if mode:
|
||||
for name, value in re.findall(r"(--[a-z0-9-]+)\s*:([^;]*);", body):
|
||||
out[mode][name] = " ".join(value.split())
|
||||
i = j
|
||||
|
||||
walk(css, False)
|
||||
return out
|
||||
|
||||
|
||||
def _modes(css: str) -> dict[str, dict[str, str]]:
|
||||
b = _blocks(css)
|
||||
return {
|
||||
"light": b["light"],
|
||||
"dark": {**b["light"], **b["dark"]},
|
||||
"auto": {**b["light"], **b["auto"]},
|
||||
}
|
||||
|
||||
|
||||
def resolve(value: str, env: dict[str, str]) -> str:
|
||||
for _ in range(10):
|
||||
new = VAR.sub(lambda m: env.get(m.group(1), (m.group(2) or "").strip()), value)
|
||||
if new == value:
|
||||
break
|
||||
value = new
|
||||
return " ".join(value.split()).lower()
|
||||
|
||||
|
||||
def draw_decls() -> list[tuple[str, str]]:
|
||||
out = []
|
||||
for rel in DRAW_CSS:
|
||||
text = re.sub(r"/\*.*?\*/", "", (ROOT / rel).read_text(encoding="utf-8"), flags=re.S)
|
||||
out += [(rel, m.group(2).strip()) for m in DECL.finditer(text)]
|
||||
return out
|
||||
|
||||
|
||||
def test_draw_values_are_literal_hex():
|
||||
blocks = _blocks(THEME.read_text(encoding="utf-8"))
|
||||
for mode, env in blocks.items():
|
||||
draws = {k: v for k, v in env.items() if k.startswith("--draw-")}
|
||||
assert draws, mode
|
||||
for name, value in draws.items():
|
||||
assert HEX.fullmatch(value), (mode, name, value)
|
||||
assert len([k for k in blocks["light"] if k.startswith("--draw-")]) == 17
|
||||
|
||||
|
||||
def test_drawing_css_uses_no_screen_tokens():
|
||||
decls = draw_decls()
|
||||
assert len(decls) > 100
|
||||
bad = [(rel, v) for rel, v in decls if "var(--color-" in v]
|
||||
assert not bad, bad
|
||||
|
||||
|
||||
def test_canvas_and_3d_read_draw_tokens():
|
||||
for rel, needle in DRAW_READS:
|
||||
assert needle in (ROOT / rel).read_text(encoding="utf-8"), (rel, needle)
|
||||
for rel in NO_COLOR_READS:
|
||||
text = (ROOT / rel).read_text(encoding="utf-8")
|
||||
assert not re.search(r"""(getPropertyValue|themeColor)\(\s*["']--color-""", text), rel
|
||||
|
||||
|
||||
def test_changing_screen_tokens_keeps_drawing_colors():
|
||||
css = THEME.read_text(encoding="utf-8")
|
||||
# 옛 화면 변수를 모두 초록으로 바꾼 판 — sub1 이 테마를 갈아도 그림이 안 따라가는지
|
||||
swapped = re.sub(r"(--color-[a-z0-9-]+\s*:)[^;]*;", r"\1 #00ff00;", css)
|
||||
before, after = _modes(css), _modes(swapped)
|
||||
decls = draw_decls()
|
||||
for mode in ("light", "dark", "auto"):
|
||||
for rel, value in decls:
|
||||
a = resolve(value, before[mode])
|
||||
assert "var(" not in a, (mode, rel, value)
|
||||
assert a == resolve(value, after[mode]), (mode, rel, value)
|
||||
@@ -132,4 +132,4 @@ def test_옹벽_표식은_구조물_종류로() -> None:
|
||||
"retaining_wall"
|
||||
]
|
||||
css = (B06 / "B06_Section_UI_Style_Cross_Areas.css").read_text(encoding="utf-8")
|
||||
assert re.search(r"\.b06-chart__wall-drain line \{[^}]*var\(--color-", css), "색 토큰 없음"
|
||||
assert re.search(r"\.b06-chart__wall-drain line \{[^}]*var\(--draw-", css), "색 토큰 없음"
|
||||
|
||||
@@ -562,3 +562,61 @@ html.is-bm-route .m01lab-src__body * {
|
||||
user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
/* =============================================================================
|
||||
* 551-2 그림 전용 값 — 화면 테마와 따로 · 지금 색 고정
|
||||
* 종단 · 횡단 · 이정표 SVG 선 · 지도 계획선 · CAD 바탕 · 3D 바탕은 --draw-* 만 씀.
|
||||
* 값은 글자 hex 로 박음(--color-* 를 가리키지 않음) — 화면 테마가 바뀌어도 그림 색은 그대로.
|
||||
* ========================================================================== */
|
||||
:root {
|
||||
--draw-accent: #3e0079; /* 설계선 · EP 선 · 이정표 강조 */
|
||||
--draw-primary: #26114a; /* 자유 표시 · 노선 추천 계획선 */
|
||||
--draw-chart-0: #5b8def; /* 원지반선 · 성토 */
|
||||
--draw-chart-1: #34c38f; /* 횡단 원지반선 */
|
||||
--draw-chart-2: #f1963b; /* 토사 깎기 */
|
||||
--draw-chart-3: #9b6dde; /* 발파암 깎기 */
|
||||
--draw-success: #1f8a4c;
|
||||
--draw-warning: #b8860b;
|
||||
--draw-danger: #c0392b;
|
||||
--draw-text: #26114a;
|
||||
--draw-text-body: #333333;
|
||||
--draw-text-secondary: #615e6e;
|
||||
--draw-text-muted: #9491a1;
|
||||
--draw-grid: #e6e2e3; /* 눈금 · CAD 격자 */
|
||||
--draw-surface: #f6f7fa;
|
||||
--draw-surface-raised: #ffffff; /* 그림 바탕 · 3D 바탕 */
|
||||
--draw-canvas: #ffffff; /* CAD 바탕 */
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--draw-accent: #b99aff;
|
||||
--draw-primary: #b99aff;
|
||||
--draw-success: #3fbb6f;
|
||||
--draw-warning: #e0b64a;
|
||||
--draw-danger: #e8695a;
|
||||
--draw-text: #d8ccff;
|
||||
--draw-text-body: #e4e0f0;
|
||||
--draw-text-secondary: #b3aec6;
|
||||
--draw-text-muted: #8b86a0;
|
||||
--draw-grid: #322a45;
|
||||
--draw-surface: #1e1930;
|
||||
--draw-surface-raised: #251f38;
|
||||
--draw-canvas: #16121f;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
--draw-accent: #b99aff;
|
||||
--draw-primary: #b99aff;
|
||||
--draw-success: #3fbb6f;
|
||||
--draw-danger: #e8695a;
|
||||
--draw-text: #d8ccff;
|
||||
--draw-text-body: #e4e0f0;
|
||||
--draw-text-secondary: #b3aec6;
|
||||
--draw-text-muted: #8b86a0;
|
||||
--draw-grid: #322a45;
|
||||
--draw-surface: #1e1930;
|
||||
--draw-surface-raised: #251f38;
|
||||
--draw-canvas: #16121f;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user