diff --git a/src/main.ts b/src/main.ts
index 01ca98b..12cd3ce 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -966,6 +966,34 @@ function fillAbutBearingCard(
box.append(el('p', `검사 · ${abutBearingChecks(model, members, rule, H).join(' · ')}`, 'muted small abut-checks'));
}
+/**
+ * 날개벽 타일 그림 (2026-11-04, 48 × 24, 선 색 = 글자 색). 평면 그림은 위가 흉벽 · 벽체, 아래로 날개벽이 뻗는다.
+ * 날개벽 모양은 현재 형식을 따른다: 일반형 = 길게, 단축형 = 짧게(뒷굽 끝까지), 없음 = 흐린 점선.
+ */
+const WING_ICON = {
+ plan(left: WingForm, right: WingForm, focus?: 'left' | 'right', equal = false): string {
+ const stroke = (on: boolean) => (on ? 'stroke="currentColor" stroke-width="2.6"' : 'stroke="currentColor" stroke-width="1.6" stroke-dasharray="2 2" opacity="0.45"');
+ const wing = (side: 'left' | 'right', form: WingForm) => {
+ const x = side === 'left' ? 10 : 38;
+ const dx = side === 'left' ? -1 : 1;
+ const on = form !== 'none' && (focus === undefined || focus === side);
+ const len = form === 'general' ? 12 : 5;
+ const style = form === 'none' ? stroke(false) : stroke(on);
+ return ``;
+ };
+ const wall = '';
+ const eq = equal ? '' : '';
+ return wall + wing('left', left) + wing('right', right) + eq;
+ },
+ side(form: WingForm): string {
+ const solid = 'fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"';
+ const faint = 'fill="none" stroke="currentColor" stroke-width="1.3" stroke-dasharray="2 2" opacity="0.45"';
+ if (form === 'general') return ``;
+ if (form === 'short') return ``;
+ return ``;
+ },
+};
+
/** skew (deg) as 95°02′52″. */
function dms(deg: number): string {
const total = Math.round(Math.abs(deg) * 3600);
@@ -993,13 +1021,21 @@ function fillAbutWingCard(
const sideName = (s: 'left' | 'right') => (s === 'left' ? '좌 · ① 쪽' : `우 · ${circled(lastNo)} 쪽`);
box.append(
optionTiles('좌우', [
- { label: '좌우 같게', on: linked, isDefault: true, pick: () => apply(setWingsLinked(rec, true)) },
- { label: '따로 정하기', on: !linked, pick: () => apply(setWingsLinked(rec, false)) },
+ // 같게: the left form on both sides with "="; 따로: the current forms, or long / short when they happen to match.
+ { label: '좌우 같게', icon: WING_ICON.plan(forms.left, forms.left, undefined, true), on: linked, isDefault: true, pick: () => apply(setWingsLinked(rec, true)) },
+ {
+ label: '따로 정하기',
+ icon: forms.left === forms.right ? WING_ICON.plan('general', 'short') : WING_ICON.plan(forms.left, forms.right),
+ on: !linked,
+ pick: () => apply(setWingsLinked(rec, false)),
+ },
]),
optionTiles(
'편집할 측',
(['left', 'right'] as const).map((s) => ({
- label: `${sideName(s)} · ${NAME[forms[s]]}`,
+ // The picture shows both wings in their current form, with this side drawn bold.
+ label: sideName(s),
+ icon: WING_ICON.plan(forms.left, forms.right, s),
on: side === s,
pick: () => {
state.abutWingSide = s;
@@ -1012,6 +1048,7 @@ function fillAbutWingCard(
`${side === 'left' ? '좌' : '우'} 날개벽 (${sideName(side).split(' · ')[1]}) 형식`,
(['general', 'short', 'none'] as const).map((f) => ({
label: NAME[f],
+ icon: WING_ICON.side(f),
on: forms[side] === f,
isDefault: f === 'general',
pick: () => apply(setWingForm(rec, side, f)),