untracked files on main: dceb101 feat(#63): IMP-34 R1 donor capacity measured bound (u1+u2)

This commit is contained in:
2026-05-21 22:07:41 +09:00
commit 8f085a28d3
3220 changed files with 985495 additions and 0 deletions
@@ -0,0 +1,37 @@
# Phase Z Families — WIP Marker
**Status:** intentionally untracked, uncontracted, out-of-scope for runtime matcher.
**Closes audit follow-up:** INTEGRATION-AUDIT-01-REPORT.md §10.2 F-2 (option c).
**Gate for promote/remove:** Gitea issue #42 (`IMP-04b Catalog extension to 32 frames`).
## Baseline lock (2026-05-19)
| Surface | Count | Notes |
|---|---|---|
| `git ls-files templates/phase_z2/families/*.html` | 11 | tracked family templates |
| `templates/phase_z2/catalog/frame_contracts.yaml` top-level keys | 11 | 1:1 with tracked basenames |
| `Get-ChildItem templates/phase_z2/families/*.html` | 13 | tracked 11 + WIP 2 (below) |
Active contracted family count = **11**. Tracked basenames ↔ `frame_contracts.yaml` top-level keys are set-equal. Drift between disk (13) and contracted (11) is fully explained by the 2 WIP files below.
## WIP family templates (uncontracted)
| File | Figma frame | Status |
|---|---|---|
| `app_sw_package_vs_solution.html` | frame 23 (`1171281203`) | WIP — not in `frame_contracts.yaml`, not in runtime matcher set. |
| `pre_construction_model_info_stacked.html` | frame 9 (`1171281180`) | WIP — not in `frame_contracts.yaml`, not in runtime matcher set. |
These files are partials authored during Phase Z-2 MVP-1.5b exploration. They are **not** part of the contracted Phase Z runtime catalog and must not be enumerated by frame selection, matcher, or any Stage 3 pipeline surface.
## Rules
- Adding a file to `templates/phase_z2/families/*.html` without a matching `frame_contracts.yaml` entry is **only** permitted if it is named here as WIP.
- `tests/test_family_contract_baseline.py` enforces this invariant: tracked families ↔ `frame_contracts.yaml` keys must be set-equal, modulo the WIP allowlist parsed from this file.
- Promoting a WIP file (add `frame_contracts.yaml` entry + register with matcher) or removing it must happen under issue #42 or a follow-up issue, not silently.
## References
- `docs/architecture/INTEGRATION-AUDIT-01-REPORT.md` §10.2 F-2 (audit finding closed by issue #52, option c)
- `docs/architecture/IMP-18-SVG-GAP-REPORT.md` L28, L51 (count basis corrected to `11 contracted + 2 WIP`)
- Gitea issue #52 (this reconciliation)
- Gitea issue #42 (pre-flight gate for promote/remove)
@@ -0,0 +1,159 @@
<!-- Phase Z-2 MVP F17 schema-correction partial — paired_rows_4x2_alternating_pills.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt.
본 partial = round 55~73 review-loop 의 calibration frame implementation. -->
{#
─────────────────────────────────────────────────────────────────────────────
Frame 17 = "현황 및 문제점" (cards/paired-rows-4x2-alternating-pills).
**source = 8 atomic issues** (4 paired rows × 2 issue cells per row).
이전 strict-4 → source 의 절반 누락. round 55~73 review-loop 의 schema-correction.
Visual provenance — figma_to_html_agent/blocks/1171281194/{index.html, texts.md, assets}.
- title gradient : rgb(204,82,0) → rgb(136,55,0) (source line 50)
- row border : 3px solid #60A451 (source line 69)
- row bg : rgba(250,237,203,0.15) (source line 68)
- body text : #0c271e (source line 130)
- 분할선 (cell 사이) : 2px dashed #60A451 (source line 135)
- pill alternation : row 1/3 = pill 상단, row 2/4 = pill 하단 (source line 161~225)
- row 2-3 visual gap : source `<div class="row-gap">` (height 65px) line 199-200
PROMOTED CSS : source-faithful unified green/cream/brown theme + pill shape +
top/bottom/top/bottom pill alternation + row 2-3 visual gap.
NOT PROMOTED (scope cap per Codex round 64/72 — CSS fallback 정당) :
- pill asset crop variant (`.crop-left` left -45.3% width 145.3% / `.crop-right` width 151.25%) —
source 의 PNG asset 정확 crop reproduction 은 single-pass scope 외 (Codex round 62 §6
+ round 68 scope cap). CSS approximation = pill shape + alternation + theme 모두 보존.
- bottom pill flip image transform (source line 117) — 단순 column-reverse 로 처리.
ADAPTED : Figma absolute → 4-row flex layout + token-fixed typography.
slots (17) : title +
row_{1..4}_{left,right}_{label,body} (8 × 2 = 16).
no row headers (source 부재, infer 금지 per Codex round 58 §1 + round 70 §3.6).
#}
<style>
.f17b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 8px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
/* title — source line 50 gradient + drop-shadow (text-shadow approximation) */
.f17b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(rgb(204,82,0), rgb(136,55,0));
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
/* rows 컨테이너 (4 paired rows) */
.f17b__rows {
display: flex; flex-direction: column;
gap: 4px;
flex: 1 1 auto;
min-height: 0;
}
/* row 2 뒤 visual gap (visual_hints.row_gap_after = [2]) — source line 199-200 */
.f17b__row:nth-child(2) { margin-bottom: 10px; }
/* row = 좌우 2 cells flex */
.f17b__row {
display: flex; flex-direction: row;
gap: 6px;
flex: 1 1 0;
min-height: 0;
border: 2px solid #60A451;
border-radius: 8px;
background: rgba(250,237,203,0.15);
overflow: hidden;
position: relative;
}
/* cell — pill alternation per visual_hints.pill_positions [top,bottom,top,bottom] */
.f17b__cell {
flex: 1 1 0;
display: flex; flex-direction: column;
padding: 8px 10px;
min-width: 0;
gap: 4px;
}
/* 분할선 — source line 135 dashed 2px #60A451 (cell 사이) */
.f17b__cell--right { border-left: 2px dashed #60A451; }
/* row 1, 3 = pill 상단 (default column) */
.f17b__row:nth-child(1) .f17b__cell,
.f17b__row:nth-child(3) .f17b__cell { flex-direction: column; }
/* row 2, 4 = pill 하단 (column-reverse — pill 이미지 flip 은 단순 reverse 로 approximate per source line 117) */
.f17b__row:nth-child(2) .f17b__cell,
.f17b__row:nth-child(4) .f17b__cell { flex-direction: column-reverse; }
/* pill — CSS approximation (source assets/*.png crop variant fallback per round 64/72 scope cap).
pill shape (rounded) + green/cream/brown theme 보존. */
.f17b__pill {
display: inline-flex; align-items: center; justify-content: center;
background-image: linear-gradient(180deg, #60A451 0%, #3d6d34 100%);
color: #fff;
font-weight: 700;
font-size: var(--font-sub-title);
line-height: 1.15;
padding: 4px 14px;
border-radius: 999px;
text-align: center;
flex-shrink: 0;
letter-spacing: -0.02em;
align-self: flex-start;
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}
/* body — source line 130 color #0c271e */
.f17b__body {
flex: 1 1 auto;
overflow: hidden;
color: #0c271e;
min-height: 0;
display: flex; flex-direction: column;
gap: 2px;
}
.f17b__body .text-line {
color: inherit;
font-size: var(--font-body);
line-height: var(--lh-body);
}
</style>
<div class="f17b" data-frame-id="1171281194" data-template-id="bim_current_problems_paired">
<div class="f17b__title">{{ slot_payload.title }}</div>
<div class="f17b__rows">
{% for r in [1, 2, 3, 4] %}
<div class="f17b__row">
<div class="f17b__cell f17b__cell--left">
<div class="f17b__pill">{{ slot_payload['row_' ~ r ~ '_left_label'] | safe }}</div>
<div class="f17b__body">
{% set body_left = slot_payload['row_' ~ r ~ '_left_body'] %}
{% if body_left %}
{% for line in body_left %}<div class="text-line{% if line.indent and line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f17b__cell f17b__cell--right">
<div class="f17b__pill">{{ slot_payload['row_' ~ r ~ '_right_label'] | safe }}</div>
<div class="f17b__body">
{% set body_right = slot_payload['row_' ~ r ~ '_right_body'] %}
{% if body_right %}
{% for line in body_right %}<div class="text-line{% if line.indent and line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
@@ -0,0 +1,146 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281195/ (frame 18)
─────────────────────────────────────────────────────────────────────────────
Frame 18 = "BIM 과 DX 의 이해" (table / compare-rows). 2개 column header (BIM vs DX) +
중앙 category column + N category rows (범위 / S/W / 프로세스 / 성과물 / 활용 /
확장성 / 수행개념 / 주체 등). compare 관점의 다면 비교 표 디자인.
본 partial = Track A frame 4 (Codex round 41 accepted, V4 UAI tier). NEW builder
`compare_table_2col` + NEW parser `compare_row_2col_item` 도입.
3-layer architecture (matrix §0) :
- V4 = matching authority — V4 ranked this frame use_as_is for 01-2.
- figma_to_html = source/evidence — analysis/texts/index.html/flat/assets full.
- Phase Z = runtime orchestration — 본 commit 추가 runtime 자원.
PROMOTED — CSS :
- title gradient (#000 → #883700, F13/F14/F12/F11 zone-title family)
- header row : col_a/col_b background tint + bold typography
- row 별 alternating background (zebra) — readability ↑
- cell border : subtle divider (#A5BBB4 family — F11 와 통일)
NOT PROMOTED (P1 case-by-case, compact zone fit) :
- Figma 의 column header 의 *raster icon* (있는 경우) — compact 에서 효과 ↓
- 다양한 색 강조 / 한자 deco (Figma source 보존, 미 promote)
ADAPTED :
- Figma 표 absolute positioning + zoom → Phase Z flex/grid (3-column table)
- typography → token-fixed (zone-title / sub-title / caption / body)
- row 별 height auto (content-fit)
─────────────────────────────────────────────────────────────────────────────
min_height_px derivation :
title 30 + header 30 + 6 data rows × 35 (compact) + padding 30 = 300
+ safety buffer (longer cell content) 50 = **350** (F14 와 동등 class).
Confirm via smoke + R3 artifact + V4 use_as_is target sample (MDX 01-2 미 trigger
in MDX 03 regression, 단 future batch verification 가능).
─────────────────────────────────────────────────────────────────────────────
slots :
- title : section.title
- col_a_label : 좌 column header (예: "BIM")
- col_b_label : 우 column header (예: "DX")
- rows : list[{label, col_a, col_b}] — N category rows
─────────────────────────────────────────────────────────────────────────────
4-class failure taxonomy :
- class 1 adapter readiness : NEW builder `compare_table_2col` + NEW parser
`compare_row_2col_item` 등록 필수 (PAYLOAD_BUILDERS / ITEM_PARSERS). 본 commit.
- class 2 content-fit : row 수 max 12 (builder limit). cell content 한 줄 한계
— 긴 문장 시 truncate 또는 wrap (CSS overflow-hidden).
#}
<style>
.f18b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f18b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
/* compare table — 3-column (category / col_a / col_b) */
.f18b__table {
display: grid;
grid-template-columns: 1fr 2fr 2fr;
gap: 0;
flex: 1 1 auto;
min-height: 0;
border: 1px solid #A5BBB4;
border-radius: 6px;
overflow: hidden;
background: #fff;
}
/* header row */
.f18b__header {
display: contents;
}
.f18b__header-cell {
background: linear-gradient(180deg, rgba(50,31,9,0.85) 0%, rgba(50,31,9,0.95) 100%);
color: #fff;
font-weight: 700;
font-size: var(--font-caption);
line-height: 1.2;
padding: 6px 8px;
text-align: center;
border-bottom: 2px solid #A5BBB4;
}
.f18b__header-cell--category {
background: linear-gradient(180deg, rgba(120,90,40,0.85) 0%, rgba(120,90,40,0.95) 100%);
font-style: italic;
}
/* data rows */
.f18b__rows {
display: contents;
}
.f18b__cell {
padding: 5px 8px;
font-size: var(--font-body);
line-height: var(--lh-body);
border-bottom: 1px solid rgba(165,187,180,0.4);
color: #1a1a1a;
overflow: hidden;
}
.f18b__cell--category {
background: rgba(255,250,240,0.7);
font-weight: 700;
color: #5a4b2e; /* PROMOTED — brown family */
text-align: center;
}
/* zebra striping (visual readability) — odd rows alternate */
.f18b__row:nth-child(odd) .f18b__cell:not(.f18b__cell--category) {
background: rgba(248,250,252,0.6);
}
</style>
<div class="f18b" data-frame-id="1171281195" data-template-id="bim_dx_comparison_table">
<div class="f18b__title">{{ slot_payload.title }}</div>
<div class="f18b__table">
<div class="f18b__header">
<div class="f18b__header-cell f18b__header-cell--category">구분</div>
<div class="f18b__header-cell">{{ slot_payload.col_a_label | safe }}</div>
<div class="f18b__header-cell">{{ slot_payload.col_b_label | safe }}</div>
</div>
<div class="f18b__rows">
{% for row in slot_payload.rows %}
<div class="f18b__row" style="display:contents;">
<div class="f18b__cell f18b__cell--category">{{ row.label | safe }}</div>
<div class="f18b__cell f18b__cell--col-a">{{ row.col_a | safe }}</div>
<div class="f18b__cell f18b__cell--col-b">{{ row.col_b | safe }}</div>
</div>
{% endfor %}
</div>
</div>
</div>
@@ -0,0 +1,223 @@
<!-- Phase Z-2 frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281193/index.html
─────────────────────────────────────────────────────────────────────────────
PROMOTED (Figma 1:1 변환물 → 그대로 사용):
- card-bg gradient (TL/TR top→bottom) : line 49 → linear-gradient(180deg, #f2f2f2 0%, #ffffff 100%)
- card-bg gradient (BL/BR bottom→top) : line 53-54 → linear-gradient(0deg, #f2f2f2 0%, #ffffff 100%)
- header-ribbon (TL/BL — 갈색) : line 75, 79 → linear-gradient(270deg, rgba(165,161,150,0.5), #39321E 73%)
- header-ribbon (TR/BR — 청록) : line 83, 87 → linear-gradient(90deg, rgba(41,107,85,0.5), #032118)
- red headline color : line 127 → #ff0000
- body-text color : line 136 → #000
- center-quote (Rome wasn't Built in a day!) : line 233 (decorative, MDX 4-2.2 의 핵심 메시지로 대체 가능)
- bullet marker : line 241 → "•"
- card 모서리 radius : line 51-54 → 50px (top corners TL/TR, bottom corners BL/BR)
NOT PROMOTED (Figma 데코지만 MDX 04-2.2 에 없는 콘텐츠):
- center-quote 의 영문 ("Rome wasn't Built in a day!") — slot_payload.center_quote 로 동적 (없으면 omit)
ADAPTED (Figma px / native size 무시, zone-compatible):
- 2226×1766 inner + zoom 0.575 → CSS grid 2×2 (no zoom, no fixed inner)
- Figma 60px ribbon font / 55px headline / 42px body → token-fixed (zone-title 13 / sub-title 12 / body 11)
- 1080px card width / 119px ribbon height → grid 1fr 1fr / 22px ribbon
- 644×584 center 원 → 90px 원 (zone-fit)
- absolute positioning (4 quadrants) → grid-template-areas
─────────────────────────────────────────────────────────────────────────────
slots: title, center_quote (옵션), quadrant_{1,2,3,4}_{label, body}
- quadrant 1 = TL (정책 집행)
- quadrant 2 = TR (수행 개념)
- quadrant 3 = BL (근본 취지의 이해부족)
- quadrant 4 = BR (지속적 투자 의지 부재)
- body 형식 = text-line family 호환 HTML (text_lines list 또는 pre-rendered string)
#}
<style>
.f16b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 4px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
position: relative;
}
.f16b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
color: #1e293b;
flex-shrink: 0;
padding-left: 4px;
}
/* 4 quadrants — 2×2 grid (CSS grid-template-areas) */
.f16b__quadrants {
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 6px;
position: relative;
min-height: 0;
}
.f16b__quadrant {
display: flex; flex-direction: column;
overflow: hidden;
min-height: 0;
padding: 0 8px 6px;
/* PROMOTED — card-bg gradient */
}
.f16b__quadrant--tl {
background: linear-gradient(180deg, #f2f2f2 0%, #ffffff 100%);
border-radius: 14px 14px 0 0; /* PROMOTED 50px → adapted 14px */
}
.f16b__quadrant--tr {
background: linear-gradient(180deg, #f2f2f2 0%, #ffffff 100%);
border-radius: 14px 14px 0 0;
}
.f16b__quadrant--bl {
background: linear-gradient(0deg, #f2f2f2 0%, #ffffff 100%);
border-radius: 0 0 14px 14px;
}
.f16b__quadrant--br {
background: linear-gradient(0deg, #f2f2f2 0%, #ffffff 100%);
border-radius: 0 0 14px 14px;
}
/* Header ribbon — PROMOTED gradient + token font */
.f16b__ribbon {
height: 22px;
margin: 0 -4px 4px;
border-radius: 999px;
display: flex; align-items: center; justify-content: center;
font-size: var(--font-sub-title);
font-weight: 900;
color: #fff;
text-shadow: 0 0 3px #322c1e;
flex-shrink: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0 8px;
}
/* PROMOTED ribbon gradient — TL/BL 갈색, TR/BR 청록 (figma line 75,79,83,87) */
.f16b__quadrant--tl .f16b__ribbon,
.f16b__quadrant--bl .f16b__ribbon {
background: linear-gradient(270deg, rgba(165,161,150,0.5) -26.87%, #39321E 73.13%);
}
.f16b__quadrant--tr .f16b__ribbon,
.f16b__quadrant--br .f16b__ribbon {
background: linear-gradient(90deg, rgba(41,107,85,0.5) 0%, #032118 100%);
}
/* Body — red headline + text-line bullets */
.f16b__body {
flex: 1;
overflow: hidden;
min-height: 0;
font-size: var(--font-body);
line-height: var(--lh-body);
color: #000;
}
.f16b__headline {
color: #ff0000; /* PROMOTED line 127 */
font-weight: 700;
font-size: var(--font-sub-title);
line-height: 1.3;
margin-bottom: 3px;
}
/* text-line family 은 slide_base.html 의 공통 contract 사용 */
/* Center quote (옵션 — MDX 에 있을 때만) */
.f16b__center {
position: absolute;
left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 80px; height: 80px;
border-radius: 50%;
background: linear-gradient(135deg, rgba(60,50,30,0.85), rgba(20,15,5,0.92));
display: flex; align-items: center; justify-content: center;
z-index: 2;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
pointer-events: none;
}
.f16b__center-quote {
color: #fff;
font-size: 9px;
font-weight: 700;
text-align: center;
line-height: 1.2;
padding: 0 6px;
}
</style>
<div class="f16b" data-frame-id="1171281193" data-template-id="bim_issues_quadrant_four">
{% if slot_payload.title %}
<div class="f16b__title">{{ slot_payload.title }}</div>
{% endif %}
<div class="f16b__quadrants">
{# Quadrant 1 (TL) — 정책 집행 (갈색 ribbon) #}
<div class="f16b__quadrant f16b__quadrant--tl">
{% if slot_payload.quadrant_1_label %}
<div class="f16b__ribbon">{{ slot_payload.quadrant_1_label | safe }}</div>
{% endif %}
{% if slot_payload.quadrant_1_headline or slot_payload.quadrant_1_body %}
<div class="f16b__body">
{% if slot_payload.quadrant_1_headline %}<div class="f16b__headline">{{ slot_payload.quadrant_1_headline | safe }}</div>{% endif %}
{% for line in slot_payload.quadrant_1_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
</div>
{% endif %}
</div>
{# Quadrant 2 (TR) — 수행 개념 (청록 ribbon) #}
<div class="f16b__quadrant f16b__quadrant--tr">
{% if slot_payload.quadrant_2_label %}
<div class="f16b__ribbon">{{ slot_payload.quadrant_2_label | safe }}</div>
{% endif %}
{% if slot_payload.quadrant_2_headline or slot_payload.quadrant_2_body %}
<div class="f16b__body">
{% if slot_payload.quadrant_2_headline %}<div class="f16b__headline">{{ slot_payload.quadrant_2_headline | safe }}</div>{% endif %}
{% for line in slot_payload.quadrant_2_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
</div>
{% endif %}
</div>
{# Quadrant 3 (BL) — 근본 취지의 이해부족 (갈색 ribbon) #}
<div class="f16b__quadrant f16b__quadrant--bl">
{% if slot_payload.quadrant_3_label %}
<div class="f16b__ribbon">{{ slot_payload.quadrant_3_label | safe }}</div>
{% endif %}
{% if slot_payload.quadrant_3_headline or slot_payload.quadrant_3_body %}
<div class="f16b__body">
{% if slot_payload.quadrant_3_headline %}<div class="f16b__headline">{{ slot_payload.quadrant_3_headline | safe }}</div>{% endif %}
{% for line in slot_payload.quadrant_3_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
</div>
{% endif %}
</div>
{# Quadrant 4 (BR) — 지속적 투자 의지 부재 (청록 ribbon) #}
<div class="f16b__quadrant f16b__quadrant--br">
{% if slot_payload.quadrant_4_label %}
<div class="f16b__ribbon">{{ slot_payload.quadrant_4_label | safe }}</div>
{% endif %}
{% if slot_payload.quadrant_4_headline or slot_payload.quadrant_4_body %}
<div class="f16b__body">
{% if slot_payload.quadrant_4_headline %}<div class="f16b__headline">{{ slot_payload.quadrant_4_headline | safe }}</div>{% endif %}
{% for line in slot_payload.quadrant_4_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
</div>
{% endif %}
</div>
{# Center quote — 옵션 #}
{% if slot_payload.center_quote %}
<div class="f16b__center">
<div class="f16b__center-quote">{{ slot_payload.center_quote | safe }}</div>
</div>
{% endif %}
</div>
</div>
@@ -0,0 +1,169 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281182/ (frame 11)
─────────────────────────────────────────────────────────────────────────────
Frame 11 = "시공단계 BIM 모델·정보 활용 구분" (cards-3-category, 1248×1066
px, scale 0.67542). Figma 원본 = 3 horizontal stacked rows (각 row = brown
label box at left + white content card at right with green border) + bottom
BIM 모델/공사 Process 다이어그램 (deco).
본 partial = Track A frame 3 (Codex round 39 accepted, V4 strongest UAI tier).
`index.html` base + Phase Z 규약 adapt + **compact MDX-mapped focus**.
3-layer architecture (matrix §0) :
- V4 = matching authority — V4 ranked this frame as use_as_is for "01-1 용어 정의"
(MDX 01) and restructure=1 다른 section. UAI tier post-F12.
- figma_to_html = source/evidence — 401-line index.html + 4 PNG assets (title-icon,
card_decor × 3). full A+T+I+F+S resource.
- Phase Z = runtime orchestration — 본 commit 추가 runtime 자원 (catalog + partial + smoke).
PROMOTED — CSS (Figma 색/디자인 의도 → CSS 보존) :
- 브라운 label box : rgba(50,31,9,0.8) bg + 우측 둥글기 (border-radius 0 20 20 0)
+ drop-shadow — index.html L82-95
- 라벨 typography : yellow (#FFE100) Korean + white English/subscript text — index.html L92-96
- 화이트 content card : white bg + green border (#A5BBB4) — index.html L99-103
- title gradient : F13/F14/F12 zone-title family (#000 ~ #883700)
NOT PROMOTED — Phase Z compact zone fit (자체 결정, P1 case-by-case, matrix §4.1 Fix 7) :
- title-icon (50×50 PNG) — small icon, zone-size 에서 visible 효과 ↓
- card_decor × 3 (260×120 decorative image at right side of each card) — Figma
의 visual 풍부함이지만 MDX 내용과 무관 deco
- 하단 BIM 모델/공사 Process 연계 다이어그램 — Figma 의 *대구도 시각* 으로
compact zone (320px 정도) 에서 표현 불가. content 의 *bottom synthesis text* 가
이 역할 대체 가능 — 단 현재 cardinality strict 3 (body) 라 별 slot 추가 X
→ figma_to_html source evidence 는 *보존* (assets/ 폴더 그대로). 향후 *fidelity
review* 시 promote 결정 가능 (preservation guardrail, Codex round 37 §3 정합).
ADAPTED :
- Figma 50/45/38/30px → token-fixed (zone-title 13 / sub-title 12 / caption / body 11)
- 1248×1066 absolute positioning + zoom 0.67542 → Phase Z flex column (3 row stack)
- 335×124 label box → compact 90~110×40~50 box (zone fit)
- 870×124 card → flex-1 (남은 width 차지)
─────────────────────────────────────────────────────────────────────────────
min_height_px derivation (round 13 §2.2) :
title 30 + 3 row × 70 (label + body 2-3 bullets) + gap 6×2 + padding 30 = 282
+ safety buffer 38 = **320**. F29/F12 와 동등 class.
─────────────────────────────────────────────────────────────────────────────
slots :
- title : section.title
- category_1_label / 2_label / 3_label : 3 category headings (quadrant_flat_slots)
- category_1_body / 2_body / 3_body : 3 category bullet lists (text_lines)
─────────────────────────────────────────────────────────────────────────────
4-class failure taxonomy (matrix §4.1 Fix 7) :
- class 1 adapter readiness : `quadrant_flat_slots` builder 재사용 (pad_to=3 +
key_pattern). 기존 F16 builder 미터치, secondary reuse 허용 (Codex round 39).
- class 2 content-fit : 3 row stack + body bullets. row 별 ~70px 한계 →
body 가 2-3 bullets 짧게. 4+ bullets 시 overflow watch.
#}
<style>
.f11b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f11b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
/* 3 row stack — Figma 의 brown-label + white-card horizontal pair */
.f11b__rows {
display: flex; flex-direction: column;
gap: 6px;
flex: 1 1 auto;
min-height: 0;
}
.f11b__row {
display: flex; align-items: stretch;
gap: 0;
flex: 1 1 0;
min-height: 0;
}
/* label box — Figma L82-95 (rgba(50,31,9,0.8) brown + 둥글기 + drop-shadow) */
.f11b__label {
flex: 0 0 110px;
background: rgba(50, 31, 9, 0.8);
border-radius: 0 12px 12px 0;
filter: drop-shadow(0 2px 1px rgba(0,0,0,0.25));
color: #fff;
font-weight: 700;
font-size: var(--font-sub-title);
line-height: 1.15;
letter-spacing: -0.04em;
display: flex; align-items: center; justify-content: center;
text-align: center;
padding: 4px 6px;
word-break: keep-all;
}
/* white card — Figma L99-103 (white bg + green border #A5BBB4) */
.f11b__card {
flex: 1 1 auto;
background: #fff;
border: 2px solid #A5BBB4;
border-radius: 12px;
padding: 6px 10px;
color: #1a1a1a;
min-height: 0;
overflow: hidden;
display: flex; flex-direction: column;
gap: 2px;
}
.f11b__card .text-line {
color: inherit;
font-size: var(--font-body);
line-height: var(--lh-body);
position: relative;
padding-left: 12px;
}
.f11b__card .text-line--bullet::before {
content: "•";
position: absolute;
left: 2px; top: 0;
color: #5a4b2e; /* PROMOTED — brown family */
font-weight: 700;
}
</style>
<div class="f11b" data-frame-id="1171281182" data-template-id="construction_bim_three_usage">
<div class="f11b__title">{{ slot_payload.title }}</div>
<div class="f11b__rows">
{# 3 rows — quadrant_flat_slots produces category_N_label / category_N_body for N=1..3 #}
<div class="f11b__row">
<div class="f11b__label">{{ slot_payload.category_1_label | safe }}</div>
<div class="f11b__card">
{% if slot_payload.category_1_body %}
{% for line in slot_payload.category_1_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f11b__row">
<div class="f11b__label">{{ slot_payload.category_2_label | safe }}</div>
<div class="f11b__card">
{% if slot_payload.category_2_body %}
{% for line in slot_payload.category_2_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f11b__row">
<div class="f11b__label">{{ slot_payload.category_3_label | safe }}</div>
<div class="f11b__card">
{% if slot_payload.category_3_body %}
{% for line in slot_payload.category_3_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
@@ -0,0 +1,173 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281189/ (frame 12)
─────────────────────────────────────────────────────────────────────────────
Frame 12 = "건설산업의 목표 (BIM 의 목적)" (cycle-3way-intersection, 2195×1195
px, scale 0.58312). Figma 원본 = 3 메인 원 (안전·품질 / 생산성·향상 / 소통·
신뢰) + 6 액센트 한자 원 (安/質/速/利/通/信) + 6 사이드 라벨 (안전성 제고 등)
+ 3 장식 rect + 3 arc + bg texture.
본 partial = Track A frame 2 (Codex round 30/33/35 합의, V4 strongest UAI tier).
`index.html` (510 lines) base + Phase Z 규약 adapt + **compact MDX-mapped focus**
(MDX 콘텐츠와 직접 매핑되는 5 slots 만 유지. Figma 의 frame-side decoration
는 NOT PROMOTED — zone 사이즈에서 cluttered 회피).
PROMOTED — CSS (Figma 색/디자인 의도 → CSS 으로 충분) :
- circle 1 (safety) gradient : index.html L142-145 (outer) + L149-154 (inner)
outer = linear-gradient(145.28deg, #FDC69E, #E0782C) multiply blend
inner = linear-gradient(145.28deg, #BC652B, #A24200) + white border + shadow
- circle 2 (productivity) : index.html L158-172
outer = linear-gradient(218.84deg, #D5AA89, #737373) multiply
inner = linear-gradient(153.95deg, #897445, #3E3523) + white border
- circle 3 (trust) : index.html L175-189
outer = linear-gradient(145.90deg, #FFFFFF, #253E1F) multiply
inner = linear-gradient(153.95deg, #296B55, #123328) + white border
- title gradient : #000 → #883700 (index.html L42-46) — F13/F14 zone-title 와 동일 family
- main label typography : 700 weight, white, text-shadow (index.html L192-204)
NOT PROMOTED — Phase Z compact zone fit (자체 결정, P1 case-by-case) :
- 6 액센트 한자 원 (安/質/速/利/通/信) — Figma 외 deco, MDX 무관, zone 사이즈에서 cluttered
- 6 사이드 라벨 (안전성 제고 / 품질 향상 / 신속·정확성 증진 / 비용저감 / 소통·이해 / 신뢰·투명성)
— Figma source 의 정해진 문구. MDX content 와 무관 deco text
- 3 장식 rect (gradient 곡선 wrap) + 3 arc 이미지 — Figma 의 시각 풍부함이지만 zone-size 에서 visible 효과 약함
- bg-texture multiply image (index.html L375) — zone 사이즈에서 effect 미미
ADAPTED :
- Figma 70/50/40px → token-fixed (zone-title 13 / sub-title 12 / caption / body 11)
- 3 메인 원 absolute positioning + zoom 0.58312 → Phase Z flex/grid (3-circle row)
- 350×350 원 사이즈 → compact 70-90 px circle (zone fit)
- Figma 의 3 원 *겹침 layout* (안전-품질 위 / 생산성 좌 / 소통 우) → flex row (분리, *cycle 의 의미*는 intersection text 가 표현)
─────────────────────────────────────────────────────────────────────────────
min_height_px derivation (Codex round 13 §2.2 — derive + confirm) :
Figma frame 1195 px @ scale 0.58312 → 697 px adapted (full frame, 6 deco 포함).
Phase Z compact (3 메인 원 + title + intersection) :
title 30 + 3 circle row 80 + label area 60 + intersection 30 + padding 40 = 240 px
+ safety buffer (가벼운 텍스트 overflow 보호) 80 = **320** (F14 350 보다 가벼움).
Confirm via smoke harness `--render-to` artifact.
─────────────────────────────────────────────────────────────────────────────
slots :
- title : section.title (Jinja 변수)
- circle_1_label / 2_label / 3_label : 3 메인 원 label (cycle_intersect_3 builder 산출)
- intersection : 중앙 교차 텍스트 (optional)
─────────────────────────────────────────────────────────────────────────────
4-class failure taxonomy (matrix §4.1 Fix 7) :
- class 1 adapter readiness 보호 : new builder cycle_intersect_3 가 PAYLOAD_BUILDERS
에 등록되어야 contract 가 valid. 안 등록 시 → builder None → 본 frame runtime fail
- class 2 content-fit : MDX 의 3 bullets 가 너무 길면 (label > ~20 chars) overflow.
label 짧게 (compact) 권장
─────────────────────────────────────────────────────────────────────────────
#}
<style>
.f12b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f12b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
/* 3 circle row — compact flex layout (Figma 의 겹침 cycle layout 단순화) */
.f12b__circles {
display: flex; align-items: center; justify-content: center;
gap: 16px;
flex: 1 1 auto;
min-height: 0;
padding: 8px 0;
}
.f12b__circle {
flex: 0 0 auto;
width: 110px; height: 110px;
border-radius: 50%;
position: relative;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
/* outer ring (Figma multiply blend 의도) — CSS gradient approximation */
.f12b__circle::before {
content: "";
position: absolute; inset: -8px;
border-radius: 50%;
z-index: -1;
mix-blend-mode: multiply;
}
/* per-circle gradient (PROMOTED from index.html L141-189) */
.f12b__circle--safety {
background: linear-gradient(145.28deg, #BC652B 16.04%, #A24200 55.20%);
border: 3px solid #fff;
}
.f12b__circle--safety::before {
background: linear-gradient(145.28deg, #FDC69E 16.04%, #E0782C 55.20%);
}
.f12b__circle--productivity {
background: linear-gradient(153.95deg, #897445 15.27%, #3E3523 61.74%);
border: 3px solid #fff;
}
.f12b__circle--productivity::before {
background: linear-gradient(218.84deg, #D5AA89 14.08%, #737373 92.67%);
}
.f12b__circle--trust {
background: linear-gradient(153.95deg, #296B55 15.27%, #123328 61.74%);
border: 3px solid #fff;
}
.f12b__circle--trust::before {
background: linear-gradient(145.90deg, #FFFFFF 8.47%, #253E1F 87.56%);
}
/* circle 안 label (white text + shadow, index.html L192-204) */
.f12b__circle-label {
color: #fff;
font-size: var(--font-caption);
font-weight: 700;
line-height: 1.1;
text-align: center;
padding: 4px;
text-shadow: 0 0 4px rgba(0,0,0,0.6);
word-break: keep-all;
}
/* intersection — 중앙 교차 텍스트 (optional, MDX 의 emphasis content) */
.f12b__intersection {
flex-shrink: 0;
text-align: center;
padding: 6px 12px;
font-size: var(--font-sub-title);
font-weight: 700;
color: #883700; /* PROMOTED — title gradient 의 end color */
background: linear-gradient(180deg, rgba(255,250,240,0.6) 0%, rgba(255,250,240,0) 100%);
border-top: 1px dashed #883700;
line-height: 1.3;
min-height: 0;
}
.f12b__intersection:empty {
display: none; /* slot 빈 경우 자동 hide */
}
</style>
<div class="f12b" data-frame-id="1171281189" data-template-id="construction_goals_three_circle_intersection">
<div class="f12b__title">{{ slot_payload.title }}</div>
<div class="f12b__circles">
<div class="f12b__circle f12b__circle--safety">
<div class="f12b__circle-label">{{ slot_payload.circle_1_label | safe }}</div>
</div>
<div class="f12b__circle f12b__circle--productivity">
<div class="f12b__circle-label">{{ slot_payload.circle_2_label | safe }}</div>
</div>
<div class="f12b__circle f12b__circle--trust">
<div class="f12b__circle-label">{{ slot_payload.circle_3_label | safe }}</div>
</div>
</div>
<div class="f12b__intersection">{{ slot_payload.intersection | safe }}</div>
</div>
@@ -0,0 +1,158 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281198/ (frame 20)
─────────────────────────────────────────────────────────────────────────────
Frame 20 = "디지털 전환(DX)은 S/W가 필수다" (cards-3-header). Figma 원본 =
상단 dark green banner ("디지털 전환(DX)은 S/W가 필수다" green/white mix) +
좌측 DX circular area + 우측 3 perspective cards (BIM 전면설계 / 디지털
전환 S/W / 고부가가치 산업전환).
본 partial = Track A frame 5 (Codex round 45 accepted, V4 LE tier strongest).
builder 재사용 = `quadrant_flat_slots` (F11 cards-3-category pattern). 새
builder/parser 0.
3-layer architecture (matrix §0) :
- V4 = matching authority — V4 ranked this frame light_edit for 03-1 + 01-1.
- figma_to_html (1171281198) = source/evidence — 386-line index.html + assets/.
- Phase Z = runtime — 본 commit adds catalog + partial + smoke fixture.
PROMOTED — CSS :
- 3 column header bg : dark green (`#296B55` family, Figma green theme)
- header text white bold + green accent
- title gradient (#000 → #883700, F13/F14/F12/F11/F18 zone-title family)
- card border + bullet markers (green family)
NOT PROMOTED (P1 case-by-case, compact zone fit) :
- 상단 dark green banner (Figma 의 큰 visual 영역, MDX 의 *title 만* 핵심)
- 좌측 DX circular area (multi-image + center text + decor — Figma 의 main
rhetorical anchor 단 compact zone 에서 표현 불가). title 의 gradient 로 의도 보존
- 한자/장식/배경 텍스처 — Figma source evidence 보존, 미 promote
ADAPTED :
- Figma 90/65/40px → token-fixed (zone-title 13 / sub-title 12 / caption / body 11)
- 1280×426 absolute positioning + zoom → Phase Z 3-column grid
- 3 perspective cards (header + body) → flex column
─────────────────────────────────────────────────────────────────────────────
min_height_px derivation :
3 col × (header 30 + body 3-bullets × 25) + title 30 + padding 30 = ~195
+ safety buffer (longer label / 5+ bullets) 125 = **320**. F12/F11/F18 class.
─────────────────────────────────────────────────────────────────────────────
slots :
- title : section.title
- perspective_1/2/3_label : 3 column headers
- perspective_1/2/3_body : list[{text, indent}] : 3 column bullets
─────────────────────────────────────────────────────────────────────────────
4-class failure taxonomy :
- class 1 readiness : builder reuse `quadrant_flat_slots` + `quadrant_item`.
contract + partial + smoke fixture.
- class 2 content-fit : header label 짧게 (single line). body 3-5 bullets per
column (zone fit). 6+ bullets 시 watch.
#}
<style>
.f20b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f20b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
/* 3-column grid — Figma cards-3-header pattern */
.f20b__cols {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
flex: 1 1 auto;
min-height: 0;
}
.f20b__col {
display: flex; flex-direction: column;
border: 2px solid #296B55; /* PROMOTED — green family from Figma */
border-radius: 8px;
overflow: hidden;
background: #fff;
min-height: 0;
}
/* header bar (top of each card, dark green per Figma) */
.f20b__header {
background: linear-gradient(180deg, #296B55 0%, #123328 100%); /* PROMOTED — Figma green theme */
color: #fff;
font-weight: 700;
font-size: var(--font-sub-title);
line-height: 1.15;
padding: 6px 10px;
text-align: center;
flex-shrink: 0;
letter-spacing: -0.04em;
}
/* body — bullet list (CSS check marker, F14 pattern) */
.f20b__body {
flex: 1 1 auto;
overflow: hidden;
padding: 6px 10px 8px;
color: #1a1a1a;
min-height: 0;
display: flex; flex-direction: column;
gap: 3px;
}
.f20b__body .text-line {
color: inherit;
font-size: var(--font-body);
line-height: var(--lh-body);
position: relative;
padding-left: 14px;
}
.f20b__body .text-line--bullet::before {
content: "\2713"; /* ✓ check mark — green theme */
position: absolute;
left: 0; top: 0;
color: #296B55; /* PROMOTED — green family */
font-weight: 700;
}
</style>
<div class="f20b" data-frame-id="1171281198" data-template-id="dx_sw_necessity_three_perspectives">
<div class="f20b__title">{{ slot_payload.title }}</div>
<div class="f20b__cols">
{# 3 columns — quadrant_flat_slots produces perspective_N_label / perspective_N_body for N=1..3 #}
<div class="f20b__col">
<div class="f20b__header">{{ slot_payload.perspective_1_label | safe }}</div>
<div class="f20b__body">
{% if slot_payload.perspective_1_body %}
{% for line in slot_payload.perspective_1_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f20b__col">
<div class="f20b__header">{{ slot_payload.perspective_2_label | safe }}</div>
<div class="f20b__body">
{% if slot_payload.perspective_2_body %}
{% for line in slot_payload.perspective_2_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f20b__col">
<div class="f20b__header">{{ slot_payload.perspective_3_label | safe }}</div>
<div class="f20b__body">
{% if slot_payload.perspective_3_body %}
{% for line in slot_payload.perspective_3_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
@@ -0,0 +1,152 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281179/ (frame 8)
─────────────────────────────────────────────────────────────────────────────
Frame 8 = "효율적인 정보의 관리와 활용 (What/How/When)" (cards/3-section-framework).
3 sections framework — What (무슨 정보) / How (어떻게 연계) / When (언제 사용).
정보 관리·활용 3관점 병렬 제시 디자인.
본 partial = Track A frame 6 (Codex round 47 V4-zero catalog-completeness
activation guardrail). **V4 신호 0** (4 MDX sample 기준). 32-frame all-in
scope 채우는 등록 — V4 가 다른 MDX 에서 본 frame 을 추천 시 backend 받음.
*V4 endorsement 아님* — V4 = matching authority 보존, Phase Z 는 runtime
availability 추가만.
3-layer architecture (matrix §0) :
- V4 = matching authority — 본 frame 은 4 MDX 에서 미선택 (UAI/LE/RS = 0).
단 V4 evidence 미 cover 의 MDX 가 추천 시 backend 가 받을 수 있게 등록.
- figma_to_html (1171281179) = source/evidence — analysis + texts + index +
flat + assets 모두 보유. 본 partial 의 visual base.
- Phase Z = runtime — catalog + partial + smoke fixture 추가.
PROMOTED — CSS :
- 3 section header color (W/H/W = What/How/When framework)
- title gradient (zone-title family — F13/F14/F12/F11/F18/F20/F8 등 동일)
- card border + bullet markers
NOT PROMOTED (P1 case-by-case + preservation guardrail) :
- Figma 의 상단 banner / icon / 배경 텍스처 / 장식 image 등 — figma_to_html
source evidence 보존, compact zone fit 위해 미 promote
ADAPTED :
- Figma 50px+ → token-fixed
- absolute positioning → Phase Z 3-column grid
─────────────────────────────────────────────────────────────────────────────
min_height_px = 320 (F11/F20 와 동등 — 3-column header + body)
slots : title, section_1/2/3_label, section_1/2/3_body
4-class status :
- class 1 ready (builder reuse + partial + smoke)
- class 2 watch (body 5+ bullets per column)
#}
<style>
.f8b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f8b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
.f8b__cols {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
flex: 1 1 auto;
min-height: 0;
}
.f8b__col {
display: flex; flex-direction: column;
border: 2px solid;
border-radius: 8px;
overflow: hidden;
background: #fff;
min-height: 0;
}
/* per-section accent — W/H/W theme (다른 frame 들과 차별) */
.f8b__col:nth-child(1) { border-color: #2563eb; } /* What — blue */
.f8b__col:nth-child(2) { border-color: #ea580c; } /* How — orange */
.f8b__col:nth-child(3) { border-color: #16a34a; } /* When — green */
.f8b__header {
color: #fff;
font-weight: 700;
font-size: var(--font-sub-title);
line-height: 1.15;
padding: 6px 10px;
text-align: center;
flex-shrink: 0;
letter-spacing: -0.02em;
}
.f8b__col:nth-child(1) .f8b__header { background: linear-gradient(180deg, #2563eb 0%, #1e40af 100%); }
.f8b__col:nth-child(2) .f8b__header { background: linear-gradient(180deg, #ea580c 0%, #c2410c 100%); }
.f8b__col:nth-child(3) .f8b__header { background: linear-gradient(180deg, #16a34a 0%, #15803d 100%); }
.f8b__body {
flex: 1 1 auto;
overflow: hidden;
padding: 6px 10px 8px;
color: #1a1a1a;
min-height: 0;
display: flex; flex-direction: column;
gap: 3px;
}
.f8b__body .text-line {
color: inherit;
font-size: var(--font-body);
line-height: var(--lh-body);
position: relative;
padding-left: 14px;
}
.f8b__body .text-line--bullet::before {
content: "•";
position: absolute;
left: 2px; top: 0;
font-weight: 700;
}
.f8b__col:nth-child(1) .f8b__body .text-line--bullet::before { color: #2563eb; }
.f8b__col:nth-child(2) .f8b__body .text-line--bullet::before { color: #ea580c; }
.f8b__col:nth-child(3) .f8b__body .text-line--bullet::before { color: #16a34a; }
</style>
<div class="f8b" data-frame-id="1171281179" data-template-id="info_management_what_how_when">
<div class="f8b__title">{{ slot_payload.title }}</div>
<div class="f8b__cols">
<div class="f8b__col">
<div class="f8b__header">{{ slot_payload.section_1_label | safe }}</div>
<div class="f8b__body">
{% if slot_payload.section_1_body %}
{% for line in slot_payload.section_1_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f8b__col">
<div class="f8b__header">{{ slot_payload.section_2_label | safe }}</div>
<div class="f8b__body">
{% if slot_payload.section_2_body %}
{% for line in slot_payload.section_2_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f8b__col">
<div class="f8b__header">{{ slot_payload.section_3_label | safe }}</div>
<div class="f8b__body">
{% if slot_payload.section_3_body %}
{% for line in slot_payload.section_3_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
@@ -0,0 +1,294 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281210/index.html
─────────────────────────────────────────────────────────────────────────────
PROMOTED (Figma 1:1 변환물 → 그대로 사용):
- banner-left text gradient : lines 101-104 → linear-gradient(90deg, rgb(62,53,35), rgb(62,53,35)) on linear-gradient(180deg, rgb(41,107,85), rgb(18,51,40))
- banner-right text gradient : lines 110-113 → linear-gradient(90deg, rgb(34,95,74), rgb(34,95,74)) on linear-gradient(180deg, rgb(41,107,85), rgb(18,51,40))
- banner-left bg gradient : lines 84-91 → linear-gradient(to right, rgba(136,131,118,.343), #39321E 73.1%, #39321E) + border-radius pill
- banner-right bg gradient : lines 92-98 → linear-gradient(to right, #032118, rgba(41,107,85,.1)) + border-radius pill
- body bg gradients (좌/우) : lines 53-68 → multi-bg / 좌(57,50,30) α0.3 → white α0.3, 우(41,107,85) α0.3 → white α0.3
- section-title-left color : line 125 → #5C3714 (갈)
- section-title-right color : line 126 → #084C56 (짙은 청록)
- bullets text : line 136 → 700 / #000 / list-disc
- arrow PNG asset : line 220 → assets/arrow.png (AS-IS → TO-BE)
- footnote (*) inline : lines 144, 281-283 → 25.8px small + indent
(2026-05-08 수정) 원본 SVG 3 개 (header_left_bg / header_right_bg / body_bg) → CSS gradient 로 재현.
asset 파일 부재 (figma 원본 R8 룰 = "순수 CSS 우선" 따라 SVG 자체 미생성). 시각 fidelity 동일.
ADAPTED (Figma px / native 무시, zone flex 재구성):
- 3848×1388 inner + zoom 0.33270 → flex layout (no zoom, no fixed inner)
- 70px banner / 50px section / 40px body→ var(--font-sub-title) / 8-10px / var(--font-caption)
- absolute left/top px → flex grid (no absolute)
- banner heights 142px + body 933px → 비율 기반 flex (banner ~28%, body ~72%)
- assets 1921×142 / 3845×933 sizes → object-fit cover, 비율 유지
─────────────────────────────────────────────────────────────────────────────
slots: title (omitted), banner_left, banner_right,
process.sections[3] (s[0]: AS-IS/TO-BE, s[1-2]: bullets),
product.sections[3] (bullets, optional footnote/sub_title)
#}
<style>
.f29b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 4px;
position: relative;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
overflow: hidden;
}
.f29b__title {
font-size: var(--font-zone-title); /* 13px — frame 13 의 f13b__title 과 동일 위계 */
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
padding-left: 4px;
}
/* banners — top */
.f29b__banners {
flex: 0 0 auto;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px;
position: relative;
height: 36px;
}
.f29b__banner {
position: relative;
overflow: hidden;
display: flex; align-items: center; justify-content: center;
}
/* PROMOTED background gradients — figma origin lines 84-98 (header-bg--left/right).
원본 SVG 3 개 → CSS gradient 로 재현 (R8/R9 준수). border-radius 9999px = 자동 pill. */
.f29b__banner--left {
background: linear-gradient(to right,
rgba(136, 131, 118, 0.343) 0%,
#39321E 73.1%,
#39321E 100%);
border-radius: 0 9999px 9999px 0;
}
.f29b__banner--right {
background: linear-gradient(to right,
#032118 0%,
rgba(41, 107, 85, 0.1) 100%);
border-radius: 9999px 0 0 9999px;
}
.f29b__banner-text {
position: relative;
z-index: 1;
font-size: var(--font-sub-title);
font-weight: 900;
line-height: 1;
text-shadow: 0 0 2px #322C1E;
-webkit-background-clip: text; background-clip: text;
color: transparent;
padding: 0 8px;
}
/* PROMOTED gradient — lines 101-104 / 110-113 */
.f29b__banner--left .f29b__banner-text {
background-image:
linear-gradient(90deg, rgb(62,53,35) 0%, rgb(62,53,35) 100%),
linear-gradient(180deg, rgb(41,107,85) 0%, rgb(18,51,40) 100%);
}
.f29b__banner--right .f29b__banner-text {
background-image:
linear-gradient(90deg, rgb(34,95,74) 0%, rgb(34,95,74) 100%),
linear-gradient(180deg, rgb(41,107,85) 0%, rgb(18,51,40) 100%);
}
/* body — 6 cell grid (3 rows × 2 cols) — 좌우 row divider Y 정렬 */
/* PROMOTED background — figma origin lines 53-68 (body-bg-left/right).
좌(0~50%): #39321E α0.3 (top) → white α0.3 (bottom)
우(50~100%): #296B55 α0.3 (top) → white α0.3 (bottom)
원본 SVG → CSS multi-bg 로 재현. */
.f29b__body {
flex: 1;
position: relative;
min-height: 0;
padding-top: 4px;
background:
linear-gradient(to bottom, rgba(57,50,30,0.3) 0%, rgba(255,255,255,0.3) 100%) 0% 0% / 50% 100% no-repeat,
linear-gradient(to bottom, rgba(41,107,85,0.3) 0%, rgba(255,255,255,0.3) 100%) 100% 0% / 50% 100% no-repeat;
}
/* 6 cell grid: 3 rows (section 1/2/3), 2 cols (process/product). 각 row 의 height = max(좌, 우) */
.f29b__grid {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: auto;
gap: 6px 10px;
padding: 4px 8px;
height: 100%;
align-content: start;
}
.f29b__cell {
overflow: hidden;
min-width: 0;
min-height: 0;
}
/* row 2/3 (3 번째 cell 이후) 위에 dashed divider — 좌우 같은 Y */
.f29b__cell:nth-child(n+3) {
border-top: 1px dashed rgba(0,0,0,0.15);
padding-top: 6px;
margin-top: 4px;
}
/* section-title — 부소목차 (사용자 5-layer 직설 2026-05-07): Analogue 기반... 같은 깊이 0 굵은 bullet */
.f29b__section-title {
font-size: var(--font-sub-title); /* 12px — 부소목차 위계 */
font-weight: 900;
line-height: 1.3;
margin-bottom: 5px;
padding-left: 6px;
border-left: 3px solid currentColor;
}
.f29b__cell--left .f29b__section-title { color: #5C3714; } /* PROMOTED line 125 */
.f29b__cell--right .f29b__section-title { color: #084C56; } /* PROMOTED line 126 */
.f29b__section-title__sub {
font-size: var(--font-caption); /* 10px */
margin-left: 3px;
}
/* f29b 의 본문 = .text-line 공통 contract 사용. bullet color override. */
.f29b__cell .text-line--bullet { color: #000; font-weight: 700; }
/* AS-IS/TO-BE 좌우 + arrow (PROMOTED 구조) */
.f29b__transform {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 4px;
align-items: start;
}
.f29b__transform__list {
/* .text-line 공통 contract 그대로. wrapper 만 grid 안의 cell 역할 */
}
.f29b__transform__arrow {
align-self: center;
width: 28px;
flex-shrink: 0;
}
.f29b__transform__arrow img {
width: 100%;
height: auto;
display: block;
}
.f29b__footnote {
font-size: var(--font-caption); /* 10px */
line-height: var(--lh-caption);
color: #333;
padding-left: 14px;
margin-top: 1px;
white-space: pre-wrap;
}
.f29b__aster-small { font-size: 9px; }
</style>
<div class="f29b" data-frame-id="1171281210" data-template-id="process_product_two_way">
{# H2 mid-heading — section.title 렌더 (frame 13 의 f13b__title 과 동일 위계) #}
<div class="f29b__title">{{ slot_payload.title }}</div>
{# Banners (PROMOTED 구조 + gradient lines 101-113).
배경 = .f29b__banner--left/right 의 CSS gradient (figma SVG → R8 CSS gradient 재현). #}
<div class="f29b__banners">
<div class="f29b__banner f29b__banner--left">
<div class="f29b__banner-text">{{ slot_payload.banner_left }}</div>
</div>
<div class="f29b__banner f29b__banner--right">
<div class="f29b__banner-text">{{ slot_payload.banner_right }}</div>
</div>
</div>
{# Body — 6 cell grid (row-major: row 1 좌/우, row 2 좌/우, row 3 좌/우).
row 별 height = max(좌, 우) → divider Y 정렬.
배경 = .f29b__body 의 CSS multi-gradient (figma SVG → R8 CSS gradient 재현). #}
<div class="f29b__body">
<div class="f29b__grid">
{# ───── Row 1: section 1 ───── #}
{% set s1 = slot_payload.process.sections[0] %}
<div class="f29b__cell f29b__cell--left" data-frame-slot-id="process_column">
{% if s1.title %}
<div class="f29b__section-title">{{ s1.title | safe }}</div>
{% if s1.transforms %}
<div class="transform-block">
<div class="transform-block__header">
<span class="transform-block__label--from">AS-IS</span>
<span></span>
<span class="transform-block__label--to">TO-BE</span>
</div>
<div class="transform-rows">
{% for t in s1.transforms %}
<div class="transform-row">
<div class="transform-row__from">{{ t.from | safe }}</div>
<div class="transform-row__arrow">➜</div>
<div class="transform-row__to">{{ t.to | safe }}</div>
</div>
{% endfor %}
</div>
</div>
{% elif s1.text_lines %}
{% for line in s1.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
{% endif %}
</div>
{% set p1 = slot_payload.product.sections[0] %}
<div class="f29b__cell f29b__cell--right" data-frame-slot-id="product_column">
{% if p1.title %}
<div class="f29b__section-title">{{ p1.title | safe }}</div>
{% for line in p1.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
{# ───── Row 2: section 2 ───── #}
{% set s2 = slot_payload.process.sections[1] %}
<div class="f29b__cell f29b__cell--left" data-frame-slot-id="process_column">
{% if s2.title %}
<div class="f29b__section-title">{{ s2.title | safe }}</div>
{% for line in s2.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
{% set p2 = slot_payload.product.sections[1] %}
<div class="f29b__cell f29b__cell--right" data-frame-slot-id="product_column">
{% if p2.title %}
<div class="f29b__section-title">{{ p2.title | safe }}</div>
{% for line in p2.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% if p2.footnote %}
<div class="f29b__footnote"><span class="f29b__aster-small">*</span> {{ p2.footnote | safe }}</div>
{% endif %}
{% endif %}
</div>
{# ───── Row 3: section 3 ───── #}
{% set s3 = slot_payload.process.sections[2] %}
<div class="f29b__cell f29b__cell--left" data-frame-slot-id="process_column">
{% if s3.title %}
<div class="f29b__section-title">{{ s3.title | safe }}</div>
{% for line in s3.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
{% set p3 = slot_payload.product.sections[2] %}
<div class="f29b__cell f29b__cell--right" data-frame-slot-id="product_column">
{% if p3.title %}
<div class="f29b__section-title">{{ p3.title | safe }}{% if p3.sub_title %}<span class="f29b__section-title__sub">{{ p3.sub_title | safe }}</span>{% endif %}</div>
{% for line in p3.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
@@ -0,0 +1,135 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281209/ (frame 28)
─────────────────────────────────────────────────────────────────────────────
Frame 28 = "현존 상용 S/W의 현실" (cards/title-plus-3-emphasis). 3 emphasis
cards parallel — 3 problem/약점/한계 진단 (토목 전문성 부족 / 비효율성 /
실무 적용 불가).
본 partial = Track A frame 7 (V4-zero catalog-completeness activation per
Codex round 49 guardrail). V4 = matching authority 보존. Phase Z 는 runtime
availability 만 추가.
PROMOTED CSS :
- per-emphasis 경고 색 (red/orange/amber — problem theme)
- title gradient (zone-title family)
- bullet markers per-emphasis color
NOT PROMOTED : Figma source decoration / banner / texture — 보존 (figma_to_html).
ADAPTED : Figma absolute → flex 3-column grid + token-fixed typography.
slots : title, emphasis_1/2/3_label, emphasis_1/2/3_body.
#}
<style>
.f28b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f28b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
.f28b__cols {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
flex: 1 1 auto;
min-height: 0;
}
.f28b__col {
display: flex; flex-direction: column;
border: 2px solid;
border-radius: 8px;
overflow: hidden;
background: #fff;
min-height: 0;
}
/* per-emphasis problem theme — orange/red family for 약점/한계 진단 */
.f28b__col:nth-child(1) { border-color: #dc2626; } /* red */
.f28b__col:nth-child(2) { border-color: #ea580c; } /* orange */
.f28b__col:nth-child(3) { border-color: #d97706; } /* amber */
.f28b__header {
color: #fff;
font-weight: 700;
font-size: var(--font-sub-title);
line-height: 1.15;
padding: 6px 10px;
text-align: center;
flex-shrink: 0;
letter-spacing: -0.02em;
}
.f28b__col:nth-child(1) .f28b__header { background: linear-gradient(180deg, #dc2626 0%, #991b1b 100%); }
.f28b__col:nth-child(2) .f28b__header { background: linear-gradient(180deg, #ea580c 0%, #9a3412 100%); }
.f28b__col:nth-child(3) .f28b__header { background: linear-gradient(180deg, #d97706 0%, #92400e 100%); }
.f28b__body {
flex: 1 1 auto;
overflow: hidden;
padding: 6px 10px 8px;
color: #1a1a1a;
min-height: 0;
display: flex; flex-direction: column;
gap: 3px;
}
.f28b__body .text-line {
color: inherit;
font-size: var(--font-body);
line-height: var(--lh-body);
position: relative;
padding-left: 14px;
}
.f28b__body .text-line--bullet::before {
content: "!";
position: absolute;
left: 4px; top: 0;
font-weight: 700;
}
.f28b__col:nth-child(1) .f28b__body .text-line--bullet::before { color: #dc2626; }
.f28b__col:nth-child(2) .f28b__body .text-line--bullet::before { color: #ea580c; }
.f28b__col:nth-child(3) .f28b__body .text-line--bullet::before { color: #d97706; }
</style>
<div class="f28b" data-frame-id="1171281209" data-template-id="sw_reality_three_emphasis">
<div class="f28b__title">{{ slot_payload.title }}</div>
<div class="f28b__cols">
<div class="f28b__col">
<div class="f28b__header">{{ slot_payload.emphasis_1_label | safe }}</div>
<div class="f28b__body">
{% if slot_payload.emphasis_1_body %}
{% for line in slot_payload.emphasis_1_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f28b__col">
<div class="f28b__header">{{ slot_payload.emphasis_2_label | safe }}</div>
<div class="f28b__body">
{% if slot_payload.emphasis_2_body %}
{% for line in slot_payload.emphasis_2_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
<div class="f28b__col">
<div class="f28b__header">{{ slot_payload.emphasis_3_label | safe }}</div>
<div class="f28b__body">
{% if slot_payload.emphasis_3_body %}
{% for line in slot_payload.emphasis_3_body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
@@ -0,0 +1,157 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281190/index.html
─────────────────────────────────────────────────────────────────────────────
PROMOTED (Figma 1:1 변환물 → 그대로 사용):
- tech bar gradient : line 71 → linear-gradient(180deg, #0D78D0 0%, #023056 100%)
- people bar gradient : line 72 → linear-gradient(180deg, #FF9A23 0%, #CC5200 100%)
- nature bar gradient : line 73 → linear-gradient(180deg, #39BE49 21%, #23742C 100%)
- tech heading text : line 123 → linear-gradient(180deg, #0D78D0, #134D7F)
- people heading text : line 124 → linear-gradient(180deg, #FE900C, #D18B37)
- nature heading text : line 125 → linear-gradient(180deg, #3CA649, #23742C)
- title gradient : line 40 → linear-gradient(180deg, #000, #883700)
- desc color : line 118 → #3E3523
- col 외곽 border : line 57 → 2px solid #000 (top + bottom)
- col-section divider : line 103 → 2px dashed #000
NOT PROMOTED (Figma 데코지만 MDX 에 없으므로 주입 X):
- 한자 (技/術 / 人/材 / 天/地) ← MDX 에 없는 content. Figma frame 의 visual 데코일 뿐.
ADAPTED:
- Figma px / native size 무시, flex layout
- Figma 70/50/45/35px fonts → token-fixed (zone-title 13 / sub-title 12 / body 11 / caption 10)
- desc <br>-joined → nested <ul><li> (구조 보존)
─────────────────────────────────────────────────────────────────────────────
slots: title, pillars[].{label, color_class, sections[].{heading, bullets[]}}
#}
<style>
.f13b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 4px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f13b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
}
.f13b__cols {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 8px;
flex: 1;
min-height: 0;
}
.f13b__col {
display: flex;
border-top: 2px solid #000; /* PROMOTED line 57 */
border-bottom: 2px solid #000;
overflow: hidden;
min-width: 0;
background: rgba(255,255,255,0.5);
}
.f13b__bar {
flex: 0 0 50px;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
color: #fff;
font-weight: 700;
text-align: center;
padding: 6px 2px;
gap: 3px;
}
.f13b__col--tech .f13b__bar { background: linear-gradient(180deg, #0D78D0 0%, #023056 100%); }
.f13b__col--people .f13b__bar { background: linear-gradient(180deg, #FF9A23 0%, #CC5200 100%); }
.f13b__col--nature .f13b__bar { background: linear-gradient(180deg, #39BE49 21%, #23742C 100%); }
/* PROMOTED Figma frame 13 line 92-93 — main + parenthetical stacked vertically */
.f13b__bar-main {
font-size: var(--font-sub-title); /* 12px — main word "기술/사람/자연" */
font-weight: 700;
line-height: 1.2;
display: block;
}
.f13b__bar-paren {
font-size: var(--font-caption); /* 10px — "(디지털/역량/여건)" */
font-weight: 500;
line-height: 1.2;
display: block;
opacity: 0.95;
}
.f13b__body {
flex: 1;
display: flex; flex-direction: column;
padding: 8px 12px; /* breathing (was 6px 10px) */
min-width: 0;
overflow: hidden;
}
.f13b__section {
flex: 1;
padding: 6px 0; /* breathing (was 4px) */
overflow: hidden;
min-height: 0;
}
.f13b__section + .f13b__section {
border-top: 2px dashed #000; /* PROMOTED line 103 */
margin-top: 6px; /* visible section gap (was 4px) */
padding-top: 8px; /* breathing (was 6px) */
}
/* heading — 부소목차 (사용자 5-layer 직설 2026-05-07): Digital 기술과... 같은 깊이 1 굵은 bullet */
.f13b__heading {
font-size: var(--font-sub-title); /* 12px — 부소목차 위계 */
font-weight: 700;
line-height: var(--lh-sub-title);
-webkit-background-clip: text; background-clip: text;
color: transparent;
margin-bottom: 6px; /* visible heading-body gap (was 4px) */
}
.f13b__col--tech .f13b__heading { background-image: linear-gradient(180deg, #0D78D0 0%, #134D7F 100%); }
.f13b__col--people .f13b__heading { background-image: linear-gradient(180deg, #FE900C 0%, #D18B37 100%); }
.f13b__col--nature .f13b__heading { background-image: linear-gradient(180deg, #3CA649 21%, #23742C 100%); }
/* desc — frame-family text layout contract (.text-line 공통 클래스 사용)
feedback (mvp1.5b_test5): browser-native ul/li 폐기. */
.f13b__desc {
color: #3E3523; /* PROMOTED line 118 */
overflow: hidden;
}
/* desc 안 .text-line 색 override */
.f13b__desc .text-line { color: #3E3523; }
</style>
<div class="f13b" data-frame-id="1171281190" data-template-id="three_parallel_requirements">
<div class="f13b__title">{{ slot_payload.title }}</div>
<div class="f13b__cols">
{% for pillar in slot_payload.pillars %}
<div class="f13b__col f13b__col--{{ pillar.color_class }}">
<div class="f13b__bar">
<span class="f13b__bar-main">{{ pillar.label_main | safe }}</span>
{% if pillar.label_paren %}
<span class="f13b__bar-paren">{{ pillar.label_paren | safe }}</span>
{% endif %}
</div>
<div class="f13b__body">
{% for section in pillar.sections %}
<div class="f13b__section">
<div class="f13b__heading">{{ section.heading | safe }}</div>
{% if section.text_lines %}
<div class="f13b__desc">
{% for line in section.text_lines %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
@@ -0,0 +1,248 @@
<!-- Phase Z-2 MVP-1.5b frame-derived adapted block.
§17 룰 — Figma 시각 언어 promote, geometry 만 zone-compatible adapt. -->
{#
─────────────────────────────────────────────────────────────────────────────
Visual Provenance — figma_to_html_agent/blocks/1171281191/ (frame 14)
─────────────────────────────────────────────────────────────────────────────
Frame 14 = "주체별 기대효과" (cards-3col-persona, 2601×1927 px, scale 0.49213).
3 컬럼 카드 : 발주자 / 시공자 / 설계자 각 persona 별 *목표* + bullet 7 개 안팎.
본 partial 은 `figma_to_html_agent/blocks/1171281191/index.html` (184 lines) 을
base 로 Phase Z 규약 (Jinja slot + token CSS + slide-base wrap) adapt.
본 commit (Track A 1/16 second refinement, F2 re-do post-Codex round 22 catch) :
asset-promotion policy = per-asset case-by-case (round 13 §2.3 + round 24 합의).
strict CSS-only over-generalization (first refinement `2fcd8bb`) 정정.
PROMOTED — RASTER (Phase Z `copy_assets()` 가 figma_to_html_agent/blocks/1171281191/
assets/ → {run_dir}/assets/three_persona_benefits/ 복사) :
- col_bg_texture (4a17cd1d...png) — 3 컬럼 BG 텍스처. CSS noise/gradient 근사 보다 fidelity 보존.
- bottom photo client (d2c070f2...png) — 발주자 카드 하단 사진
- bottom photo constructor (2a6a58e7...png) — 시공자 카드 하단 사진
- bottom photo designer (39113493...png) — 설계자 카드 하단 사진
- badge outer client (77f31997...png) — 발주자 round badge outer ring
- badge inner client (e64c967d...png) — 발주자 round badge inner disk
- badge outer constructor (1550ec75...png)
- badge inner constructor (85beaf9d...png)
- badge outer designer (9ac089fa...png)
- badge inner designer (4b534ccf...png)
→ 10 raster (1 BG + 3 photos + 6 badge). Codex round 24 tightening : badge =
default promote (asset-capable path 검증).
PROMOTED — CSS (Figma 색/디자인 의도 → CSS 으로 충분) :
- 발주자 accent color : Figma TEXT #285b4a (dark green) — index.html L80
- 시공자 accent color : Figma TEXT #445a2f (olive) — index.html L81
- 설계자 accent color : Figma TEXT #743002 (red-brown) — index.html L82
- col-overlay tint : #d6e7c4 / #e1efe1 / #d0c0ad (opacity-80 — solid 색, CSS equivalent)
- title gradient : #000 → #883700 (F13 zone-title 와 동일 family)
- bullet check marker : ✓ unicode (실제 png 6896d5c2 와 동등)
NOT PROMOTED (MDX 무관 + Figma 데코) :
- 한자/장식 텍스트 (Figma 안 deco) — index.html 에도 없음. N/A.
ADAPTED :
- Figma 65/50/40px → token-fixed (zone-title 13 / sub-title 12 / caption / body 11)
- Figma 396×397 absolute round badge → flex card-header 안 round image
- Figma `zoom: 0.49213` absolute positioning → Phase Z flex column (zone fit)
- Figma 7 bullets absolute layout → flex column gap auto spacing
─────────────────────────────────────────────────────────────────────────────
min_height_px derivation (round 13 §2.2 — derive + confirm) :
Figma frame 1927 px @ scale 0.49213 → 948 px adapted (full Figma fit).
Phase Z slide-body ≤ 585 px → adaptive content fit.
Content density (3 col × 7 bullets + badge + photo) → F29 (345) 보다 약간 ↑.
Derived = 320 (badge 30 + bullet body ~210 + photo strip ~50 + padding 30).
Confirm via smoke + V2 validation (MDX 02 sample run).
─────────────────────────────────────────────────────────────────────────────
slots : title, personas[].{label, body, color_class}
- color_class ∈ {client, constructor, designer} (role_order 따라)
- body = list[{text:str, indent:int}] (parse_quadrant_item 출력)
- persona suffix "목표" = frame 의 visual 언어 (slot 미사용, partial 노출)
─────────────────────────────────────────────────────────────────────────────
Asset path runtime resolution :
Phase Z `copy_assets(template_id, run_dir)` (phase_z2_pipeline.py:746) copies
figma_to_html_agent/blocks/1171281191/assets/ → {run_dir}/assets/three_persona_benefits/
→ partial 의 src="assets/three_persona_benefits/<filename>.png" 가 runtime 에서 resolve.
#}
<style>
.f14b {
width: 100%; height: 100%;
display: flex; flex-direction: column;
gap: 6px;
font-family: 'Noto Sans KR', 'Pretendard', sans-serif;
word-break: keep-all;
}
.f14b__title {
font-size: var(--font-zone-title);
font-weight: 700;
line-height: var(--lh-zone-title);
background-image: linear-gradient(180deg, #000 0%, #883700 100%);
-webkit-background-clip: text; background-clip: text;
color: transparent;
flex-shrink: 0;
filter: drop-shadow(0 0 3px rgba(50,44,30,0.4));
}
.f14b__cols {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
flex: 1 1 auto;
min-height: 0;
}
.f14b__col {
position: relative;
display: flex; flex-direction: column;
border: 2px solid;
border-radius: 12px;
overflow: hidden;
min-height: 0;
isolation: isolate;
}
/* col-bg 텍스처 (PROMOTED raster) */
.f14b__col::before {
content: ""; position: absolute; inset: 0;
background: url("assets/three_persona_benefits/4a17cd1dddaba8a220b706df3ec052d2bfde4f47.png") center/cover no-repeat;
opacity: 0.6;
z-index: -2;
}
/* col-overlay (CSS solid tint per persona — index.html L44-47) */
.f14b__col::after {
content: ""; position: absolute; inset: 0;
opacity: 0.8;
z-index: -1;
}
.f14b__col--client { border-color: #285b4a; }
.f14b__col--constructor { border-color: #445a2f; }
.f14b__col--designer { border-color: #743002; }
.f14b__col--client::after { background: #d6e7c4; } /* PROMOTED CSS */
.f14b__col--constructor::after { background: #e1efe1; } /* PROMOTED CSS */
.f14b__col--designer::after { background: #d0c0ad; } /* PROMOTED CSS */
/* badge — PROMOTED raster (outer + inner ring image, name + 목표 text overlay) */
.f14b__badge {
position: relative;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
padding: 6px;
flex-shrink: 0;
aspect-ratio: 1 / 1;
width: 70px; height: 70px;
margin: 6px auto 4px;
}
.f14b__badge-outer, .f14b__badge-inner {
position: absolute; inset: 0;
width: 100%; height: 100%;
object-fit: contain;
}
.f14b__badge-inner {
width: 78%; height: 78%;
top: 11%; left: 11%;
}
.f14b__badge-text {
position: relative; z-index: 1;
display: flex; flex-direction: column;
align-items: center;
text-align: center;
line-height: 1;
}
.f14b__badge-name {
font-size: var(--font-caption);
font-weight: 700;
letter-spacing: -0.04em;
}
.f14b__badge-suffix {
font-size: 0.65rem;
font-weight: 500;
margin-top: 2px;
opacity: 0.85;
}
.f14b__col--client .f14b__badge-text { color: #285b4a; }
.f14b__col--constructor .f14b__badge-text { color: #445a2f; }
.f14b__col--designer .f14b__badge-text { color: #743002; }
/* body — bullet list. check marker CSS (PROMOTED CSS, raster 6896d5c2 와 동등) */
.f14b__body {
flex: 1 1 auto;
overflow: hidden;
padding: 4px 10px;
color: #1a1a1a;
min-height: 0;
display: flex; flex-direction: column;
gap: 3px;
}
.f14b__body .text-line {
color: inherit;
font-size: var(--font-body);
line-height: var(--lh-body);
position: relative;
padding-left: 14px;
}
.f14b__body .text-line--bullet::before {
content: "\2713";
position: absolute;
left: 0; top: 0;
font-weight: 700;
}
.f14b__col--client .f14b__body .text-line--bullet::before { color: #285b4a; }
.f14b__col--constructor .f14b__body .text-line--bullet::before { color: #445a2f; }
.f14b__col--designer .f14b__body .text-line--bullet::before { color: #743002; }
/* bottom photo — PROMOTED raster (per persona 실사 사진, CSS 불가) */
.f14b__photo {
flex-shrink: 0;
width: 100%; height: 36px;
overflow: hidden;
border-radius: 0 0 8px 8px;
margin-top: 2px;
}
.f14b__photo img {
width: 100%; height: 100%;
object-fit: cover;
opacity: 0.7; /* index.html L53 — opacity 0.70 */
display: block;
}
</style>
<div class="f14b" data-frame-id="1171281191" data-template-id="three_persona_benefits">
<div class="f14b__title">{{ slot_payload.title }}</div>
<div class="f14b__cols">
{% for persona in slot_payload.personas %}
<div class="f14b__col f14b__col--{{ persona.color_class }}">
{# badge — raster outer/inner + CSS text overlay #}
<div class="f14b__badge">
{% if persona.color_class == "client" %}
<img class="f14b__badge-outer" src="assets/three_persona_benefits/77f319979c880da34ff3d423fcd97827f636c01e.png" alt="">
<img class="f14b__badge-inner" src="assets/three_persona_benefits/e64c967dd00302bfbef6cfbcbb4f7a4db5d9d96c.png" alt="">
{% elif persona.color_class == "constructor" %}
<img class="f14b__badge-outer" src="assets/three_persona_benefits/1550ec755fa7922dcfc1c90135a570d6b9df82cc.png" alt="">
<img class="f14b__badge-inner" src="assets/three_persona_benefits/85beaf9dfc17b7ed4620729a086ba22143606517.png" alt="">
{% elif persona.color_class == "designer" %}
<img class="f14b__badge-outer" src="assets/three_persona_benefits/9ac089fa9c5106b6b26d47727003641bb56ba4b0.png" alt="">
<img class="f14b__badge-inner" src="assets/three_persona_benefits/4b534ccf4e945fbe7436a0d8d96a6deffcfe5cef.png" alt="">
{% endif %}
<div class="f14b__badge-text">
<span class="f14b__badge-name">{{ persona.label | safe }}</span>
<span class="f14b__badge-suffix">목표</span>
</div>
</div>
{# body — bullets with CSS check marker #}
<div class="f14b__body">
{% if persona.body %}
{% for line in persona.body %}<div class="text-line text-line--bullet{% if line.indent > 0 %} text-line--indent-{{ line.indent }}{% endif %}">{{ line.text | safe }}</div>{% endfor %}
{% endif %}
</div>
{# bottom photo — per persona 실사 사진 #}
<div class="f14b__photo">
{% if persona.color_class == "client" %}
<img src="assets/three_persona_benefits/d2c070f200af83f563976b6b0f309d38321d204d.png" alt="">
{% elif persona.color_class == "constructor" %}
<img src="assets/three_persona_benefits/2a6a58e7bf7a645b5ede65115feb2890ccc414d1.png" alt="">
{% elif persona.color_class == "designer" %}
<img src="assets/three_persona_benefits/39113493f6e3ae76d766e86e293b0f0dcbf55d91.png" alt="">
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>