Figma-to-HTML 에이전트 초기 커밋

- 10단계 변환 프로세스 (PROCESS.md)
- 수학 공식 레퍼런스 (MATH.md, gradient_math.py)
- CSS 보정 규칙 R1~R16 (RULES.md)
- 작업 규율 7개 규칙 (PROCESS-CONTROL.md)
- 8개 Figma 프레임 1:1 HTML 변환물 (block-tests/)
- 8개 Jinja2 템플릿 staging (templates_staging/)
- 변환 완료 도서관 + 디자인 인사이트 (blocks_index.md)
- 사용법 가이드 (README.md)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 11:16:33 +09:00
commit beb5fd0c61
205 changed files with 19164 additions and 0 deletions

View File

@@ -0,0 +1,475 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1280">
<title>BIM 목표 3원 블록 (Frame 1171281211) — Pure CSS</title>
<!--
============================================================
Figma → HTML 수학적 변환 (bottom-up, Pure CSS 버전)
============================================================
원본 Frame: 2062.205 × 956.998 px (node 66:310, Frame 1171281211)
타겟 슬라이드: 1280 × 720 px (16:9)
Scale factor S = 1280 / 2062.205 = 0.620694
블록 높이 = 956.998 × S ≈ 594 px
구현 전략:
1. CSS `transform: scale(0.620694)` 균일 축소 — 내부는 Figma 원본 좌표계(2062×957) 그대로
2. 모든 원은 **순수 HTML div + linear-gradient + mix-blend-mode: multiply**
- SVG 파일 의존 제거
- 블렌드는 브라우저 호환 가능한 multiply (원본 plus-darker는 Safari 전용)
3. 곡선 아크 3개만 SVG img로 유지 (CSS로 곡선 불가)
4. 배경 텍스처는 PNG img (실사 이미지)
그라데이션 수학적 도출:
SVG `<linearGradient x1 y1 x2 y2 gradientUnits="userSpaceOnUse">` 를
CSS `linear-gradient(Ndeg, color P%, color Q%)` 로 변환:
- 각도 = atan2(dy, dx) + 90° (SVG y-down → CSS from-12-o'clock-CW)
- stop % = 박스 중심의 t_center 기준 (L_css / 2) / L_svg 범위로 정규화
계산 코드: 본 프로젝트 내 Python svg_to_css() 스크립트 참조
플래튼 목록: frame_1171281211_flat.md
============================================================
-->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@500;700&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; /* 한글 단어 단위 줄바꿈 (전역 default) */
}
.slide {
width: 1280px; height: 720px;
background: #ffffff;
position: relative;
display: flex; justify-content: center; align-items: center;
box-shadow: 0 4px 20px rgba(0,0,0,.15);
}
.block {
width: 1280px;
height: 593.96px; /* 957 × 0.620694 */
background: #ffffff;
position: relative;
overflow: hidden;
}
/* Figma 원본 좌표계 유지, CSS transform으로 균일 축소 */
.inner {
position: absolute;
left: 0; top: 0;
width: 2062.205px;
height: 956.998px;
transform: scale(0.620694);
transform-origin: top left;
}
/* ─────────────────────────────────────────────────────────
레이어 1 — 배경 이미지 (실사 텍스처)
───────────────────────────────────────────────────────── */
.bg-texture {
position: absolute;
left: 139px; top: 683px;
width: 1768px; height: 274px;
mix-blend-mode: multiply;
pointer-events: none;
z-index: 0;
}
.bg-texture img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* ─────────────────────────────────────────────────────────
레이어 2 — 회전 그라데이션 데코 (66:306 → 66:309 → 64:245)
순수 CSS: gradient + border-radius + nested transforms
───────────────────────────────────────────────────────── */
.deco-wrap {
position: absolute;
left: 71px; top: 38px;
width: 685.475px; height: 836.277px;
display: flex; align-items: center; justify-content: center;
pointer-events: none;
z-index: 1;
}
.deco-rot { flex: none; transform: rotate(-120deg); }
.deco-flip { transform: scaleY(-1); }
.deco-rect {
width: 763px; height: 351px;
border-radius: 175.5px 0 0 175.5px;
background: linear-gradient(235.162deg,
rgba(115,115,115,0) 14.18%,
rgba(213,170,137,0.33) 66.964%);
}
/* ─────────────────────────────────────────────────────────
레이어 3 — 연결 아크 3개 (SVG img, 곡선 CSS 불가)
───────────────────────────────────────────────────────── */
.arc { position: absolute; z-index: 2; display: flex; align-items: center; justify-content: center; }
.arc img { display: block; flex: none; }
.arc--top { left: 926px; top: 134px; width: 209px; height: 99px; }
.arc--top img { width: 209px; height: 99px; transform: rotate(180deg); }
.arc--left { left: 627px; top: 549px; width: 99px; height: 209px; }
.arc--left img { width: 209px; height: 99px; transform: rotate(90deg); }
.arc--right { left: 1329px; top: 549px; width: 99px; height: 209px; }
.arc--right img { width: 209px; height: 99px; transform: rotate(-90deg); }
/* ─────────────────────────────────────────────────────────
레이어 4 — 메인 3원 (순수 CSS div, mix-blend-mode)
각 원 = outer 350×350 + inner ring (280 또는 290 w/ border)
outer: linear-gradient + mix-blend-mode: multiply
inner: linear-gradient + 5px white border (box-sizing border-box)
+ box-shadow (SVG drop-shadow stdDev 5 근사: 0 0 10px black)
───────────────────────────────────────────────────────── */
.big-outer {
position: absolute;
width: 350px; height: 350px;
border-radius: 50%;
/* Figma plus-darker → CSS multiply (Safari 외 호환) */
mix-blend-mode: multiply;
z-index: 3;
}
.big-outer--safety {
left: 853px; top: 206px;
background: linear-gradient(145.28deg, #FDC69E 16.04%, #E0782C 55.20%);
}
.big-outer--prod {
left: 694px; top: 480px;
background: linear-gradient(218.84deg, #D5AA89 14.08%, #737373 92.67%);
}
.big-outer--trust {
left: 1009px; top: 480px;
background: linear-gradient(145.90deg, #FFFFFF 8.47%, #253E1F 87.56%);
}
/* inner ring: 안전과 품질은 stroke가 fill 바깥 → 290 border-box */
.big-ring {
position: absolute;
border-radius: 50%;
box-shadow: 0 0 10px 0 rgba(0,0,0,1); /* SVG feGaussianBlur stdDev 5 ≈ CSS blur 10px */
z-index: 4;
}
.big-ring--safety {
/* Figma (887.06, 240.06) 280×280 → 290×290 at (-5,-5) (stroke 5 outside) */
left: 882.06px; top: 235.06px;
width: 290px; height: 290px;
border: 5px solid #FFFFFF;
/* 그라데이션은 fill 영역 280×280에 매핑 (padding-box 기본값) */
background: linear-gradient(145.28deg, #BC652B 16.04%, #A24200 55.20%);
}
/* 생산성/소통 ring: stroke가 fill 내부 → 280×280 그대로, 그라데이션은 border-box 포함 */
.big-ring--prod {
left: 728.06px; top: 514.06px;
width: 280px; height: 280px;
border: 5px solid #FFFFFF;
background: linear-gradient(153.95deg, #897445 15.27%, #3E3523 61.74%);
background-origin: border-box;
background-clip: border-box;
}
.big-ring--trust {
left: 1043.06px; top: 514.06px;
width: 280px; height: 280px;
border: 5px solid #FFFFFF;
background: linear-gradient(153.95deg, #296B55 15.27%, #123328 61.74%);
background-origin: border-box;
background-clip: border-box;
}
/* 메인 원 라벨 (50px Bold 흰색, 2줄) */
.big-title {
position: absolute;
width: 262.923px; height: 114.078px;
font-weight: 700;
font-size: 50px;
line-height: 50px;
color: #ffffff;
text-align: center;
letter-spacing: -2.5px;
display: flex; flex-direction: column; justify-content: center;
z-index: 5;
}
.big-title p { line-height: 50px; }
.big-title--safety { left: 896.46px; top: 330.49px; text-shadow: 0 0 5px #cc5200; }
.big-title--prod { left: 737.46px; top: 604.49px; }
.big-title--trust { left: 1053.63px; top: 597.45px; }
/* ─────────────────────────────────────────────────────────
레이어 5 — 액센트 6원 (순수 CSS)
outer 130.9 (fill-opacity 0.3 → rgba alpha 또는 opacity)
+ mix-blend-mode: multiply
inner 82.96 (= fill 78.96 + 2px outer stroke)
+ white 2px border + box-shadow
───────────────────────────────────────────────────────── */
.acc-outer {
position: absolute;
width: 130.901px; height: 130.901px;
border-radius: 50%;
opacity: 0.3; /* fill-opacity 0.3 */
mix-blend-mode: multiply;
z-index: 6;
}
.acc-inner {
position: absolute;
width: 82.965px; height: 82.965px; /* fill 78.96 + stroke 2×2 */
border: 2px solid #FFFFFF;
border-radius: 50%;
box-shadow: 0 0 10px 0 rgba(0,0,0,1);
z-index: 7;
}
/* outer 위치는 Figma 좌표 그대로, inner는 offset -2 (stroke 외부) */
.acc-outer--an { left: 859px; top: 22px;
background: linear-gradient(145.90deg, #D9C868 8.47%, #DC670E 87.56%); }
.acc-outer--jil { left: 1071px; top: 22px;
background: linear-gradient(145.90deg, #D9C868 8.47%, #DC670E 87.56%); }
.acc-outer--sok { left: 555px; top: 483px;
background: linear-gradient(218.84deg, #D5AA89 14.08%, #737373 92.67%); }
.acc-outer--ri { left: 555px; top: 689px;
background: linear-gradient(218.84deg, #D5AA89 14.08%, #737373 92.67%); }
.acc-outer--tong { left: 1372px; top: 483px;
background: linear-gradient(145.90deg, #60A451 8.47%, #253E1F 87.56%); }
.acc-outer--sin { left: 1372px; top: 689px;
background: linear-gradient(145.90deg, #60A451 8.47%, #253E1F 87.56%); }
/* inner: outer + 25.97 (= (130.9-78.96)/2) - 2 (stroke) = +23.97 */
.acc-inner--an { left: 882.47px; top: 45.47px;
background: linear-gradient(145.28deg, #BC652B 16.04%, #A24200 55.20%); }
.acc-inner--jil { left: 1094.47px; top: 45.47px;
background: linear-gradient(145.28deg, #BC652B 16.04%, #A24200 55.20%); }
.acc-inner--sok { left: 578.47px; top: 506.47px;
background: linear-gradient(153.95deg, #897445 15.27%, #3E3523 61.73%); }
.acc-inner--ri { left: 578.47px; top: 712.47px;
background: linear-gradient(153.95deg, #897445 15.27%, #3E3523 61.73%); }
.acc-inner--tong { left: 1395.47px; top: 506.47px;
background: linear-gradient(153.95deg, #296B55 15.27%, #123328 61.73%); }
.acc-inner--sin { left: 1395.47px; top: 712.47px;
background: linear-gradient(153.95deg, #296B55 15.27%, #123328 61.73%); }
/* 한자 텍스트 (font 45 bold white, lh 50, tracking -2.25, text-shadow) */
.acc-text {
position: absolute;
width: 98.334px; height: 42.666px;
font-weight: 700;
font-size: 45px;
line-height: 50px;
color: #ffffff;
text-align: center;
letter-spacing: -2.25px;
text-shadow: 0 0 5px #cc5200;
display: flex; align-items: center; justify-content: center;
z-index: 8;
}
.acc-text--an { left: 875.25px; top: 63.60px; }
.acc-text--jil { left: 1087.25px; top: 63.60px; }
.acc-text--sok { left: 571.25px; top: 524.60px; }
.acc-text--ri { left: 571.25px; top: 730.60px; }
.acc-text--tong { left: 1388.25px; top: 524.60px; }
.acc-text--sin { left: 1388.25px; top: 730.60px; }
/* ─────────────────────────────────────────────────────────
레이어 6 — 사이드 텍스트 라벨 (상/좌/우 12개)
───────────────────────────────────────────────────────── */
/* 상단 타이틀 orange #cc5200 */
.lbl-top-title {
position: absolute;
font-weight: 700;
font-size: 40px;
line-height: 95px;
color: #cc5200;
white-space: nowrap;
top: 0;
z-index: 5;
}
.title--safety-top { left: 645px; width: 194px; text-align: right; }
.title--quality-top { left: 1233px; width: 157px; text-align: right; }
/* 상단 desc */
.lbl-top-desc {
position: absolute;
font-weight: 500;
font-size: 30px;
color: #525151;
top: 78px;
z-index: 5;
}
.lbl-top-desc p { line-height: 35px; padding-bottom: 5px; }
.desc--safety-top { left: 331px; width: 508.478px; text-align: right; }
.desc--quality-top { left: 1233px; width: 508.478px; }
/* 좌측 타이틀 olive #604f32 */
.lbl-left-title {
position: absolute;
font-weight: 700;
font-size: 40px;
line-height: 95px;
color: #604f32;
text-align: right;
z-index: 5;
}
.title--speed { left: 0; top: 456px; width: 531.393px; height: 95.345px; white-space: nowrap; }
.title--profit {
left: 84.67px; top: 661.79px; width: 446.049px; height: 96.418px;
display: flex; flex-direction: column; justify-content: center;
}
/* 좌측 desc */
.lbl-left-desc {
position: absolute;
font-weight: 500;
font-size: 30px;
color: #525151;
text-align: right;
z-index: 5;
}
.lbl-left-desc p { line-height: 35px; padding-bottom: 5px; }
.desc--speed { left: 52.01px; top: 546px; width: 478.731px; height: 70.561px; }
.desc--profit {
left: 102.02px; top: 734px; width: 428.315px; height: 91.343px;
display: flex; flex-direction: column; justify-content: center;
}
/* 우측 타이틀 green #124133 */
.lbl-right-title {
position: absolute;
font-weight: 700;
font-size: 40px;
line-height: 95px;
color: #124133;
white-space: nowrap;
z-index: 5;
}
.title--comm { left: 1518px; top: 456px; width: 267.016px; }
.title--trust-side { left: 1518px; top: 664px; width: 304.016px; }
/* 우측 desc */
.lbl-right-desc {
position: absolute;
font-weight: 500;
font-size: 30px;
color: #525151;
z-index: 5;
}
.lbl-right-desc p { line-height: 35px; padding-bottom: 5px; }
.desc--comm { left: 1518px; top: 541px; width: 429.012px; white-space: nowrap; }
.desc--trust-desc {
left: 1518px; top: 754.21px; width: 544.198px; height: 70.561px;
display: flex; flex-direction: column; justify-content: center;
}
</style>
</head>
<body>
<div class="slide">
<div class="block">
<div class="inner">
<!-- ═══ 배경 ═══ -->
<div class="bg-texture"><img src="assets/frame_1171281211/bg_texture.png" alt=""></div>
<div class="deco-wrap">
<div class="deco-rot">
<div class="deco-flip">
<div class="deco-rect"></div>
</div>
</div>
</div>
<!-- ═══ 아크 3개 (SVG) ═══ -->
<div class="arc arc--top"><img src="assets/frame_1171281211/arc_top.png" alt=""></div>
<div class="arc arc--left"><img src="assets/frame_1171281211/arc_side.png" alt=""></div>
<div class="arc arc--right"><img src="assets/frame_1171281211/arc_side.png" alt=""></div>
<!-- ═══ 메인 3원 (순수 CSS) ═══ -->
<div class="big-outer big-outer--safety"></div>
<div class="big-ring big-ring--safety"></div>
<div class="big-outer big-outer--prod"></div>
<div class="big-ring big-ring--prod"></div>
<div class="big-outer big-outer--trust"></div>
<div class="big-ring big-ring--trust"></div>
<!-- 메인 원 타이틀 -->
<div class="big-title big-title--safety"><p>안전과</p><p>품질</p></div>
<div class="big-title big-title--prod"><p>생산성</p><p>향상</p></div>
<div class="big-title big-title--trust"><p>소통과</p><p>신뢰</p></div>
<!-- ═══ 액센트 6원 (순수 CSS) ═══ -->
<div class="acc-outer acc-outer--an"></div>
<div class="acc-inner acc-inner--an"></div>
<div class="acc-text acc-text--an"></div>
<div class="acc-outer acc-outer--jil"></div>
<div class="acc-inner acc-inner--jil"></div>
<div class="acc-text acc-text--jil"></div>
<div class="acc-outer acc-outer--sok"></div>
<div class="acc-inner acc-inner--sok"></div>
<div class="acc-text acc-text--sok"></div>
<div class="acc-outer acc-outer--ri"></div>
<div class="acc-inner acc-inner--ri"></div>
<div class="acc-text acc-text--ri"></div>
<div class="acc-outer acc-outer--tong"></div>
<div class="acc-inner acc-inner--tong"></div>
<div class="acc-text acc-text--tong"></div>
<div class="acc-outer acc-outer--sin"></div>
<div class="acc-inner acc-inner--sin"></div>
<div class="acc-text acc-text--sin"></div>
<!-- ═══ 사이드 텍스트 (상단) ═══ -->
<div class="lbl-top-title title--safety-top">안전성 제고</div>
<div class="lbl-top-desc desc--safety-top">
<p>시설물의 요구성능의 만족,</p>
<p>건설중 및 운영중 안전확보</p>
</div>
<div class="lbl-top-title title--quality-top">품질 향상</div>
<div class="lbl-top-desc desc--quality-top">
<p>Copy &amp; Paste로 하향 평준화된</p>
<p>기존 성과물의 품질 향상</p>
</div>
<!-- ═══ 사이드 텍스트 (좌측) ═══ -->
<div class="lbl-left-title title--speed">신속ㆍ정확성 증진</div>
<div class="lbl-left-desc desc--speed">
<p>Analogue 기반 업무를</p>
<p>Digital화 하는 Process 혁신</p>
</div>
<div class="lbl-left-title title--profit"><p>비용저감ㆍ부가가치 창출</p></div>
<div class="lbl-left-desc desc--profit">
<p>건설비용 및 유지관리비 감소,</p>
<p>인력투입 최소화 등 생산성 향상</p>
</div>
<!-- ═══ 사이드 텍스트 (우측) ═══ -->
<div class="lbl-right-title title--comm">소통ㆍ이해 원할</div>
<div class="lbl-right-desc desc--comm">
<p>성과품, Solution을 통한</p>
<p>사용 편리성, 협업 및 의사소통 강화</p>
</div>
<div class="lbl-right-title title--trust-side">신뢰ㆍ투명성 강화</div>
<div class="lbl-right-desc desc--trust-desc">
<p>3D 모델을 통한 오류</p>
<p>최소화 및 Claim 예방</p>
</div>
</div>
</div>
</div>
</body>
</html>