add: figma_to_html_agent/blocks/ + 변환 도구 docs 갱신
전체 401 files (397 추가 + 4 수정), 14304 insertions.
추가:
- figma_to_html_agent/blocks/ — Figma 변환 결과 (32 frame, ~79MB).
각 frame folder = {analysis.md, flat.md, texts.md, index.html, assets/,
_renders/, _render.py, RELATIONSHIPS.md / STATUS.md / classification.md
(일부 frame)}.
Phase Z 의 *figma source layer* — runtime 에서 직접 사용 X, contract /
partial / builder adapter (미래 axis A) 의 source.
- figma_to_html_agent/DISCUSSION-SUMMARY-20260411.md — 변환 설계 회의 기록.
- figma_to_html_agent/HARNESS.md — 변환 검증 harness.
- figma_to_html_agent/scripts/fetch_figma_screenshots.py — Figma 스크린샷 자동 수집.
수정:
- figma_to_html_agent/PROCESS-CONTROL.md / PROCESS.md / RULES.md —
변환 프로세스 / 룰 갱신 (R8/R9 lock 강화 등).
- figma_to_html_agent/blocks_index.md — 32 frame 인덱스 갱신.
Phase Z 영향 0 (figma_to_html_agent/blocks/ 가 V4 catalog +
templates/phase_z2/families adapter 의 source — runtime 에서 직접 import X).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86
figma_to_html_agent/blocks/1171281198/_compare.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""HTML 렌더 + Figma MCP 데이터 기반 정밀 비교"""
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from PIL import Image
|
||||
import os, time, json
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
renders = os.path.join(here, '_renders')
|
||||
os.makedirs(renders, exist_ok=True)
|
||||
|
||||
# 1. 큰 viewport로 띄워서 높은 해상도 렌더 (zoom 1.0으로)
|
||||
opts = Options()
|
||||
opts.add_argument('--headless=new')
|
||||
opts.add_argument('--hide-scrollbars')
|
||||
opts.add_argument('--force-device-scale-factor=1')
|
||||
opts.add_argument('--window-size=1920,1200')
|
||||
d = webdriver.Chrome(options=opts)
|
||||
|
||||
p = os.path.join(here, 'index.html').replace(os.sep, '/')
|
||||
d.get('file:///' + p)
|
||||
|
||||
# 폰트 + 이미지 모두 로드 대기
|
||||
d.execute_script("""
|
||||
return Promise.all([
|
||||
document.fonts.ready,
|
||||
...Array.from(document.images).map(img =>
|
||||
img.complete ? Promise.resolve() : new Promise(r => { img.onload = img.onerror = r; })
|
||||
)
|
||||
]);
|
||||
""")
|
||||
time.sleep(2.0)
|
||||
|
||||
# 모든 핵심 요소의 computed style + bounding rect 측정
|
||||
data = d.execute_script("""
|
||||
const out = {};
|
||||
const selectors = [
|
||||
'.title-text',
|
||||
'.title-text .green',
|
||||
'.title-text .white',
|
||||
'.card-title-1',
|
||||
'.card-title-2',
|
||||
'.card-title-3',
|
||||
'.body-card-1',
|
||||
'.body-card-2-p1',
|
||||
'.body-card-3',
|
||||
'.dx-circle img',
|
||||
'.bullet-1-1 img',
|
||||
'.card-1-frame img',
|
||||
'.card-1-header img'
|
||||
];
|
||||
for (const sel of selectors) {
|
||||
const el = document.querySelector(sel);
|
||||
if (!el) { out[sel] = 'NOT FOUND'; continue; }
|
||||
const r = el.getBoundingClientRect();
|
||||
const cs = getComputedStyle(el);
|
||||
out[sel] = {
|
||||
rect: { x: r.x, y: r.y, w: r.width, h: r.height },
|
||||
color: cs.color,
|
||||
fontSize: cs.fontSize,
|
||||
fontWeight: cs.fontWeight,
|
||||
fontFamily: cs.fontFamily,
|
||||
backgroundImage: cs.backgroundImage.length > 100 ? cs.backgroundImage.slice(0,100)+'...' : cs.backgroundImage,
|
||||
webkitTextFillColor: cs.webkitTextFillColor,
|
||||
text: el.textContent ? el.textContent.slice(0, 50) : null
|
||||
};
|
||||
}
|
||||
return out;
|
||||
""")
|
||||
print(json.dumps(data, indent=2, ensure_ascii=False))
|
||||
|
||||
# 풀 해상도 스크린샷
|
||||
full_png = os.path.join(renders, '_compare_full.png')
|
||||
d.save_screenshot(full_png)
|
||||
|
||||
# slide만 잘라서 저장
|
||||
r = d.execute_script(
|
||||
'const r=document.querySelector(".slide").getBoundingClientRect();'
|
||||
'return [r.x,r.y,r.width,r.height];'
|
||||
)
|
||||
print('\nslide bounds:', r)
|
||||
Image.open(full_png).crop(
|
||||
(int(r[0]), int(r[1]), int(r[0]+r[2]), int(r[1]+r[3]))
|
||||
).save(os.path.join(renders, 'slide_v2.png'))
|
||||
|
||||
d.quit()
|
||||
print('\nSaved:', os.path.join(renders, 'slide_v2.png'))
|
||||
81
figma_to_html_agent/blocks/1171281198/_diff.py
Normal file
@@ -0,0 +1,81 @@
|
||||
"""Figma 원본 vs HTML 렌더 정밀 diff
|
||||
- selenium으로 HTML을 1280px 폭으로 정확히 렌더 (slide만)
|
||||
- Figma get_screenshot 응답 화면을 미리 저장한 figma_ref.png로 비교
|
||||
"""
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import os, time, urllib.request
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
renders = os.path.join(here, '_renders')
|
||||
|
||||
# ──────────────────────────
|
||||
# 1. HTML을 1280×426 정확히 캡처 (block만)
|
||||
# ──────────────────────────
|
||||
opts = Options()
|
||||
opts.add_argument('--headless=new')
|
||||
opts.add_argument('--hide-scrollbars')
|
||||
opts.add_argument('--force-device-scale-factor=1')
|
||||
opts.add_argument('--window-size=1600,900')
|
||||
d = webdriver.Chrome(options=opts)
|
||||
|
||||
p = os.path.join(here, 'index.html').replace(os.sep, '/')
|
||||
d.get('file:///' + p)
|
||||
d.execute_script("""
|
||||
return Promise.all([
|
||||
document.fonts.ready,
|
||||
...Array.from(document.images).map(img =>
|
||||
img.complete ? Promise.resolve() : new Promise(r => { img.onload = img.onerror = r; })
|
||||
)
|
||||
]);
|
||||
""")
|
||||
time.sleep(2.0)
|
||||
|
||||
full_png = os.path.join(renders, '_diff_full.png')
|
||||
d.save_screenshot(full_png)
|
||||
|
||||
block_rect = d.execute_script(
|
||||
'const r=document.querySelector(".block").getBoundingClientRect();'
|
||||
'return [Math.round(r.x), Math.round(r.y), Math.round(r.width), Math.round(r.height)];'
|
||||
)
|
||||
print('block:', block_rect)
|
||||
|
||||
block_img = Image.open(full_png).crop(
|
||||
(block_rect[0], block_rect[1], block_rect[0]+block_rect[2], block_rect[1]+block_rect[3])
|
||||
)
|
||||
block_path = os.path.join(renders, 'html_block.png')
|
||||
block_img.save(block_path)
|
||||
print(f'Saved html_block: {block_img.size}')
|
||||
|
||||
d.quit()
|
||||
|
||||
# ──────────────────────────
|
||||
# 2. Figma get_screenshot URL이 없으므로 — 별도로 figma_ref.png 가 있어야 함
|
||||
# (없으면 사용자에게 직접 캡처 요청)
|
||||
# ──────────────────────────
|
||||
figma_ref = os.path.join(here, 'figma_ref.png')
|
||||
if not os.path.exists(figma_ref):
|
||||
print(f'figma_ref.png NOT FOUND at {figma_ref}')
|
||||
print('=> Figma 원본 스크린샷 직접 저장 필요')
|
||||
else:
|
||||
figma_img = Image.open(figma_ref)
|
||||
print(f'figma_ref: {figma_img.size}')
|
||||
|
||||
# 둘 다 같은 폭 1280으로 리사이즈
|
||||
target_w = 1280
|
||||
h_block = block_img.height
|
||||
f_w, f_h = figma_img.size
|
||||
f_h_scaled = int(f_h * target_w / f_w)
|
||||
figma_resized = figma_img.resize((target_w, f_h_scaled), Image.LANCZOS)
|
||||
|
||||
# 위/아래로 합치기 (위: Figma, 아래: HTML)
|
||||
combined_h = f_h_scaled + h_block + 80
|
||||
combined = Image.new('RGB', (target_w, combined_h), 'white')
|
||||
draw = ImageDraw.Draw(combined)
|
||||
draw.text((10, 5), 'Figma 원본', fill='red')
|
||||
combined.paste(figma_resized, (0, 30))
|
||||
draw.text((10, 30 + f_h_scaled + 5), 'HTML 렌더 (block crop)', fill='red')
|
||||
combined.paste(block_img, (0, 30 + f_h_scaled + 30))
|
||||
combined.save(os.path.join(renders, 'side_by_side.png'))
|
||||
print(f'Saved side_by_side ({combined.size})')
|
||||
99
figma_to_html_agent/blocks/1171281198/_inspect.py
Normal file
@@ -0,0 +1,99 @@
|
||||
"""모든 title span 색상 + 위치 검증"""
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from PIL import Image
|
||||
import os, time, json
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
renders = os.path.join(here, '_renders')
|
||||
|
||||
opts = Options()
|
||||
opts.add_argument('--headless=new')
|
||||
opts.add_argument('--hide-scrollbars')
|
||||
opts.add_argument('--force-device-scale-factor=2') # 2x for higher resolution
|
||||
opts.add_argument('--window-size=1600,900')
|
||||
d = webdriver.Chrome(options=opts)
|
||||
|
||||
p = os.path.join(here, 'index.html').replace(os.sep, '/')
|
||||
d.get('file:///' + p)
|
||||
d.execute_script("""
|
||||
return Promise.all([
|
||||
document.fonts.ready,
|
||||
...Array.from(document.images).map(img =>
|
||||
img.complete ? Promise.resolve() : new Promise(r => { img.onload = img.onerror = r; })
|
||||
)
|
||||
]);
|
||||
""")
|
||||
time.sleep(2.0)
|
||||
|
||||
# 모든 title span 측정
|
||||
result = d.execute_script("""
|
||||
const out = [];
|
||||
// title 모든 span
|
||||
document.querySelectorAll('.title-text span').forEach((el, i) => {
|
||||
const r = el.getBoundingClientRect();
|
||||
const cs = getComputedStyle(el);
|
||||
out.push({
|
||||
type: 'title-span-' + i,
|
||||
text: el.textContent,
|
||||
color: cs.color,
|
||||
rect: {x: r.x, y: r.y, w: r.width, h: r.height},
|
||||
});
|
||||
});
|
||||
// 모든 card-title
|
||||
document.querySelectorAll('[class*="card-title-"]').forEach((el, i) => {
|
||||
const r = el.getBoundingClientRect();
|
||||
const cs = getComputedStyle(el);
|
||||
out.push({
|
||||
type: 'card-title-' + i,
|
||||
text: el.textContent.trim(),
|
||||
color: cs.color,
|
||||
fillColor: cs.webkitTextFillColor,
|
||||
bgImage: cs.backgroundImage.slice(0, 80),
|
||||
rect: {x: r.x, y: r.y, w: r.width, h: r.height},
|
||||
});
|
||||
});
|
||||
// body-card 위치/크기
|
||||
['.body-card-1', '.body-card-2-p1', '.body-card-2-p2', '.body-card-2-p3', '.body-card-3'].forEach(sel => {
|
||||
const el = document.querySelector(sel);
|
||||
if (el) {
|
||||
const r = el.getBoundingClientRect();
|
||||
out.push({
|
||||
type: 'body-' + sel,
|
||||
text: el.textContent.trim().slice(0, 40),
|
||||
rect: {x: r.x, y: r.y, w: r.width, h: r.height},
|
||||
});
|
||||
}
|
||||
});
|
||||
return out;
|
||||
""")
|
||||
print(json.dumps(result, indent=2, ensure_ascii=False))
|
||||
|
||||
# 2x screenshot
|
||||
full_png = os.path.join(renders, '_inspect_full_2x.png')
|
||||
d.save_screenshot(full_png)
|
||||
|
||||
# slide만 2x crop
|
||||
r = d.execute_script(
|
||||
'const dpr = window.devicePixelRatio;'
|
||||
'const r=document.querySelector(".slide").getBoundingClientRect();'
|
||||
'return [Math.round(r.x*dpr), Math.round(r.y*dpr), Math.round(r.width*dpr), Math.round(r.height*dpr)];'
|
||||
)
|
||||
Image.open(full_png).crop(
|
||||
(r[0], r[1], r[0]+r[2], r[1]+r[3])
|
||||
).save(os.path.join(renders, 'slide_hires.png'))
|
||||
|
||||
# title 영역만 zoom (title은 block 상단)
|
||||
b = d.execute_script(
|
||||
'const dpr = window.devicePixelRatio;'
|
||||
'const t=document.querySelector(".title-text").getBoundingClientRect();'
|
||||
'return [Math.round(t.x*dpr), Math.round(t.y*dpr), Math.round(t.width*dpr), Math.round(t.height*dpr)];'
|
||||
)
|
||||
Image.open(full_png).crop(
|
||||
(b[0]-20, b[1]-20, b[0]+b[2]+20, b[1]+b[3]+20)
|
||||
).save(os.path.join(renders, 'title_zoom.png'))
|
||||
|
||||
d.quit()
|
||||
print('\nSaved:')
|
||||
print(' - slide_hires.png')
|
||||
print(' - title_zoom.png')
|
||||
51
figma_to_html_agent/blocks/1171281198/_render.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from PIL import Image
|
||||
import os, time
|
||||
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
renders = os.path.join(here, '_renders')
|
||||
os.makedirs(renders, exist_ok=True)
|
||||
|
||||
opts = Options()
|
||||
opts.add_argument('--headless=new')
|
||||
opts.add_argument('--hide-scrollbars')
|
||||
opts.add_argument('--force-device-scale-factor=1')
|
||||
opts.add_argument('--window-size=1600,900')
|
||||
d = webdriver.Chrome(options=opts)
|
||||
|
||||
p = os.path.join(here, 'index.html').replace(os.sep, '/')
|
||||
d.get('file:///' + p)
|
||||
# 폰트 + 이미지 모두 로드될 때까지 대기
|
||||
d.execute_script("""
|
||||
return Promise.all([
|
||||
document.fonts.ready,
|
||||
...Array.from(document.images).map(img =>
|
||||
img.complete ? Promise.resolve() : new Promise(r => { img.onload = img.onerror = r; })
|
||||
)
|
||||
]);
|
||||
""")
|
||||
time.sleep(1.0)
|
||||
full_png = os.path.join(renders, '_full.png')
|
||||
d.save_screenshot(full_png)
|
||||
|
||||
r = d.execute_script(
|
||||
'const r=document.querySelector(".slide").getBoundingClientRect();'
|
||||
'return [r.x,r.y,r.width,r.height];'
|
||||
)
|
||||
print('slide bounds:', r)
|
||||
Image.open(full_png).crop(
|
||||
(int(r[0]), int(r[1]), int(r[0]+r[2]), int(r[1]+r[3]))
|
||||
).save(os.path.join(renders, 'slide.png'))
|
||||
|
||||
b = d.execute_script(
|
||||
'const r=document.querySelector(".block").getBoundingClientRect();'
|
||||
'return [r.x,r.y,r.width,r.height];'
|
||||
)
|
||||
print('block bounds:', b)
|
||||
Image.open(full_png).crop(
|
||||
(int(b[0]), int(b[1]), int(b[0]+b[2]), int(b[1]+b[3]))
|
||||
).save(os.path.join(renders, 'block.png'))
|
||||
|
||||
d.quit()
|
||||
print('OK')
|
||||
BIN
figma_to_html_agent/blocks/1171281198/_renders/_compare_full.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 44 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_diff_full.png
Normal file
|
After Width: | Height: | Size: 194 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_full.png
Normal file
|
After Width: | Height: | Size: 221 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_hires2.png
Normal file
|
After Width: | Height: | Size: 532 KiB |
|
After Width: | Height: | Size: 65 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_hires2_slide.png
Normal file
|
After Width: | Height: | Size: 492 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_hires_full.png
Normal file
|
After Width: | Height: | Size: 458 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_hires_header.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_hires_slide.png
Normal file
|
After Width: | Height: | Size: 437 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_hires_titles.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 443 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/_sidebyside.png
Normal file
|
After Width: | Height: | Size: 516 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/block.png
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/html_block.png
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/slide.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/slide_2x.png
Normal file
|
After Width: | Height: | Size: 771 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/slide_hires.png
Normal file
|
After Width: | Height: | Size: 435 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/slide_v2.png
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
figma_to_html_agent/blocks/1171281198/_renders/title_zoom.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
64
figma_to_html_agent/blocks/1171281198/analysis.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Frame 1171281198 — 디지털 전환(DX)은 S/W가 필수다
|
||||
|
||||
## 내용 설명
|
||||
|
||||
디지털 전환(DX) 실현을 위해 S/W가 필수임을 BIM·디지털·전면설계의
|
||||
3가지 관점 카드로 설명하는 디자인. 3열 카드 헤더 라벨 + 카드별
|
||||
본문 구조로 고부가가치 실현 논거를 전개. 이 디자인은 BIM과 DX를
|
||||
서로 비교하는 것이 아니라, DX를 주 서사로 두고 S/W 필수성을 3관점
|
||||
으로 뒷받침하는 구조. DX·S/W 필수성 서사·BIM/디지털/전면설계 3관점
|
||||
병렬 전개·고부가가치 실현 논거에 적합.
|
||||
BIM vs DX 다면 비교 (Frame 18)·단순 2개 개념 대조·시간 순서·
|
||||
4개 이상 항목에는 부적합.
|
||||
|
||||
## 후보 키워드
|
||||
|
||||
DX, S/W, 필수, BIM, 디지털, 전면설계, 고부가가치, 실현
|
||||
|
||||
## 정제 Anchor Sets
|
||||
|
||||
- **dx_sw_necessity**: DX, S/W, 필수, 필수
|
||||
- **three_design_perspectives**: BIM, 디지털, 전면설계
|
||||
- **high_value_goal**: 고부가가치, 실현
|
||||
|
||||
## 구조 매칭 정보
|
||||
|
||||
- **family**: cards
|
||||
- **layout**: cards-3-header
|
||||
- **axis**: horizontal
|
||||
- **relation_type**: parallel
|
||||
- **cardinality**: ideal 3 / min 3 / max 3
|
||||
- **slots** (7개, required 7개): title, perspective_1_label, perspective_1_body, perspective_2_label, perspective_2_body, perspective_3_label, perspective_3_body
|
||||
- **source title**: 디지털 전환(DX)은 S/W가 필수다
|
||||
- **original layout**: 3col-cards
|
||||
|
||||
## 적합/부적합 기준
|
||||
|
||||
### suits
|
||||
- DX와 S/W 필수성 서사
|
||||
- BIM/디지털/전면설계 3관점
|
||||
- 고부가가치 실현 논거
|
||||
|
||||
### not_suits
|
||||
- 2개 개념 다면 비교
|
||||
- BIM vs DX 직접 대조
|
||||
- 시간 순서
|
||||
- 4개 이상 항목
|
||||
- 단일 관점 심층
|
||||
- 문제/약점 진단 (부정형)
|
||||
|
||||
## 재구성 허용
|
||||
|
||||
- **split**: False
|
||||
- **merge**: False
|
||||
- **infer_missing_slot**: False
|
||||
- **rewrite_label**: True
|
||||
- **rewrite_body**: True
|
||||
|
||||
## 메타
|
||||
|
||||
- schema_version: template-fit-v1 mirror
|
||||
- source_of_truth: structure_ontology.yaml + keyword_base.yaml
|
||||
- structure_content_original_tagged_by: claude-opus-4-7 (2026-04-21)
|
||||
- keyword_base_sync_at: 2026-04-22
|
||||
- anchor_sets_cleaned_at: 2026-04-22
|
||||
@@ -0,0 +1,17 @@
|
||||
# Frame 1171281198 — 디지털 전환(DX)은 S/W가 필수다
|
||||
|
||||
## 구조
|
||||
- **layout**: 3col-cards
|
||||
- **detail**: 타이틀("디지털 전환(DX)은 S/W가 필수다") + 3열 카드 헤더(상단 라벨) + 카드별 내용
|
||||
|
||||
## 내용
|
||||
디지털 전환(DX) 실현을 위한 S/W 필수성 — BIM·디지털·전면설계 관점에서 고부가가치 실현을 3열 카드로 정리.
|
||||
|
||||
## 후보 키워드
|
||||
디지털전환, DX, S/W필수, BIM, 디지털, 전면설계, 고부가가치, 3열카드, DX전환
|
||||
|
||||
## 메타
|
||||
- source: texts.md + flat.md
|
||||
- schema_version: analysis-v1
|
||||
- tagged_by: claude-opus-4-7
|
||||
- tagged_at: 2026-04-21
|
||||
BIN
figma_to_html_agent/blocks/1171281198/assets/body_bg.png
Normal file
|
After Width: | Height: | Size: 296 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/bullet_arrow.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 30 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/card_frame.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/card_header_bg.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/dx_circle.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/hanmaek_label.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/header_center.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/header_decor.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/header_full.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/header_left.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/header_right.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/left_bg.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/left_decor.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/left_inner_bg.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
figma_to_html_agent/blocks/1171281198/assets/middle_overlay.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
124
figma_to_html_agent/blocks/1171281198/flat.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Frame 1171281198 — 실측 기록 (flat)
|
||||
|
||||
> 원본: 2734.634 × 910.775 px (node 182:2766, file 9S6LsQyO6zlRxtiqZccOUM, page 29:373)
|
||||
> 패턴: dx-banner-with-3perspective-cards (상단 다크 그린 배너 + 좌측 DX 원형 라벨 + 우측 3 카드)
|
||||
> Scale: **min(1280/2734.6, 720/910.8) = 1280/2734.6 = 0.46810** (width fit, 1280×426 block)
|
||||
|
||||
## 구조 (bottom-up)
|
||||
|
||||
```
|
||||
Frame 182:2766 "Frame 1171281198" (2734.634 × 910.775)
|
||||
│
|
||||
├─ ① 상단 다크 그린 배너 (0~198)
|
||||
│ ├─ 182:2768 header_left.png (0, 0.99, 364×198) — 좌측 헤더 BG (대각선 패턴)
|
||||
│ ├─ 182:2769 header_center.png (363, 0, 2007×198) — 중앙
|
||||
│ ├─ 182:2770 header_right.png (2369, 0, 366×198) — 우측
|
||||
│ ├─ 182:2771 image 3568 placeholder (539, 19.74, 1748×145) — design_context에 src 없음, 무시
|
||||
│ ├─ 182:2772 header_decor.png (30.94, 37.51, 127×114) — 좌측 데코
|
||||
│ └─ 182:2773 header_decor.png (2585.11, 68.11, 127×114) — 우측 데코 (rotate-180)
|
||||
│
|
||||
├─ ② 타이틀 (배너 위 텍스트)
|
||||
│ └─ 182:2774 TEXT "디지털 전환(DX)은 S/W가 필수다."
|
||||
│ center=(1369.38, 96.24) → top-left=(3.6, 0.98)
|
||||
│ w=2730.503, h=190.518
|
||||
│ 90px Bold, line-height 65, text-align center
|
||||
│ "디지털 전환(DX)" #90FA33 (green) / "은" white / " S/W" green / "가 필수다." white
|
||||
│
|
||||
├─ ③ 본문 영역 (164~910)
|
||||
│ │
|
||||
│ ├─ 좌측 DX 원형 영역 (164~880, x=0~620)
|
||||
│ │ ├─ 182:2776 body_bg.png (1.03, 196.09, 2733.6×508) — 본문 BG
|
||||
│ │ ├─ 182:2777 middle_overlay.png (805.34, 263.21, 1897×648, opacity 0.8)
|
||||
│ │ ├─ 182:2778 left_bg.png (127.86, 164.5, 888×720)
|
||||
│ │ ├─ 182:2779 left_decor.png (4.13, 233.6, 612×639) — scaleY(-1) + rotate(90)
|
||||
│ │ ├─ 182:2780 left_inner_bg.png (27.84, 256.3, 591×566)
|
||||
│ │ ├─ 182:2781 hanmaek_label.png (142.3, 374.76, 56×32, opacity 0.9)
|
||||
│ │ └─ 182:2782 dx_circle.png (28.87, 378.71, 592×320) — "DX를 위한 S/W" 텍스트 포함된 원형 이미지
|
||||
│ │
|
||||
│ ├─ 우측 3 카드 영역 (310~880, x=913~2596)
|
||||
│ │ ├─ Card 1 (BIM 전면설계, x=913) green tone
|
||||
│ │ │ ├─ 182:2783 card_frame.png (913, 310, 515×378) — 카드 outline frame (orange/green)
|
||||
│ │ │ ├─ 182:2786 card_header_bg.png (974, 310, 378×86) — 헤더 BG (label 배경)
|
||||
│ │ │ ├─ 182:2787 card_bottom_decor.png (913, 642, 515×186)
|
||||
│ │ │ ├─ 182:2792 TEXT "BIM 전면설계" — 40px Bold gradient #296B55→#123328
|
||||
│ │ │ │ center=(1164.18, 323.43+32.08=355.51) → top-left=(969, 323)
|
||||
│ │ │ ├─ 182:2796 본문 텍스트 (989.91, 450.77, 426×334) — 37px Medium black, 5 단락
|
||||
│ │ │ │ "건설산업 생산성 향상" / blank / "고부가가치 산업으로의 전환" / blank /
|
||||
│ │ │ │ "건설산업의 디지털전환(DX)\n체계 마련 및 고도화 필요"
|
||||
│ │ │ └─ 3 bullet icons (936.29, 461.63 / 936.29, 543.56 / 936.29, 622.53) 41×39
|
||||
│ │ │
|
||||
│ │ ├─ Card 2 (디지털 전환 S/W, x=1500) orange tone
|
||||
│ │ │ ├─ 182:2784 card_frame.png (1500, 310, 515×377)
|
||||
│ │ │ ├─ 182:2788 card_header_bg.png (1558, 310, 378×86)
|
||||
│ │ │ ├─ 182:2789 card_bottom_decor.png (1500, 642, 515×186)
|
||||
│ │ │ ├─ 182:2793 TEXT "디지털 전환 S/W" — 40px Bold gradient #CC5200→#8D3900
|
||||
│ │ │ ├─ 182:2797 "노동집약형 업무 탈피" (1570, 450, 453×60) — 37px Medium
|
||||
│ │ │ ├─ 182:2808 "S/W의 지속적인 고도화 필요" (1571, 530, 453×63) — 37px Medium
|
||||
│ │ │ ├─ 182:2809 "충분한 투자(인력, 비용, 시간 등)와 엔지니어의 적극적 동참" (1568, 612, 453×120)
|
||||
│ │ │ │ — 37px Medium + 30px (인력, 비용, 시간 등)
|
||||
│ │ │ └─ 3 bullet icons (1520.96, 461 / 1520.96, 543 / 1520.96, 625) 41×39
|
||||
│ │ │
|
||||
│ │ └─ Card 3 (고부가가치 산업전환, x=2080) green tone
|
||||
│ │ ├─ 182:2785 card_frame.png (2080, 310, 515×377)
|
||||
│ │ ├─ 182:2790 card_header_bg.png (2141, 310, 378×86)
|
||||
│ │ ├─ 182:2791 card_bottom_decor.png (2081, 642, 515×186)
|
||||
│ │ ├─ 182:2794 TEXT "고부가가치 산업전환" — 40px Bold gradient #296B55→#123328
|
||||
│ │ ├─ 182:2798 본문 (2154, 450, 442×334) — 37px Medium, 3 단락
|
||||
│ │ │ "기본기술의 이해 & 발전 필요" / blank /
|
||||
│ │ │ "업무 본질에 대한 깊은 이해를 바탕으로 창의적 아이디어 발현" / blank /
|
||||
│ │ │ "업무환경 개선과 DX를 통한\nProcess 혁신과 Product 개선"
|
||||
│ │ └─ 3 bullet icons (2101, 461 / 2101, 543 / 2101, 678) 41×39
|
||||
```
|
||||
|
||||
## 에셋 (15개)
|
||||
|
||||
| 파일 | 의미 | 크기 | 사용 |
|
||||
|------|------|------|------|
|
||||
| `header_left.png` | 좌측 다크 그린 헤더 BG (대각선 패턴) | 364×198 | 1× |
|
||||
| `header_center.png` | 중앙 다크 그린 헤더 BG | 2007×198 | 1× |
|
||||
| `header_right.png` | 우측 다크 그린 헤더 BG | 366×198 | 1× |
|
||||
| `header_decor.png` | 헤더 좌/우 작은 데코 (사각형 군) | 127×114 | 2× (우측은 rotate-180) |
|
||||
| `body_bg.png` | 본문 BG | 2733×508 | 1× |
|
||||
| `middle_overlay.png` | 중앙 BG 오버레이 | 1897×648 | 1× (opacity 0.8) |
|
||||
| `left_bg.png` | 좌측 영역 BG | 888×720 | 1× |
|
||||
| `left_decor.png` | 좌측 데코 | 612×639 | 1× (scaleY(-1) + rotate(90)) |
|
||||
| `left_inner_bg.png` | 좌측 내부 BG | 591×566 | 1× |
|
||||
| `hanmaek_label.png` | 한맥기술 작은 라벨 | 56×32 | 1× (opacity 0.9) |
|
||||
| `dx_circle.png` | "DX를 위한 S/W" 텍스트 포함 원형 이미지 | 592×320 | 1× |
|
||||
| `card_frame.png` | 카드 외곽 프레임 (orange/green border) | 515×378 | **3×** |
|
||||
| `card_header_bg.png` | 카드 상단 라벨 BG | 378×86 | **3×** |
|
||||
| `card_bottom_decor.png` | 카드 하단 데코 | 515×186 | **3×** |
|
||||
| `bullet_arrow.png` | 녹색 ▶ 화살표 (1171281209 공유) | 41×39 | **9×** |
|
||||
|
||||
## 이상 탐지 결과
|
||||
|
||||
| 검사 | 결과 |
|
||||
|------|------|
|
||||
| 회전 적용 | header_decor 우측 인스턴스 rotate-180; left_decor scaleY(-1) + rotate(90) |
|
||||
| Vector 좌표 metadata vs design_context | 일치 |
|
||||
| 중복 노드 | header_decor (2×), card_frame/header_bg/bottom_decor (3×), bullet_arrow (9×) — 정상 재사용 |
|
||||
| **누락 자산** | image 3568 (placeholder, src 없음) — 무시 |
|
||||
| **DX를 위한 S/W 텍스트** | 텍스트 노드 아님, dx_circle.png 안에 baked in. 1:1 변환에는 그대로 PNG 사용. 향후 템플릿화 시 CSS+텍스트 분리 검토 |
|
||||
|
||||
## 변형 가능 축
|
||||
|
||||
- **cards[N=3] (required)** — cardinality 3 고정 (analysis.md)
|
||||
- `card_label` (required, 40px Bold gradient — color depends on tone)
|
||||
- `card_color_palette` (required) — green (#296B55→#123328) 또는 orange (#CC5200→#8D3900)
|
||||
- `body_paragraphs[N=1~3]` (required) — 37px Medium, line-height 60
|
||||
- `body_bullets[N=3]` (required) — 녹색 ▶
|
||||
- `title` (required) — 90px Bold, 인라인 색상 변경 가능 (#90FA33 강조 + 흰색)
|
||||
- `header_decor_left/right` (optional) — 작은 사각형 군 데코
|
||||
- `dx_circle` (required for this layout) — 좌측 큰 원형 텍스트 이미지
|
||||
|
||||
## Sub-patterns
|
||||
|
||||
- `dark-green-banner-title` — 상단 다크 그린 배너 + 인라인 색상 강조 텍스트 (#90FA33)
|
||||
- `card-with-orange-frame-and-bullet-list` — 카드 외곽 프레임 PNG + 헤더 BG PNG + 본문 + ▶ 불릿
|
||||
- `bullet-paragraph-multiline-with-spacer` — 단락 사이에 빈 줄 패턴 (line-height 60 빈 paragraph)
|
||||
|
||||
## 임시 보정 (1:1, 템플릿화 시 재고려)
|
||||
|
||||
- 카드 프레임/헤더/하단 데코를 PNG로 유지 (CSS gradient/border-radius로 변환 가능 → 프로모션 시 검토)
|
||||
- 좌측 dx_circle은 텍스트가 baked-in 이미지라 동적 변경 불가 — 템플릿화 시 별도 CSS 처리 필요
|
||||
- 본문의 `tracking-[-X.YYpx]` 마이크로 letter-spacing 다수 — 자연 wrap에 맡길 것
|
||||
386
figma_to_html_agent/blocks/1171281198/index.html
Normal file
@@ -0,0 +1,386 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1280">
|
||||
<title>디지털 전환(DX)은 S/W가 필수다 (Frame 1171281198)</title>
|
||||
<!--
|
||||
Frame: 182:2766, 2734.634 × 910.775 px (Frame 1171281198)
|
||||
Source: file 9S6LsQyO6zlRxtiqZccOUM, page 29:373
|
||||
Scale: min(1280/2734.6, 720/910.8) = 1280/2734.6 = 0.46810 (width fit)
|
||||
Block in slide: 1280 × 426 px
|
||||
패턴: dx-banner-with-3perspective-cards
|
||||
-->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700;900&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'Noto Sans KR', sans-serif;
|
||||
background: #e8ecf0;
|
||||
display: flex; justify-content: center; align-items: center;
|
||||
min-height: 100vh;
|
||||
word-break: keep-all;
|
||||
}
|
||||
.slide {
|
||||
width: 1280px; height: 720px;
|
||||
background: #fff;
|
||||
position: relative; overflow: hidden;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,.15);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.block {
|
||||
width: 1280px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.inner {
|
||||
width: 2734.634px; height: 910.775px;
|
||||
position: relative;
|
||||
zoom: 0.46810;
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────────
|
||||
① 상단 배너 — 가로 그라디언트 (녹 → 갈)
|
||||
원본 3 PNG 들은 가장자리 alpha=0 (rounded corner) 이라 어떻게 합성해도 솔기 발생.
|
||||
샘플링한 색상 stop 으로 CSS linear-gradient 로 재현 (R8: 디자인 의도 명확한 배경 허용).
|
||||
──────────────────────────────────────────────── */
|
||||
.header-bg-full {
|
||||
position: absolute;
|
||||
left: 0; top: 0;
|
||||
width: 2735px; height: 199px;
|
||||
background: linear-gradient(90deg,
|
||||
rgb(15, 50, 30) 0%,
|
||||
rgb(23, 62, 47) 5%,
|
||||
rgb(29, 60, 45) 20%,
|
||||
rgb(36, 59, 43) 30%,
|
||||
rgb(41, 57, 41) 40%,
|
||||
rgb(46, 56, 39) 50%,
|
||||
rgb(51, 55, 38) 60%,
|
||||
rgb(54, 54, 36) 70%,
|
||||
rgb(57, 53, 35) 80%,
|
||||
rgb(59, 52, 35) 90%,
|
||||
rgb(60, 52, 34) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.header-decor-l, .header-decor-r {
|
||||
position: absolute;
|
||||
width: 127.864px; height: 114.508px;
|
||||
}
|
||||
.header-decor-l { left: 30.94px; top: 37.51px; }
|
||||
.header-decor-r { left: 2585.11px; top: 68.11px; transform: rotate(180deg); transform-origin: center; }
|
||||
.header-decor-l img, .header-decor-r img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
/* ② 타이틀 텍스트 */
|
||||
.title-text {
|
||||
position: absolute;
|
||||
/* center=(1369.38, 96.24), w=2730.503, h=190.518 */
|
||||
left: 3.6px; /* 1369.38 - 2730.503/2 */
|
||||
top: 0.98px; /* 96.24 - 190.518/2 */
|
||||
width: 2730.503px;
|
||||
height: 190.518px;
|
||||
font-family: 'Noto Sans KR', sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 90px;
|
||||
text-align: center;
|
||||
display: flex; flex-direction: column; justify-content: center;
|
||||
}
|
||||
.title-text > p { margin: 0; line-height: 65px; }
|
||||
.title-text .green { color: #90FA33; }
|
||||
.title-text .white { color: #ffffff; }
|
||||
|
||||
/* ③ 본문 영역 BG */
|
||||
.body-bg {
|
||||
position: absolute;
|
||||
left: 1.03px; top: 196.09px;
|
||||
width: 2733.6px; height: 508.377px;
|
||||
}
|
||||
.body-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.middle-overlay {
|
||||
position: absolute;
|
||||
left: 805.34px; top: 263.21px;
|
||||
width: 1897.331px; height: 647.564px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.middle-overlay img { width: 100%; height: 100%; object-fit: cover; opacity: 0.8; display: block; }
|
||||
|
||||
.left-bg {
|
||||
position: absolute;
|
||||
left: 127.86px; top: 164.5px;
|
||||
width: 888.858px; height: 719.625px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.left-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.left-decor {
|
||||
position: absolute;
|
||||
left: 4.13px; top: 233.6px;
|
||||
width: 639.318px; height: 612.027px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.left-decor-inner {
|
||||
width: 612.027px; height: 639.318px;
|
||||
transform: scaleY(-1) rotate(90deg);
|
||||
}
|
||||
.left-decor-inner img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.left-inner-bg {
|
||||
position: absolute;
|
||||
left: 27.84px; top: 256.3px;
|
||||
width: 591.885px; height: 566.618px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.left-inner-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.hanmaek-label {
|
||||
position: absolute;
|
||||
left: 142.3px; top: 374.76px;
|
||||
width: 56.714px; height: 32.576px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.hanmaek-label img { width: 100%; height: 100%; object-fit: cover; opacity: 0.9; display: block; }
|
||||
|
||||
.dx-circle {
|
||||
position: absolute;
|
||||
left: 28.87px; top: 378.71px;
|
||||
width: 592.916px; height: 320.82px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.dx-circle img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
/* ────────────────────────────────────────────────
|
||||
카드 (3개)
|
||||
──────────────────────────────────────────────── */
|
||||
.card-frame {
|
||||
position: absolute;
|
||||
width: 515.579px; height: 377.767px;
|
||||
}
|
||||
.card-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.card-header-bg {
|
||||
position: absolute;
|
||||
width: 378.435px; height: 85.881px;
|
||||
}
|
||||
.card-header-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
.card-bottom-decor {
|
||||
position: absolute;
|
||||
width: 515.579px; height: 185.746px;
|
||||
}
|
||||
.card-bottom-decor img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
|
||||
/* 카드 1 (BIM 전면설계, x=913) */
|
||||
.card-1-frame { left: 913.61px; top: 310.59px; }
|
||||
.card-1-header { left: 974.45px; top: 310.59px; }
|
||||
.card-1-decor { left: 913.61px; top: 642.27px; }
|
||||
|
||||
/* 카드 2 (디지털 전환 S/W, x=1500) */
|
||||
.card-2-frame { left: 1500.34px; top: 310.59px; height: 376.908px; }
|
||||
.card-2-header { left: 1558.08px; top: 310.59px; }
|
||||
.card-2-decor { left: 1500.34px; top: 642.27px; }
|
||||
|
||||
/* 카드 3 (고부가가치 산업전환, x=2080) */
|
||||
.card-3-frame { left: 2080.88px; top: 310.59px; height: 376.908px; }
|
||||
.card-3-header { left: 2141.71px; top: 310.59px; }
|
||||
.card-3-decor { left: 2081.91px; top: 642.27px; }
|
||||
|
||||
/* 카드 타이틀 — 40px Bold, 흰 fill + 컬러 stroke (Figma 실제 렌더 기준)
|
||||
design_context 가 잘못 알려준 dark gradient 가 아니라 시각 검증으로 확정 */
|
||||
.card-title {
|
||||
position: absolute;
|
||||
width: 389.778px; height: 64.164px;
|
||||
font-family: 'Noto Sans KR', sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 40px;
|
||||
line-height: 64.164px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
color: #ffffff;
|
||||
/* 외곽 다크 글로우 + 컬러 stroke (paint-order 로 fill 위에) */
|
||||
}
|
||||
.card-title-1 {
|
||||
/* center=(1164.18, 355.51) → top-left=(969.29, 323.43) */
|
||||
left: 969.29px; top: 323.43px;
|
||||
-webkit-text-stroke: 1.5px #1d4d3e;
|
||||
text-shadow: 0 0 4px #322c1e;
|
||||
paint-order: stroke fill;
|
||||
}
|
||||
.card-title-2 {
|
||||
/* center=(1743.69, 355.51) → top-left=(1548.8, 323.43) */
|
||||
left: 1548.8px; top: 323.43px;
|
||||
-webkit-text-stroke: 1.5px #cc5200;
|
||||
text-shadow: 0 0 4px #322c1e;
|
||||
paint-order: stroke fill;
|
||||
}
|
||||
.card-title-3 {
|
||||
/* center=(2336.6, 355.51) → top-left=(2141.71, 323.43) */
|
||||
left: 2141.71px; top: 323.43px;
|
||||
-webkit-text-stroke: 1.5px #1d4d3e;
|
||||
text-shadow: 0 0 4px #322c1e;
|
||||
paint-order: stroke fill;
|
||||
}
|
||||
|
||||
/* 본문 텍스트 — Figma leading-[0] + per-p leading-[60px] 패턴 */
|
||||
.body-text {
|
||||
position: absolute;
|
||||
font-family: 'Noto Sans KR', sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 37px;
|
||||
color: black;
|
||||
line-height: 0; /* 부모 leading-0 (Figma) — 자식 <p> 가 자기 leading 가짐 */
|
||||
}
|
||||
.body-text p { margin: 0; line-height: 60px; }
|
||||
.body-text p.blank { line-height: 60px; }
|
||||
.body-text p.blank::before { content: "\200B"; } /* zero-width-space — Figma의 와 동일 */
|
||||
|
||||
/* card 1 — 3 단락 절대좌표 (bullet top - 10.86 에 align) */
|
||||
.body-card-1-p1 {
|
||||
left: 989.91px; top: 450.77px; /* 1st bullet 461.63 - 10.86 */
|
||||
width: 426.233px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
.body-card-1-p3 {
|
||||
left: 989.91px; top: 532.70px; /* bullet 1.2 543.56 - 10.86 */
|
||||
width: 426.233px;
|
||||
letter-spacing: -0.48px;
|
||||
}
|
||||
.body-card-1-p5 {
|
||||
left: 989.91px; top: 611.67px; /* bullet 1.3 622.53 - 10.86 */
|
||||
width: 426.233px;
|
||||
letter-spacing: -0.48px;
|
||||
}
|
||||
|
||||
/* card 2 — 3 단락 (Figma 그대로 분리되어 있음) */
|
||||
.body-card-2-p1 {
|
||||
left: 1570.48px; top: 450.77px;
|
||||
width: 453.964px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
.body-card-2-p2 {
|
||||
left: 1571.49px; top: 530.77px;
|
||||
width: 453.964px;
|
||||
letter-spacing: -0.64px;
|
||||
}
|
||||
.body-card-2-p3 {
|
||||
left: 1568.11px; top: 612.29px;
|
||||
width: 453.964px;
|
||||
}
|
||||
.body-card-2-p3 .seg-37-tight { font-size: 37px; letter-spacing: -2.22px; }
|
||||
.body-card-2-p3 .seg-30 { font-size: 30px; letter-spacing: -1.8px; }
|
||||
.body-card-2-p3 .seg-37-loose { font-size: 37px; letter-spacing: -1.48px; }
|
||||
|
||||
/* card 3 — 4 그룹 절대좌표 (p3+p4 는 한 컨테이너로 연속, p6 는 br 으로 2줄) */
|
||||
.body-card-3-p1 {
|
||||
left: 2154.09px; top: 450.77px;
|
||||
width: 442.62px;
|
||||
letter-spacing: -1.48px;
|
||||
}
|
||||
.body-card-3-p3p4 {
|
||||
/* p3 "업무 본질..." 와 p4 "바탕으로..." 가 연속 (between blank 없음) */
|
||||
left: 2154.09px; top: 532.70px; /* bullet 3.2 543.56 - 10.86 */
|
||||
width: 442.62px;
|
||||
}
|
||||
.body-card-3-p3p4 .p3 { letter-spacing: -2.59px; }
|
||||
.body-card-3-p3p4 .p4 { letter-spacing: -2.96px; }
|
||||
.body-card-3-p6 {
|
||||
left: 2154.09px; top: 667.94px; /* bullet 3.3 678.8 - 10.86 */
|
||||
width: 442.62px;
|
||||
}
|
||||
.body-card-3-p6 .seg-37 { font-size: 37px; letter-spacing: -1.11px; }
|
||||
.body-card-3-p6 .seg-33 { font-size: 33px; letter-spacing: -0.99px; }
|
||||
|
||||
/* 불릿 (▶ 화살표 9개) */
|
||||
.bullet {
|
||||
position: absolute;
|
||||
width: 41.246px; height: 39.486px;
|
||||
}
|
||||
.bullet img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
.bullet-1-1 { left: 936.29px; top: 461.63px; }
|
||||
.bullet-1-2 { left: 936.29px; top: 543.56px; }
|
||||
.bullet-1-3 { left: 936.29px; top: 622.53px; }
|
||||
.bullet-2-1 { left: 1520.96px; top: 461.63px; }
|
||||
.bullet-2-2 { left: 1520.96px; top: 543.56px; }
|
||||
.bullet-2-3 { left: 1520.96px; top: 625.5px; }
|
||||
.bullet-3-1 { left: 2101.5px; top: 461.63px; }
|
||||
.bullet-3-2 { left: 2101.5px; top: 543.56px; }
|
||||
.bullet-3-3 { left: 2101.5px; top: 678.8px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="slide">
|
||||
<div class="block">
|
||||
<div class="inner">
|
||||
|
||||
<!-- ① 상단 배너 (가로 그라디언트, CSS) -->
|
||||
<div class="header-bg-full"></div>
|
||||
<div class="header-decor-l"><img src="assets/header_decor.png" alt=""></div>
|
||||
<div class="header-decor-r"><img src="assets/header_decor.png" alt=""></div>
|
||||
|
||||
<!-- ② 타이틀 -->
|
||||
<div class="title-text">
|
||||
<p><span class="green">디지털 전환(DX)</span><span class="white">은</span><span class="green"> S/W</span><span class="white">가 필수다.</span></p>
|
||||
</div>
|
||||
|
||||
<!-- ③ 본문 BG -->
|
||||
<div class="body-bg"><img src="assets/body_bg.png" alt=""></div>
|
||||
<div class="middle-overlay"><img src="assets/middle_overlay.png" alt=""></div>
|
||||
<div class="left-bg"><img src="assets/left_bg.png" alt=""></div>
|
||||
<div class="left-decor"><div class="left-decor-inner"><img src="assets/left_decor.png" alt=""></div></div>
|
||||
<div class="left-inner-bg"><img src="assets/left_inner_bg.png" alt=""></div>
|
||||
<div class="hanmaek-label"><img src="assets/hanmaek_label.png" alt=""></div>
|
||||
<div class="dx-circle"><img src="assets/dx_circle.png" alt=""></div>
|
||||
|
||||
<!-- 카드 1 — BIM 전면설계 -->
|
||||
<div class="card-frame card-1-frame"><img src="assets/card_frame.png" alt=""></div>
|
||||
<div class="card-header-bg card-1-header"><img src="assets/card_header_bg.png" alt=""></div>
|
||||
<div class="card-bottom-decor card-1-decor"><img src="assets/card_bottom_decor.png" alt=""></div>
|
||||
<div class="card-title card-title-1">BIM 전면설계</div>
|
||||
<div class="body-text body-card-1-p1"><p>건설산업 생산성 향상</p></div>
|
||||
<div class="body-text body-card-1-p3"><p>고부가가치 산업으로의 전환</p></div>
|
||||
<div class="body-text body-card-1-p5"><p>건설산업의 디지털전환(DX)<br>체계 마련 및 고도화 필요</p></div>
|
||||
<div class="bullet bullet-1-1"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
<div class="bullet bullet-1-2"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
<div class="bullet bullet-1-3"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
|
||||
<!-- 카드 2 — 디지털 전환 S/W -->
|
||||
<div class="card-frame card-2-frame"><img src="assets/card_frame.png" alt=""></div>
|
||||
<div class="card-header-bg card-2-header"><img src="assets/card_header_bg.png" alt=""></div>
|
||||
<div class="card-bottom-decor card-2-decor"><img src="assets/card_bottom_decor.png" alt=""></div>
|
||||
<div class="card-title card-title-2">디지털 전환 S/W</div>
|
||||
<div class="body-text body-card-2-p1"><p>노동집약형 업무 탈피</p></div>
|
||||
<div class="body-text body-card-2-p2"><p class="p1">S/W의 지속적인 고도화 필요</p></div>
|
||||
<div class="body-text body-card-2-p3">
|
||||
<p><span class="seg-37-tight">충분한 투자</span><span class="seg-30">(인력, 비용, 시간 등)</span><span class="seg-37-tight">와</span><span class="seg-37-loose"> 엔지니어의 적극적 동참</span></p>
|
||||
</div>
|
||||
<div class="bullet bullet-2-1"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
<div class="bullet bullet-2-2"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
<div class="bullet bullet-2-3"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
|
||||
<!-- 카드 3 — 고부가가치 산업전환 -->
|
||||
<div class="card-frame card-3-frame"><img src="assets/card_frame.png" alt=""></div>
|
||||
<div class="card-header-bg card-3-header"><img src="assets/card_header_bg.png" alt=""></div>
|
||||
<div class="card-bottom-decor card-3-decor"><img src="assets/card_bottom_decor.png" alt=""></div>
|
||||
<div class="card-title card-title-3">고부가가치 산업전환</div>
|
||||
<div class="body-text body-card-3-p1"><p>기본기술의 이해 & 발전 필요</p></div>
|
||||
<div class="body-text body-card-3-p3p4">
|
||||
<p class="p3">업무 본질에 대한 깊은 이해를</p>
|
||||
<p class="p4">바탕으로 창의적 아이디어 발현</p>
|
||||
</div>
|
||||
<div class="body-text body-card-3-p6">
|
||||
<p><span class="seg-37">업무환경 개선과 DX를 통한<br></span><span class="seg-33">Process</span><span class="seg-37"> 혁신과 </span><span class="seg-33">Product</span><span class="seg-37"> 개선</span></p>
|
||||
</div>
|
||||
<div class="bullet bullet-3-1"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
<div class="bullet bullet-3-2"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
<div class="bullet bullet-3-3"><img src="assets/bullet_arrow.png" alt="▶"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
figma_to_html_agent/blocks/1171281198/preview.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
40
figma_to_html_agent/blocks/1171281198/texts.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Frame 1171281198 — 텍스트 (TF-IDF 매칭용)
|
||||
|
||||
> 프레임 안의 모든 텍스트를 빠짐없이 추출.
|
||||
|
||||
## 타이틀
|
||||
|
||||
디지털 전환(DX)은 S/W가 필수다.
|
||||
|
||||
> "디지털 전환(DX)" 및 "S/W" 부분은 녹색(#90fa33), 나머지("은", "가 필수다.")는 흰색
|
||||
|
||||
## 3열 카드 헤더 (상단 라벨)
|
||||
|
||||
### 열1 헤더
|
||||
BIM 전면설계
|
||||
|
||||
### 열2 헤더
|
||||
디지털 전환 S/W
|
||||
|
||||
### 열3 헤더
|
||||
고부가가치 산업전환
|
||||
|
||||
## 본문 (3열 불릿 리스트)
|
||||
|
||||
### 열1 — BIM 전면설계
|
||||
|
||||
- 건설산업 생산성 향상
|
||||
- 고부가가치 산업으로의 전환
|
||||
- 건설산업의 디지털전환(DX) 체계 마련 및 고도화 필요
|
||||
|
||||
### 열2 — 디지털 전환 S/W
|
||||
|
||||
- 노동집약형 업무 탈피
|
||||
- S/W의 지속적인 고도화 필요
|
||||
- 충분한 투자(인력, 비용, 시간 등)와 엔지니어의 적극적 동참
|
||||
|
||||
### 열3 — 고부가가치 산업전환
|
||||
|
||||
- 기본기술의 이해 & 발전 필요
|
||||
- 업무 본질에 대한 깊은 이해를 바탕으로 창의적 아이디어 발현
|
||||
- 업무환경 개선과 DX를 통한 Process 혁신과 Product 개선
|
||||