04. design_agent 추가 — 콘텐츠 시각 구조화 슬라이드 생성기
5단계 AI 파이프라인: 1. Kei 실장(Opus via Kei API) — 꼭지 추출 + 정보 구조 파악 2. 디자인 팀장 — FAISS 블록 검색 + Opus 추천 + Sonnet 블록 매핑 3. Kei 편집자(Kei API) — 도메인 전문 텍스트 정리 4. 디자인 실무자(Sonnet + Jinja2) — CSS 변수 조정 + HTML 조립 5. 디자인 팀장(Sonnet) — 균형 재검토 (최대 2회 루프) 블록 라이브러리 46개 (6 카테고리) + _legacy 13개 FAISS 블록 검색 (bge-m3, 1024차원) SVG N개 동적 배치 (cos/sin 좌표 계산) Pillow 이미지 크기 측정 + base64 인라인 컨테이너 예산 기반 블록 배치 (zone별 높이 px) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<!-- 3단 비교 카드: 각각 다른 색상 헤더 + 아이콘/이미지 + 불릿 -->
|
||||
<!--
|
||||
📋 card-compare-3col
|
||||
─────────────────
|
||||
용도: 3개 카테고리 비교 (예: 상용SW / 3rd Party / 전문SW)
|
||||
슬롯: cards[] (각 카드에 title, subtitle, color, image, bullets[])
|
||||
Figma 원본: 2-2_03 "상용 / 3rd Party(범용) / 전문·전용 S/W"
|
||||
-->
|
||||
<div class="block-compare-3" style="--cc-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="cc-card">
|
||||
<div class="cc-header" style="background: {{ card.color | default('#2563eb') }}">
|
||||
<div class="cc-title">{{ card.title }}</div>
|
||||
{% if card.subtitle %}<div class="cc-sub">{{ card.subtitle }}</div>{% endif %}
|
||||
</div>
|
||||
{% if card.image %}
|
||||
<img class="cc-img" src="{{ card.image }}" alt="{{ card.title }}">
|
||||
{% endif %}
|
||||
{% if card.bullets %}
|
||||
<ul class="cc-list">
|
||||
{% for item in card.bullets %}
|
||||
<li>{{ item }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-compare-3 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--cc-count, 3), 1fr);
|
||||
gap: 14px;
|
||||
}
|
||||
.cc-card {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: var(--radius);
|
||||
overflow: hidden;
|
||||
background: #ffffff;
|
||||
}
|
||||
.cc-header {
|
||||
padding: 12px 16px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
.cc-title {
|
||||
font-size: 15px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.cc-sub {
|
||||
font-size: 11px;
|
||||
opacity: 0.85;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.cc-img {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
object-fit: contain;
|
||||
background: #f8fafc;
|
||||
padding: 8px;
|
||||
}
|
||||
.cc-list {
|
||||
list-style: disc;
|
||||
padding: 12px 16px 14px 30px;
|
||||
font-size: 13px;
|
||||
color: #334155;
|
||||
line-height: 1.7;
|
||||
}
|
||||
.cc-list li {
|
||||
margin-bottom: 3px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,77 @@
|
||||
<!-- 다크 오버레이 카드: 배경 이미지 + 흰 텍스트 오버레이 -->
|
||||
<!--
|
||||
📋 card-dark-overlay
|
||||
─────────────────
|
||||
용도: 키워드+짧은 설명을 시각적으로 강조. 이미지 위에 다크 오버레이 + 흰 텍스트.
|
||||
슬롯: cards[] (각 카드에 image, title, description)
|
||||
Figma 원본: 2-2_01 > 아이콘 카드 5열 (협업지원, 오류감소, 생산성향상 등)
|
||||
-->
|
||||
<div class="block-card-dark" style="--cd-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="cd-card">
|
||||
{% if card.image %}
|
||||
<img class="cd-bg" src="{{ card.image }}" alt="">
|
||||
{% else %}
|
||||
<div class="cd-bg cd-bg-default"></div>
|
||||
{% endif %}
|
||||
<div class="cd-overlay">
|
||||
<div class="cd-title">{{ card.title }}</div>
|
||||
{% if card.description %}<div class="cd-desc">{{ card.description }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-dark {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--cd-count, 3), 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
.cd-card {
|
||||
position: relative;
|
||||
border-radius: var(--radius);
|
||||
overflow: hidden;
|
||||
height: 200px;
|
||||
}
|
||||
.cd-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
z-index: 1;
|
||||
}
|
||||
.cd-bg-default {
|
||||
background: linear-gradient(135deg, #1e3a5f 0%, #2c5282 100%);
|
||||
}
|
||||
.cd-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 2;
|
||||
background: linear-gradient(180deg, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.55) 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
.cd-title {
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 6px;
|
||||
text-shadow: 0 1px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
.cd-desc {
|
||||
white-space: pre-line;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
opacity: 0.9;
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
48
04. design_agent/templates/blocks/cards/card-icon-desc.html
Normal file
48
04. design_agent/templates/blocks/cards/card-icon-desc.html
Normal file
@@ -0,0 +1,48 @@
|
||||
<!-- 아이콘 설명 카드: 아이콘 + 제목 + 설명 (2~4열) -->
|
||||
<!--
|
||||
📋 card-icon-desc
|
||||
─────────────────
|
||||
용도: 기능/특성/장점을 아이콘과 함께 나열. 시각적으로 분류.
|
||||
슬롯: cards[] (각 카드에 icon, title, description)
|
||||
Figma 원본: 2-3_01 아이콘 3열 설명
|
||||
-->
|
||||
<div class="block-card-icon" style="--ci-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="cid-card">
|
||||
{% if card.icon %}<div class="cid-icon">{{ card.icon }}</div>{% endif %}
|
||||
<div class="cid-title">{{ card.title }}</div>
|
||||
{% if card.description %}<div class="cid-desc">{{ card.description }}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-icon {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--ci-count, 3), 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.cid-card {
|
||||
text-align: center;
|
||||
padding: 20px 16px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
.cid-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.cid-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.cid-desc {
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
line-height: 1.7;
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
96
04. design_agent/templates/blocks/cards/card-image-3col.html
Normal file
96
04. design_agent/templates/blocks/cards/card-image-3col.html
Normal file
@@ -0,0 +1,96 @@
|
||||
<!-- 이미지 카드: 상단 이미지 + 하단 텍스트 (2~4열) -->
|
||||
<!--
|
||||
📋 card-image
|
||||
─────────────────
|
||||
용도: 단계별 설명, 카테고리별 설명 (이미지가 핵심인 카드)
|
||||
슬롯: cards[] 배열 (각 카드에 image, title, title_en, items[])
|
||||
Figma 원본: 2-1_02 > Group 1171281594 (카드 3열)
|
||||
-->
|
||||
<div class="block-card-image" style="--ci-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="ci-card">
|
||||
{% if card.image %}
|
||||
<img class="ci-img" src="{{ card.image }}" alt="{{ card.title }}">
|
||||
{% endif %}
|
||||
<div class="ci-body">
|
||||
<div class="ci-title" style="color: {{ card.color | default('var(--color-accent, #006aff)') }}">{{ card.title }}</div>
|
||||
{% if card.title_en %}<div class="ci-title-en">{{ card.title_en }}</div>{% endif %}
|
||||
<div class="ci-divider"></div>
|
||||
<ul class="ci-list">
|
||||
{% for item in card.bullets %}
|
||||
<li>{{ item }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if card.source %}<div class="ci-source">{{ card.source }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-image {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--ci-count, 3), 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.ci-card {
|
||||
background: var(--color-bg, #ffffff);
|
||||
border-radius: var(--radius, 8px);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.ci-img {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
object-fit: contain;
|
||||
background: #f8f9fb;
|
||||
padding: 10px;
|
||||
}
|
||||
.ci-body {
|
||||
padding: 16px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.ci-title {
|
||||
font-size: 14px;
|
||||
font-weight: var(--weight-bold, 700);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.ci-title-en {
|
||||
font-size: 12px;
|
||||
font-weight: var(--weight-normal, 400);
|
||||
color: var(--color-text-secondary, #666);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ci-divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #000;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ci-list {
|
||||
white-space: pre-line;
|
||||
list-style: disc;
|
||||
padding-left: 18px;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
color: var(--color-text, #000);
|
||||
flex: 1;
|
||||
}
|
||||
.ci-list li {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.ci-source {
|
||||
font-size: 11px;
|
||||
color: var(--color-text-light, #94a3b8);
|
||||
font-style: italic;
|
||||
margin-top: 8px;
|
||||
border-top: 1px solid var(--color-border, #e2e8f0);
|
||||
padding-top: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<!-- 원형 이미지 카드: 원형 이미지 + 하단 제목/설명 -->
|
||||
<!--
|
||||
📋 card-image-round
|
||||
─────────────────
|
||||
용도: 포트폴리오형, 팀 소개, 가치/비전 표현 (원형 이미지가 핵심)
|
||||
슬롯: cards[] (각 카드에 image, title, description)
|
||||
Figma 원본: 1장_가치 하단 3열 원형 이미지 + 설명
|
||||
-->
|
||||
<div class="block-card-round" style="--cr-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="cr-card">
|
||||
{% if card.image %}
|
||||
<div class="cr-img-wrap">
|
||||
<img src="{{ card.image }}" alt="{{ card.title | default('') }}">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="cr-title">{{ card.title }}</div>
|
||||
{% if card.description %}<div class="cr-desc">{{ card.description }}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-round {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--cr-count, 3), 1fr);
|
||||
gap: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.cr-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.cr-img-wrap {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 3px solid #e2e8f0;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.cr-img-wrap img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.cr-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.cr-desc {
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
line-height: 1.6;
|
||||
white-space: pre-line;
|
||||
max-width: 200px;
|
||||
}
|
||||
</style>
|
||||
60
04. design_agent/templates/blocks/cards/card-numbered.html
Normal file
60
04. design_agent/templates/blocks/cards/card-numbered.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- 번호 카드: 순서 번호 + 제목 + 설명 (세로 나열) -->
|
||||
<!--
|
||||
📋 card-numbered
|
||||
─────────────────
|
||||
용도: 순서가 있는 항목 나열 (1. 2. 3.), 실행 조건, 요구사항
|
||||
슬롯: items[] (각 항목에 title, description)
|
||||
card-icon-desc와 다른 점: 아이콘 대신 순서 번호, 세로 나열
|
||||
-->
|
||||
<div class="block-card-num">
|
||||
{% for item in items %}
|
||||
<div class="cn-item">
|
||||
<div class="cn-number" style="background: {{ item.color | default('#2563eb') }}">{{ loop.index }}</div>
|
||||
<div class="cn-body">
|
||||
<div class="cn-title">{{ item.title }}</div>
|
||||
{% if item.description %}<div class="cn-desc">{{ item.description }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-num {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
.cn-item {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: flex-start;
|
||||
padding: 12px 16px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
.cn-number {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cn-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.cn-desc {
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
line-height: 1.7;
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,57 @@
|
||||
<!-- 통계 숫자 카드: 큰 숫자 + 라벨 + 설명 -->
|
||||
<!--
|
||||
📋 card-stat-number
|
||||
─────────────────
|
||||
용도: KPI, 성과 수치, 목표 달성률, 비용 절감율 등 핵심 지표 강조
|
||||
슬롯: stats[] (각 항목에 number, unit, label, description, color)
|
||||
Figma 참고: 건설 정책 수치 (30% 절감, 40% 감소 등)
|
||||
-->
|
||||
<div class="block-stat" style="--st-count: {{ stats|length }}">
|
||||
{% for stat in stats %}
|
||||
<div class="st-card">
|
||||
<div class="st-number" style="color: {{ stat.color | default('#2563eb') }}">
|
||||
{{ stat.number }}<span class="st-unit">{{ stat.unit | default('') }}</span>
|
||||
</div>
|
||||
<div class="st-label">{{ stat.label }}</div>
|
||||
{% if stat.description %}<div class="st-desc">{{ stat.description }}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-stat {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--st-count, 3), 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.st-card {
|
||||
text-align: center;
|
||||
padding: 20px 12px;
|
||||
background: #f8fafc;
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
.st-number {
|
||||
font-size: 36px;
|
||||
font-weight: 900;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.st-unit {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.st-label {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.st-desc {
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
margin-top: 4px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,93 @@
|
||||
<!-- 세로 단계 카드: 좌측 단계 마커 + 우측 이미지/텍스트 -->
|
||||
<!--
|
||||
📋 card-step-vertical
|
||||
─────────────────
|
||||
용도: 생애주기 단계별 설명, 시간순 프로세스 (설계→시공→운영→유지관리)
|
||||
슬롯: steps[] (각 단계에 phase, title, description, image, color)
|
||||
Figma 원본: 2-3_04 "건설 생애주기와 정보모델 연계" (설계단계/시공단계/운영관리/유지관리)
|
||||
-->
|
||||
<div class="block-step-v">
|
||||
{% for step in steps %}
|
||||
<div class="sv-step">
|
||||
<div class="sv-marker" style="background: {{ step.color | default('#2563eb') }}">
|
||||
<div class="sv-phase">{{ step.phase }}</div>
|
||||
</div>
|
||||
<div class="sv-content">
|
||||
<div class="sv-title">{{ step.title }}</div>
|
||||
{% if step.image %}
|
||||
<img class="sv-img" src="{{ step.image }}" alt="{{ step.title }}">
|
||||
{% endif %}
|
||||
{% if step.description %}<div class="sv-desc">{{ step.description }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not loop.last %}
|
||||
<div class="sv-connector">
|
||||
<div class="sv-line" style="background: {{ step.color | default('#2563eb') }}"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-step-v {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
.sv-step {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.sv-marker {
|
||||
width: 100px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
.sv-phase {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.sv-content {
|
||||
flex: 1;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
padding: 14px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
.sv-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.sv-img {
|
||||
width: 100%;
|
||||
max-height: 150px;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.sv-desc {
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
line-height: 1.7;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.sv-connector {
|
||||
display: flex;
|
||||
justify-content: 50px;
|
||||
padding-left: 48px;
|
||||
height: 20px;
|
||||
}
|
||||
.sv-line {
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
border-radius: 2px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
||||
63
04. design_agent/templates/blocks/cards/card-tag-image.html
Normal file
63
04. design_agent/templates/blocks/cards/card-tag-image.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!-- 태그 카드: 상단 태그 라벨 + 이미지 + 설명 -->
|
||||
<!--
|
||||
📋 card-tag-image
|
||||
─────────────────
|
||||
용도: 카테고리별 분류 (제조/건축/토목 등), 태그로 구분되는 항목
|
||||
슬롯: cards[] (각 카드에 tag, tag_color, image, title, description)
|
||||
Figma 원본: 2-3_01 "산업별 특성과 현장의 모습" (제조, 건축, 인프라/토목)
|
||||
-->
|
||||
<div class="block-card-tag" style="--ct-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="ct-card">
|
||||
<div class="ct-tag" style="background: {{ card.tag_color | default('#2563eb') }}">{{ card.tag }}</div>
|
||||
{% if card.image %}
|
||||
<img class="ct-img" src="{{ card.image }}" alt="{{ card.title | default('') }}">
|
||||
{% endif %}
|
||||
{% if card.title %}<div class="ct-title">{{ card.title }}</div>{% endif %}
|
||||
{% if card.description %}<div class="ct-desc">{{ card.description }}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-tag {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--ct-count, 3), 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.ct-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.ct-tag {
|
||||
display: inline-block;
|
||||
padding: 4px 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
border-radius: 0 0 8px 0;
|
||||
align-self: flex-start;
|
||||
}
|
||||
.ct-img {
|
||||
width: 100%;
|
||||
height: 140px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.ct-title {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
padding: 10px 14px 4px;
|
||||
}
|
||||
.ct-desc {
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
line-height: 1.7;
|
||||
padding: 0 14px 14px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
66
04. design_agent/templates/blocks/cards/card-text-grid.html
Normal file
66
04. design_agent/templates/blocks/cards/card-text-grid.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!-- 카드 그리드 블록: 2~4열 카드 배열 -->
|
||||
<div class="block-card-grid" style="--card-count: {{ cards|length }}">
|
||||
{% for card in cards %}
|
||||
<div class="card" style="border-top-color: {{ card.color | default('var(--color-accent)') }}">
|
||||
{% if card.icon %}<div class="card-icon">{{ card.icon }}</div>{% endif %}
|
||||
<div class="card-title">{{ card.title }}</div>
|
||||
{% if card.category %}<span class="card-category">{{ card.category }}</span>{% endif %}
|
||||
<div class="card-description">{{ card.description }}</div>
|
||||
{% if card.source %}<div class="card-source">{{ card.source }}</div>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.block-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--card-count, 3), 1fr);
|
||||
gap: var(--spacing-inner);
|
||||
height: 100%;
|
||||
}
|
||||
.card {
|
||||
background: var(--color-bg);
|
||||
border: var(--border-width) solid var(--color-border);
|
||||
border-top: var(--accent-border) solid var(--color-accent);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--spacing-inner);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.card-icon {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: var(--spacing-small);
|
||||
}
|
||||
.card-title {
|
||||
font-size: var(--font-subtitle);
|
||||
font-weight: var(--weight-bold);
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.card-category {
|
||||
font-size: var(--font-small);
|
||||
font-weight: var(--weight-medium);
|
||||
color: var(--color-accent);
|
||||
background: #dbeafe;
|
||||
padding: 2px 8px;
|
||||
border-radius: var(--radius);
|
||||
display: inline-block;
|
||||
margin-bottom: var(--spacing-small);
|
||||
width: fit-content;
|
||||
}
|
||||
.card-description {
|
||||
white-space: pre-line;
|
||||
font-size: var(--font-body);
|
||||
color: var(--color-text);
|
||||
line-height: var(--line-height-ko);
|
||||
flex: 1;
|
||||
}
|
||||
.card-source {
|
||||
font-size: var(--font-small);
|
||||
color: var(--color-text-light);
|
||||
font-style: italic;
|
||||
margin-top: var(--spacing-small);
|
||||
border-top: var(--border-width) solid var(--color-border);
|
||||
padding-top: var(--spacing-small);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user