o2o-infinith-frontend/src/styles/custom.css

146 lines
4.8 KiB
CSS

/* ─── Keyframes ──────────────────────────────────────── */
@keyframes blob {
0% { transform: translate3d(0, 0, 0) scale(1); }
33% { transform: translate3d(15px, -25px, 0) scale(1.05); }
66% { transform: translate3d(-10px, 10px, 0) scale(0.95); }
100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes blob-large {
0% { transform: translate3d(0, 0, 0) scale(1); }
33% { transform: translate3d(4vw, -4vh, 0) scale(1.05); }
66% { transform: translate3d(-4vw, 4vh, 0) scale(0.95); }
100% { transform: translate3d(0, 0, 0) scale(1); }
}
/* GPU-accelerate blob animations to prevent layout jitter */
.animate-blob, .animate-blob-large {
will-change: transform;
contain: layout style;
backface-visibility: hidden;
}
.animate-blob-large { animation: blob-large 25s infinite ease-in-out; }
.animation-delay-2000 { animation-delay: 2s; }
.animation-delay-4000 { animation-delay: 4s; }
.animation-delay-7000 { animation-delay: 7s; }
.animation-delay-14000 { animation-delay: 14s; }
/* ─── 글로벌 effect 클래스 (데모 호환) ─────────────────── */
.text-gradient {
background: linear-gradient(to right, var(--brand-navy), #3b5998);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
color: transparent;
}
.glass-card {
@apply bg-white/70 backdrop-blur-xl border border-white/40 shadow-[0_8px_32px_0_rgba(31,38,135,0.07)] rounded-2xl;
}
.gradient-bg {
background: radial-gradient(circle at top left, #fdfbfb, #f3e7e9);
@apply relative;
}
.gradient-bg::before {
content: "";
@apply absolute inset-0 bg-white/30 backdrop-blur-[2px] pointer-events-none;
}
.soft-gradient {
background: linear-gradient(145deg, #fdfbfb 0%, #ebedee 100%);
}
/* ─── Print / PDF (브라우저 네이티브 인쇄 → PDF) ────────────
useExportPDF 훅이 window.print()를 호출하면 이 규칙이 적용됨.
리포트/플랜 본문(data-report-content / data-plan-content)만 인쇄. */
@media print {
@page {
size: A4;
margin: 15mm 10mm 10mm 10mm;
}
/* 브랜드 색·다크 섹션·그라데이션 그대로 유지 */
*, *::before, *::after {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
html, body {
background: #ffffff !important;
margin: 0 !important;
padding: 0 !important;
}
/* 인쇄에서 제외할 UI 요소 */
[data-no-print],
[data-report-nav],
[data-plan-nav],
[data-cta-card],
[data-radix-popper-content-wrapper],
[role="menu"],
[role="dialog"],
[role="tooltip"],
nav {
display: none !important;
}
/* sticky/fixed 요소는 매 페이지마다 반복 인쇄되므로 정적으로 */
.sticky, .fixed {
position: static !important;
}
/* 가로 스크롤 영역은 줄바꿈으로 펼쳐 모든 콘텐츠를 보이게 */
[data-report-content] .overflow-x-auto,
[data-report-content] .overflow-x-scroll,
[data-report-content] .scrollbar-thin,
[data-plan-content] .overflow-x-auto,
[data-plan-content] .overflow-x-scroll,
[data-plan-content] .scrollbar-thin {
overflow: visible !important;
flex-wrap: wrap !important;
}
[data-report-content] .shrink-0,
[data-plan-content] .shrink-0 {
flex-shrink: 1 !important;
min-width: 0 !important;
}
/* SectionWrapper의 화면용 py-16/md:py-20 (≈64-80px)은 인쇄에선 너무 큼 → 살짝만 압축.
좌우 padding(px-6)과 PageContainer의 max-w-7xl/px-6은 그대로 유지하여 가독성 보존. */
[data-report-content] section,
[data-plan-content] section {
padding-top: 10mm !important;
padding-bottom: 10mm !important;
}
/* 화면의 sticky/fixed nav 오프셋용 상단 padding 제거 (인쇄에선 nav가 숨겨지므로 불필요) */
.pt-16, .pt-20, .pt-24, .pt-28, .pt-32 {
padding-top: 0 !important;
}
/* ReportHeader/PlanHeader 등 첫 섹션 상단 — @page top margin (15mm) 외 약간의 여유 */
[data-report-content] > section:first-child,
[data-plan-content] > section:first-child {
padding-top: 4mm !important;
}
/* break-inside: avoid는 의도적으로 안 씀.
KPI 표·로드맵·Transformation 칩 카드처럼 한 페이지보다 긴 요소가
통째로 다음 페이지로 밀려서 큰 빈 공간을 만들기 때문.
필요한 곳은 [data-print-keep] 명시 시 그 요소만 묶어주는 방식 사용. */
[data-print-keep] {
break-inside: avoid;
page-break-inside: avoid;
}
/* framer-motion whileInView 잔여 inline opacity 처리
(useExportPDF에서 JS로도 강제하지만 안전장치) */
[style*="opacity: 0"],
[style*="opacity:0"] {
opacity: 1 !important;
}
}