// Variant 3 (Right-aligned) — Wave Reveal // 동일한 스토리지만 모든 텍스트/콘텐츠가 화면 오른쪽 절반에 정렬됨. // 페이지 hero에서 왼쪽에 카피가 있을 때 영상이 오른쪽에 배치되어도 // 텍스트가 잘리지 않도록 설계. function ServiceTileRight({ label, korLabel, desc, icon, color, accent, children, opacity = 1, scale = 1 }) { // anchor: 오른쪽 정렬, right: 120px, vertically centered return (
{label}
{korLabel}
{icon}
{desc}
{children}
); } function FeatureChipsRight({ items, color }) { return (
{items.map((it, i) => (
{it}
))}
); } // Big wave layer — same as variant3 but with subtle left-side fade function BigWaveRight({ time, intensity = 1, baseColor = WP.blue600, accentColor = WP.cyan500, yCenter = 540, opacity = 1, phaseOffset = 0 }) { const W = 1920; const H = 1080; const buildPath = (offsetY, freq, amp, phase) => { const N = 40; const pts = []; for (let i = 0; i <= N; i++) { const x = (i / N) * W; const y = yCenter + offsetY + Math.sin((i / N) * freq * Math.PI * 2 + phase) * amp * intensity; pts.push([x, y]); } let d = `M ${pts[0][0]} ${pts[0][1]}`; for (let i = 1; i < pts.length; i++) { const cpx = (pts[i - 1][0] + pts[i][0]) / 2; d += ` Q ${pts[i - 1][0]} ${pts[i - 1][1]}, ${cpx} ${(pts[i - 1][1] + pts[i][1]) / 2}`; } d += ` L ${W} ${H} L 0 ${H} Z`; return d; }; return ( ); } function Variant3Right() { const T = useTime(); const window_ = (start, end) => { const fadeIn = clamp((T - start) / 0.7, 0, 1); const fadeOut = 1 - clamp((T - end) / 0.7, 0, 1); return Math.min(fadeIn, fadeOut); }; const webOp = window_(1.2, 4.2); const secOp = window_(4.0, 7.2); const mktOp = window_(7.0, 10.0); const webEntry = clamp((T - 1.0) / 0.8, 0, 1); const secEntry = clamp((T - 3.8) / 0.8, 0, 1); const mktEntry = clamp((T - 6.8) / 0.8, 0, 1); const logoStart = 10.5; const logoP = clamp((T - logoStart) / 1.5, 0, 1); const logoE = Easing.easeOutCubic(logoP); const sloganP = clamp((T - 11.5) / 1.5, 0, 1); const sloganE = Easing.easeOutCubic(sloganP); const swellP = clamp((T - 9.5) / 2.0, 0, 1); const swell = Math.sin(swellP * Math.PI) * 0.6 + 1; const sceneIdx = T < 4 ? 0 : T < 7 ? 1 : T < 10 ? 2 : 3; const sceneColors = [ { base: WP.blue600, accent: WP.cyan500 }, { base: WP.navy600, accent: WP.blue400 }, { base: WP.blue700, accent: WP.orange500 }, { base: WP.blue600, accent: WP.cyan500 }, ]; const colorAt = (t) => { if (t < 4) return sceneColors[0]; if (t < 4.5) { const k = (t - 4) / 0.5; return { base: mixColorR(sceneColors[0].base, sceneColors[1].base, k), accent: mixColorR(sceneColors[0].accent, sceneColors[1].accent, k), }; } if (t < 7) return sceneColors[1]; if (t < 7.5) { const k = (t - 7) / 0.5; return { base: mixColorR(sceneColors[1].base, sceneColors[2].base, k), accent: mixColorR(sceneColors[1].accent, sceneColors[2].accent, k), }; } if (t < 10) return sceneColors[2]; if (t < 10.5) { const k = (t - 10) / 0.5; return { base: mixColorR(sceneColors[2].base, sceneColors[3].base, k), accent: mixColorR(sceneColors[2].accent, sceneColors[3].accent, k), }; } return sceneColors[3]; }; const colors = colorAt(T); return (
{/* Big back wave */} {/* Section index ribbon — RIGHT aligned, top-right */}
{['WEB', 'SECURITY', 'MARKETING'].map((l, i) => { const active = sceneIdx === i; return (
{String(i + 1).padStart(2, '0')} · {l}
{i < 2 &&
} ); })}
{/* Service tiles — anchored RIGHT */}
} desc={"브랜드를 빠르게 살리는 홈페이지 구축과 안정적인 운영·유지보수를 한 팀에서 제공합니다."} >
} desc={"AI·머신러닝 기반 탐지 엔진이 24/365 실시간으로 위협을 차단하고, 침해 사고에 즉시 대응합니다."} >
} desc={"AI가 키워드 트렌드를 분석하고 콘텐츠 초안을 생성합니다. 검색 노출과 광고 성과를 한 화면에서 측정합니다."} >
{/* Convergence flash — anchored right */} {T > 9.8 && T < 12.5 && (
)} {/* Logo — anchored RIGHT */}
WAVEPIX
{/* Slogan — anchored RIGHT, fits within right ~880px */}
AI로 중심을 잡고,
한발 앞서갑니다.
wavepix.co.kr
{/* Optional safe-zone guide line at x=960 (left half) — disabled by default */}
); } function mixColorR(a, b, t) { const ah = parseInt(a.slice(1), 16); const bh = parseInt(b.slice(1), 16); const ar = (ah >> 16) & 255, ag = (ah >> 8) & 255, ab = ah & 255; const br = (bh >> 16) & 255, bg = (bh >> 8) & 255, bb = bh & 255; const r = Math.round(ar + (br - ar) * t); const g = Math.round(ag + (bg - ag) * t); const bl = Math.round(ab + (bb - ab) * t); return '#' + [r, g, bl].map(v => v.toString(16).padStart(2, '0')).join(''); } window.Variant3Right = Variant3Right;