assets, move memories to proper location
This commit is contained in:
633
assets/ads/generate_assets.py
Normal file
633
assets/ads/generate_assets.py
Normal file
@@ -0,0 +1,633 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate ShieldAI ad creative SVGs for Google Display and Meta campaigns."""
|
||||
|
||||
import os
|
||||
|
||||
OUT = os.path.join(os.path.dirname(__file__))
|
||||
|
||||
# Brand colors
|
||||
DARK_BG = "#0a0f1e"
|
||||
CARD_BG = "#1a2332"
|
||||
TEXT_PRIMARY = "#f1f5f9"
|
||||
TEXT_SECONDARY = "#94a3b8"
|
||||
TEXT_MUTED = "#64748b"
|
||||
ACCENT_BLUE = "#3b82f6"
|
||||
ACCENT_CYAN = "#06b6d4"
|
||||
SUCCESS = "#22c55e"
|
||||
ERROR = "#ef4444"
|
||||
WARNING = "#f59e0b"
|
||||
BORDER = "#1e293b"
|
||||
|
||||
def shield_logo_svg(size=40, x=0, y=0):
|
||||
return f'''<g transform="translate({x},{y})">
|
||||
<circle cx="{size//2}" cy="{size//2}" r="{size//2}" fill="url(shieldGrad)"/>
|
||||
<path d="M{size//2-10},{size//2-8} L{size//2+10},{size//2-8} L{size//2+10},{size//2+6} Q{size//2},{size//2+14} {size//2},{size//2+14} Q{size//2},{size//2+14} {size//2-10},{size//2+6} Z" fill="none" stroke="{TEXT_PRIMARY}" stroke-width="2.5"/>
|
||||
<path d="M{size//2-4},{size//2-2} L{size//2},{size//2+4} L{size//2+7},{size//2-5}" fill="none" stroke="{TEXT_PRIMARY}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>'''
|
||||
|
||||
def brand_bar(w, h):
|
||||
return f'''<rect width="{w}" height="{h}" fill="url(brandBar)"/>'''
|
||||
|
||||
def safe_text(text, max_len=80):
|
||||
return text[:max_len] if len(text) > max_len else text
|
||||
|
||||
# ============================================================
|
||||
# GOOGLE DISPLAY ASSETS
|
||||
# ============================================================
|
||||
|
||||
def gd_square():
|
||||
"""1:1 (1200x1200) — '3 Protections, 1 Platform' three-icon panel"""
|
||||
w, h = 1200, 1200
|
||||
icon_size = 100
|
||||
box_w, box_h = 280, 320
|
||||
gap = 60
|
||||
total_w = 3 * box_w + 2 * gap
|
||||
start_x = (w - total_w) // 2
|
||||
top_y = 300
|
||||
|
||||
icons_data = [
|
||||
("VoicePrint", "AI Voice Clone Detection", ACCENT_CYAN, [
|
||||
"M0,-40 Q30,-35 40,-10 Q45,5 35,20 L25,30 L0,40 L-25,30 L-35,20 Q-45,5 -40,-10 Q-30,-35 0,-40 Z",
|
||||
"M-12,0 L-4,8 L12,-10"
|
||||
]),
|
||||
("DarkWatch", "Dark Web Monitoring", ACCENT_BLUE, [
|
||||
"M-35,-30 L35,-30 L40,10 Q40,30 25,40 L0,45 L-25,40 Q-40,30 -40,10 Z",
|
||||
"M0,5 L0,25 M-10,15 L10,15"
|
||||
]),
|
||||
("SpamShield", "Spam Call & Text Blocking", SUCCESS, [
|
||||
"M-40,-10 Q-40,-40 0,-40 Q40,-40 40,-10 Q40,15 20,30 L0,40 L-20,30 Q-40,15 -40,-10 Z",
|
||||
"M-15,0 L-5,10 L18,-12"
|
||||
]),
|
||||
]
|
||||
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgGrad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="{DARK_BG}"/>
|
||||
<stop offset="100%" stop-color="#050812"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shieldGrad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgGrad)"/>
|
||||
{brand_bar(w, 6)}
|
||||
<text x="{w//2}" y="160" font-family="system-ui, sans-serif" font-size="52" font-weight="700" fill="{TEXT_PRIMARY}" text-anchor="middle">3 Protections, 1 Platform</text>
|
||||
<text x="{w//2}" y="220" font-family="system-ui, sans-serif" font-size="24" fill="{TEXT_SECONDARY}" text-anchor="middle">AI-Powered Identity Protection for Everyone</text>'''
|
||||
|
||||
for i, (name, desc, color, paths) in enumerate(icons_data):
|
||||
cx = start_x + i * (box_w + gap) + box_w // 2
|
||||
cy = top_y + box_h // 2
|
||||
|
||||
svg += f'''
|
||||
<rect x="{start_x + i * (box_w + gap)}" y="{top_y}" width="{box_w}" height="{box_h}" rx="16" fill="{CARD_BG}" stroke="{BORDER}" stroke-width="1.5"/>'''
|
||||
svg += f'''
|
||||
<g transform="translate({cx}, {cy - 40})">
|
||||
<circle cx="0" cy="0" r="50" fill="{color}22" stroke="{color}" stroke-width="2"/>
|
||||
<path d="{paths[0]}" fill="none" stroke="{color}" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="{paths[1]}" fill="none" stroke="{TEXT_PRIMARY}" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>'''
|
||||
svg += f'''
|
||||
<text x="{cx}" y="{cy + 50}" font-family="system-ui, sans-serif" font-size="22" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">{name}</text>
|
||||
<text x="{cx}" y="{cy + 80}" font-family="system-ui, sans-serif" font-size="16" fill="{TEXT_SECONDARY}" text-anchor="middle">{desc}</text>'''
|
||||
|
||||
svg += f'''
|
||||
<text x="{w//2}" y="{h - 100}" font-family="system-ui, sans-serif" font-size="18" fill="{TEXT_MUTED}" text-anchor="middle">Join 1,000+ Early Adopters</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
def gd_landscape():
|
||||
"""1.91:1 (1200x628) — 'Your Family Deserves AI Protection' family + shield"""
|
||||
w, h = 1200, 628
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgGrad2" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{DARK_BG}"/>
|
||||
<stop offset="60%" stop-color="{DARK_BG}"/>
|
||||
<stop offset="100%" stop-color="#0c1628"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shieldGrad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgGrad2)"/>
|
||||
{brand_bar(w, 5)}
|
||||
<circle cx="830" cy="314" r="240" fill="{ACCENT_BLUE}08"/>
|
||||
<circle cx="830" cy="314" r="180" fill="{ACCENT_BLUE}06"/>
|
||||
<circle cx="830" cy="314" r="220" fill="none" stroke="{ACCENT_BLUE}15" stroke-width="1" stroke-dasharray="8 8"/>
|
||||
|
||||
<!-- Digital shield icon (large, right side) -->
|
||||
<g transform="translate(830, 314)">
|
||||
<path d="M-70,-60 L70,-60 L75,20 Q75,60 40,80 L0,95 L-40,80 Q-75,60 -75,20 Z" fill="none" stroke="url(#shieldGrad)" stroke-width="3"/>
|
||||
<path d="M-30,-10 L0,25 L35,-20" fill="none" stroke="{SUCCESS}" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="0" y="130" font-family="system-ui, sans-serif" font-size="14" fill="{TEXT_SECONDARY}" text-anchor="middle">AI-Powered Protection</text>
|
||||
</g>
|
||||
|
||||
<!-- Left side: text -->
|
||||
<text x="60" y="220" font-family="system-ui, sans-serif" font-size="44" font-weight="700" fill="{TEXT_PRIMARY}">Your Family Deserves</text>
|
||||
<text x="60" y="280" font-family="system-ui, sans-serif" font-size="44" font-weight="700" fill="{ACCENT_CYAN}">AI Protection</text>
|
||||
|
||||
<text x="60" y="340" font-family="system-ui, sans-serif" font-size="18" fill="{TEXT_SECONDARY}">Real-time AI voice clone detection</text>
|
||||
<text x="60" y="368" font-family="system-ui, sans-serif" font-size="18" fill="{TEXT_SECONDARY}">Dark web monitoring • Spam blocking</text>
|
||||
|
||||
<rect x="60" y="410" width="200" height="52" rx="26" fill="{ACCENT_BLUE}"/>
|
||||
<text x="160" y="442" font-family="system-ui, sans-serif" font-size="18" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Join the Waitlist</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
def gd_portrait():
|
||||
"""4:5 (600x750) — 'Voice Clone Detection' phone call visualization"""
|
||||
w, h = 600, 750
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgGrad3" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="{DARK_BG}"/>
|
||||
<stop offset="100%" stop-color="#050812"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
<filter id="glow">
|
||||
<feGaussianBlur stdDeviation="3" result="blur"/>
|
||||
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgGrad3)"/>
|
||||
{brand_bar(w, 5)}
|
||||
|
||||
<!-- Phone icon -->
|
||||
<g transform="translate(300, 260)">
|
||||
<rect x="-60" y="-100" width="120" height="200" rx="18" fill="none" stroke="{ACCENT_BLUE}" stroke-width="3"/>
|
||||
<circle cx="0" cy="80" r="6" fill="{ACCENT_BLUE}"/>
|
||||
<!-- Sound waves -->
|
||||
<path d="M-30,-30 Q-50,-10 -30,10" fill="none" stroke="{ACCENT_CYAN}" stroke-width="2.5" stroke-linecap="round" opacity="0.6"/>
|
||||
<path d="M-20,-45 Q-65,-10 -20,25" fill="none" stroke="{ACCENT_CYAN}" stroke-width="2.5" stroke-linecap="round" opacity="0.9"/>
|
||||
<path d="M-10,-60 Q-80,-10 -10,40" fill="none" stroke="{ACCENT_CYAN}" stroke-width="2.5" stroke-linecap="round" filter="url(#glow)"/>
|
||||
</g>
|
||||
|
||||
<!-- Warning indicator -->
|
||||
<g transform="translate(300, 80)">
|
||||
<path d="M0,-30 L-20,0 L20,0 Z" fill="{WARNING}"/>
|
||||
<circle cx="0" cy="10" r="4" fill="{WARNING}"/>
|
||||
</g>
|
||||
|
||||
<text x="{w//2}" y="420" font-family="system-ui, sans-serif" font-size="34" font-weight="700" fill="{TEXT_PRIMARY}" text-anchor="middle">Voice Clone</text>
|
||||
<text x="{w//2}" y="460" font-family="system-ui, sans-serif" font-size="34" font-weight="700" fill="{ACCENT_CYAN}" text-anchor="middle">Detection</text>
|
||||
|
||||
<text x="{w//2}" y="510" font-family="system-ui, sans-serif" font-size="16" fill="{TEXT_SECONDARY}" text-anchor="middle">AI detects synthetic voices</text>
|
||||
<text x="{w//2}" y="535" font-family="system-ui, sans-serif" font-size="16" fill="{TEXT_SECONDARY}" text-anchor="middle">in real time with 99.7% accuracy</text>
|
||||
|
||||
<rect x="200" y="580" width="200" height="50" rx="25" fill="{ACCENT_BLUE}"/>
|
||||
<text x="300" y="611" font-family="system-ui, sans-serif" font-size="17" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Learn How We Detect It</text>
|
||||
|
||||
<text x="{w//2}" y="{h - 40}" font-family="system-ui, sans-serif" font-size="13" fill="{TEXT_MUTED}" text-anchor="middle">ShieldAI — AI-Powered Identity Protection</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
# ============================================================
|
||||
# META CREATIVE A: Voice Clone Threat
|
||||
# ============================================================
|
||||
|
||||
def meta_a_1x1():
|
||||
"""1:1 (1080x1080) — split-screen family / AI distortion"""
|
||||
w, h = 1080, 1080
|
||||
half = w // 2
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgGradL" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#0a1528"/>
|
||||
<stop offset="100%" stop-color="#0f1d35"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="bgGradR" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1a0a0a"/>
|
||||
<stop offset="100%" stop-color="#2d0f0f"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="distortGrad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="{ERROR}66"/>
|
||||
<stop offset="100%" stop-color="{ERROR}22"/>
|
||||
</linearGradient>
|
||||
<filter id="glitch">
|
||||
<feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="3" result="noise"/>
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="8" xChannelSelector="R" yChannelSelector="G"/>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Left panel: normal family -->
|
||||
<rect x="0" y="0" width="{half}" height="{h}" fill="url(#bgGradL)"/>
|
||||
<circle cx="{half//2}" cy="280" r="60" fill="{ACCENT_BLUE}30" stroke="{ACCENT_BLUE}" stroke-width="2"/>
|
||||
<circle cx="{half//2 - 60}" cy="220" r="40" fill="{ACCENT_BLUE}20" stroke="{ACCENT_BLUE}" stroke-width="1.5"/>
|
||||
<circle cx="{half//2 + 70}" cy="230" r="35" fill="{ACCENT_BLUE}20" stroke="{ACCENT_BLUE}" stroke-width="1.5"/>
|
||||
<circle cx="{half//2 - 30}" cy="360" r="45" fill="{ACCENT_BLUE}20" stroke="{ACCENT_BLUE}" stroke-width="1.5"/>
|
||||
<rect x="{half//2 - 70}" y="420" width="140" height="180" rx="10" fill="{ACCENT_BLUE}15" stroke="{ACCENT_BLUE}" stroke-width="1.5" opacity="0.6"/>
|
||||
<text x="{half//2}" y="680" font-family="system-ui, sans-serif" font-size="22" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Your Family</text>
|
||||
<text x="{half//2}" y="710" font-family="system-ui, sans-serif" font-size="15" fill="{TEXT_SECONDARY}" text-anchor="middle">Real & Unfiltered</text>
|
||||
|
||||
<!-- Center divider with phone icon -->
|
||||
<rect x="{half - 2}" y="0" width="4" height="{h}" fill="{BORDER}"/>
|
||||
<g transform="translate({half}, {h//2 - 60})">
|
||||
<rect x="-25" y="-50" width="50" height="100" rx="10" fill="{ACCENT_BLUE}" opacity="0.3"/>
|
||||
<path d="M-10,-10 Q-20,0 -10,10" fill="none" stroke="{ERROR}" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M0,-20 Q-25,0 0,20" fill="none" stroke="{ERROR}" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M10,-30 Q-30,0 10,30" fill="none" stroke="{ERROR}" stroke-width="2" stroke-linecap="round" opacity="0.7"/>
|
||||
</g>
|
||||
|
||||
<!-- Right panel: distorted/AI -->
|
||||
<rect x="{half}" y="0" width="{half}" height="{h}" fill="url(#bgGradR)"/>
|
||||
<g filter="url(#glitch)">
|
||||
<circle cx="{half + half//2}" cy="280" r="60" fill="{ERROR}30" stroke="{ERROR}" stroke-width="2"/>
|
||||
<circle cx="{half + half//2 - 60}" cy="220" r="40" fill="{ERROR}20" stroke="{ERROR}" stroke-width="1.5"/>
|
||||
<circle cx="{half + half//2 + 70}" cy="230" r="35" fill="{ERROR}20" stroke="{ERROR}" stroke-width="1.5"/>
|
||||
<circle cx="{half + half//2 - 30}" cy="360" r="45" fill="{ERROR}20" stroke="{ERROR}" stroke-width="1.5"/>
|
||||
<rect x="{half + half//2 - 70}" y="420" width="140" height="180" rx="10" fill="{ERROR}15" stroke="{ERROR}" stroke-width="1.5" opacity="0.6"/>
|
||||
</g>
|
||||
<text x="{half + half//2}" y="680" font-family="system-ui, sans-serif" font-size="22" font-weight="600" fill="{ERROR}" text-anchor="middle">AI Clone</text>
|
||||
<text x="{half + half//2}" y="710" font-family="system-ui, sans-serif" font-size="15" fill="{TEXT_MUTED}" text-anchor="middle">Synthetic & Dangerous</text>
|
||||
|
||||
<!-- Bottom brand bar -->
|
||||
<rect x="0" y="{h - 90}" width="{w}" height="90" fill="{CARD_BG}"/>
|
||||
<text x="{w//2}" y="{h - 55}" font-family="system-ui, sans-serif" font-size="22" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Your Family's Voice, Protected</text>
|
||||
<text x="{w//2}" y="{h - 28}" font-family="system-ui, sans-serif" font-size="15" fill="{TEXT_SECONDARY}" text-anchor="middle">ShieldAI detects AI voice cloning with 99.7% accuracy</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
def meta_a_191():
|
||||
"""1.91:1 (1200x628) — split-screen family / AI distortion"""
|
||||
w, h = 1200, 628
|
||||
half = w // 2
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgL" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#0a1528"/>
|
||||
<stop offset="100%" stop-color="#0f1d35"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="bgR" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#1a0a0a"/>
|
||||
<stop offset="100%" stop-color="#2d0f0f"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
<filter id="glitch2">
|
||||
<feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="2" result="noise"/>
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" xChannelSelector="R" yChannelSelector="G"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="{half}" height="{h}" fill="url(#bgL)"/>
|
||||
<circle cx="{half//2}" cy="{h//2 - 30}" r="35" fill="{ACCENT_BLUE}30" stroke="{ACCENT_BLUE}" stroke-width="2"/>
|
||||
<circle cx="{half//2 - 50}" cy="{h//2 - 80}" r="25" fill="{ACCENT_BLUE}20" stroke="{ACCENT_BLUE}" stroke-width="1.5"/>
|
||||
<circle cx="{half//2 + 55}" cy="{h//2 - 75}" r="22" fill="{ACCENT_BLUE}20" stroke="{ACCENT_BLUE}" stroke-width="1.5"/>
|
||||
<text x="{half//2}" y="{h//2 + 60}" font-family="system-ui, sans-serif" font-size="20" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Your Family</text>
|
||||
<rect x="0" y="{h - 50}" width="{half}" height="50" fill="{CARD_BG}"/>
|
||||
<text x="{half//2}" y="{h - 22}" font-family="system-ui, sans-serif" font-size="13" fill="{TEXT_SECONDARY}" text-anchor="middle">Real voice, real moment</text>
|
||||
|
||||
<rect x="{half - 1}" y="0" width="3" height="{h}" fill="{BORDER}"/>
|
||||
<rect x="{half}" y="0" width="{half}" height="{h}" fill="url(#bgR)"/>
|
||||
<g filter="url(#glitch2)">
|
||||
<circle cx="{half + half//2}" cy="{h//2 - 30}" r="35" fill="{ERROR}30" stroke="{ERROR}" stroke-width="2"/>
|
||||
<circle cx="{half + half//2 - 50}" cy="{h//2 - 80}" r="25" fill="{ERROR}20" stroke="{ERROR}" stroke-width="1.5"/>
|
||||
<circle cx="{half + half//2 + 55}" cy="{h//2 - 75}" r="22" fill="{ERROR}20" stroke="{ERROR}" stroke-width="1.5"/>
|
||||
</g>
|
||||
<text x="{half + half//2}" y="{h//2 + 60}" font-family="system-ui, sans-serif" font-size="20" font-weight="600" fill="{ERROR}" text-anchor="middle">AI Clone</text>
|
||||
<rect x="{half}" y="{h - 50}" width="{half}" height="50" fill="{ERROR}22"/>
|
||||
<text x="{half + half//2}" y="{h - 22}" font-family="system-ui, sans-serif" font-size="13" fill="{TEXT_MUTED}" text-anchor="middle">Synthetic voice clone</text>
|
||||
|
||||
<text x="30" y="50" font-family="system-ui, sans-serif" font-size="16" font-weight="600" fill="{TEXT_PRIMARY}">Your Family's Voice, Protected</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
# ============================================================
|
||||
# META CREATIVE B: Dark Web
|
||||
# ============================================================
|
||||
|
||||
def meta_b_1x1():
|
||||
"""1:1 (1080x1080) — dark terminal HUD aesthetic"""
|
||||
w, h = 1080, 1080
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgTerm" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#050a05"/>
|
||||
<stop offset="100%" stop-color="#0a1a0a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{SUCCESS}"/>
|
||||
<stop offset="100%" stop-color="#16a34a"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgTerm)"/>
|
||||
|
||||
<!-- Matrix-like grid lines -->
|
||||
<g stroke="{SUCCESS}10" stroke-width="0.5">
|
||||
<line x1="0" y1="100" x2="{w}" y2="100"/>
|
||||
<line x1="0" y1="200" x2="{w}" y2="200"/>
|
||||
<line x1="0" y1="300" x2="{w}" y2="300"/>
|
||||
<line x1="0" y1="400" x2="{w}" y2="400"/>
|
||||
<line x1="0" y1="500" x2="{w}" y2="500"/>
|
||||
<line x1="0" y1="600" x2="{w}" y2="600"/>
|
||||
<line x1="0" y1="700" x2="{w}" y2="700"/>
|
||||
<line x1="0" y1="800" x2="{w}" y2="800"/>
|
||||
<line x1="0" y1="900" x2="{w}" y2="900"/>
|
||||
<line x1="0" y1="1000" x2="{w}" y2="1000"/>
|
||||
</g>
|
||||
|
||||
<!-- Terminal window frame -->
|
||||
<rect x="100" y="200" width="{w - 200}" height="500" rx="12" fill="#0d1f0d" stroke="{SUCCESS}30" stroke-width="1.5"/>
|
||||
<rect x="100" y="200" width="{w - 200}" height="40" rx="12" fill="#143014"/>
|
||||
<rect x="100" y="228" width="{w - 200}" height="12" fill="#143014"/>
|
||||
<circle cx="130" cy="220" r="6" fill="{ERROR}"/>
|
||||
<circle cx="155" cy="220" r="6" fill="{WARNING}"/>
|
||||
<circle cx="180" cy="220" r="6" fill="{SUCCESS}"/>
|
||||
<text x="200" y="225" font-family="monospace" font-size="14" fill="{TEXT_MUTED}">darkwatch@shieldai:~$</text>
|
||||
|
||||
<!-- Terminal content -->
|
||||
<text x="130" y="280" font-family="monospace" font-size="16" fill="{WARNING}">> Scanning 150+ dark web marketplaces...</text>
|
||||
<text x="130" y="320" font-family="monospace" font-size="16" fill="{WARNING}">> Analyzing breach databases...</text>
|
||||
|
||||
<text x="130" y="380" font-family="monospace" font-size="18" font-weight="bold" fill="{ERROR}">! ALERT: MATCHES FOUND</text>
|
||||
|
||||
<rect x="130" y="410" width="320" height="28" fill="{ERROR}15"/>
|
||||
<text x="140" y="430" font-family="monospace" font-size="15" fill="{ERROR}">email:***@gmail.com — 3 breaches</text>
|
||||
|
||||
<rect x="130" y="445" width="320" height="28" fill="{ERROR}15"/>
|
||||
<text x="140" y="465" font-family="monospace" font-size="15" fill="{ERROR}">phone:+1 (555) ***-8842 — 2 breaches</text>
|
||||
|
||||
<rect x="130" y="480" width="320" height="28" fill="{ERROR}15"/>
|
||||
<text x="140" y="500" font-family="monospace" font-size="15" fill="{ERROR}">ssn:***-**-6781 — 1 breach</text>
|
||||
|
||||
<text x="130" y="550" font-family="monospace" font-size="16" fill="{SUCCESS}">> Total exposures found: 5,284</text>
|
||||
<text x="130" y="580" font-family="monospace" font-size="16" fill="{ACCENT_CYAN}">> Run scan on your data? [Y/n] _</text>
|
||||
|
||||
<!-- Bottom CTA -->
|
||||
<rect x="340" y="750" width="400" height="56" rx="28" fill="{SUCCESS}"/>
|
||||
<text x="540" y="785" font-family="system-ui, sans-serif" font-size="20" font-weight="700" fill="#050a05" text-anchor="middle">Scan Your Email Free</text>
|
||||
|
||||
<text x="{w//2}" y="860" font-family="system-ui, sans-serif" font-size="16" fill="{TEXT_MUTED}" text-anchor="middle">ShieldAI DarkWatch — 24/7 Dark Web Monitoring</text>
|
||||
|
||||
<text x="{w//2}" y="920" font-family="system-ui, sans-serif" font-size="28" font-weight="700" fill="{TEXT_PRIMARY}" text-anchor="middle">5K+ Exposures Found.</text>
|
||||
<text x="{w//2}" y="960" font-family="system-ui, sans-serif" font-size="28" font-weight="700" fill="{SUCCESS}" text-anchor="middle">What About Yours?</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
def meta_b_45():
|
||||
"""4:5 (1080x1350) — dark terminal HUD"""
|
||||
w, h = 1080, 1350
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgB45" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#050a05"/>
|
||||
<stop offset="100%" stop-color="#0a1a0a"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{SUCCESS}"/>
|
||||
<stop offset="100%" stop-color="#16a34a"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgB45)"/>
|
||||
|
||||
<!-- Terminal -->
|
||||
<rect x="80" y="250" width="{w - 160}" height="520" rx="12" fill="#0d1f0d" stroke="{SUCCESS}30" stroke-width="1.5"/>
|
||||
<rect x="80" y="250" width="{w - 160}" height="40" rx="12" fill="#143014"/>
|
||||
<rect x="80" y="278" width="{w - 160}" height="12" fill="#143014"/>
|
||||
<circle cx="110" cy="270" r="6" fill="{ERROR}"/>
|
||||
<circle cx="135" cy="270" r="6" fill="{WARNING}"/>
|
||||
<circle cx="160" cy="270" r="6" fill="{SUCCESS}"/>
|
||||
<text x="180" y="275" font-family="monospace" font-size="14" fill="{TEXT_MUTED}">darkwatch@shieldai:~$</text>
|
||||
|
||||
<text x="110" y="330" font-family="monospace" font-size="16" fill="{WARNING}">> Scanning 150+ dark web marketplaces...</text>
|
||||
<text x="110" y="360" font-family="monospace" font-size="16" fill="{WARNING}">> Cross-referencing databases...</text>
|
||||
|
||||
<text x="110" y="415" font-family="monospace" font-size="18" font-weight="bold" fill="{ERROR}">! ALERT: DATA EXPOSED</text>
|
||||
|
||||
<rect x="110" y="445" width="350" height="28" fill="{ERROR}15"/>
|
||||
<text x="120" y="465" font-family="monospace" font-size="14" fill="{ERROR}">email:***@gmail.com — 3 breaches</text>
|
||||
|
||||
<rect x="110" y="480" width="350" height="28" fill="{ERROR}15"/>
|
||||
<text x="120" y="500" font-family="monospace" font-size="14" fill="{ERROR}">phone:+1 (555) ***-8842 — 2 breaches</text>
|
||||
|
||||
<rect x="110" y="515" width="350" height="28" fill="{ERROR}15"/>
|
||||
<text x="120" y="535" font-family="monospace" font-size="14" fill="{ERROR}">ssn:***-**-6781 — 1 breach</text>
|
||||
|
||||
<rect x="110" y="550" width="350" height="28" fill="{ERROR}15"/>
|
||||
<text x="120" y="570" font-family="monospace" font-size="14" fill="{ERROR}">Address:*** Oak St — 1 breach</text>
|
||||
|
||||
<text x="110" y="625" font-family="monospace" font-size="16" fill="{SUCCESS}">> Total exposures monitored: 5,284</text>
|
||||
<text x="110" y="660" font-family="monospace" font-size="16" fill="{ACCENT_CYAN}">> Run scan on your data? [Y/n] _</text>
|
||||
|
||||
<text x="{w//2}" y="840" font-family="system-ui, sans-serif" font-size="30" font-weight="700" fill="{TEXT_PRIMARY}" text-anchor="middle">Your Data May Already Be</text>
|
||||
<text x="{w//2}" y="885" font-family="system-ui, sans-serif" font-size="30" font-weight="700" fill="{ERROR}" text-anchor="middle">For Sale on the Dark Web</text>
|
||||
|
||||
<text x="{w//2}" y="940" font-family="system-ui, sans-serif" font-size="16" fill="{TEXT_SECONDARY}" text-anchor="middle">ShieldAI scans 150+ marketplaces 24/7 and alerts you instantly</text>
|
||||
|
||||
<rect x="{w//2 - 175}" y="1000" width="350" height="56" rx="28" fill="{SUCCESS}"/>
|
||||
<text x="{w//2}" y="1035" font-family="system-ui, sans-serif" font-size="20" font-weight="700" fill="#050a05" text-anchor="middle">Scan Your Email Free</text>
|
||||
|
||||
<text x="{w//2}" y="{h - 50}" font-family="system-ui, sans-serif" font-size="14" fill="{TEXT_MUTED}" text-anchor="middle">ShieldAI — AI-Powered Identity Protection for Everyone</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
# ============================================================
|
||||
# META CREATIVE C: 3 Protections
|
||||
# ============================================================
|
||||
|
||||
def meta_c_1x1():
|
||||
"""1:1 (1080x1080) — three-panel layout"""
|
||||
w, h = 1080, 1080
|
||||
panel_w, panel_h = 300, 400
|
||||
gap = 30
|
||||
total_w = 3 * panel_w + 2 * gap
|
||||
start_x = (w - total_w) // 2
|
||||
top_y = 280
|
||||
|
||||
panels = [
|
||||
("VoicePrint", ACCENT_CYAN, "AI Voice Clone\nDetection", "Real-time detection\nof synthetic voices\nwith 99.7% accuracy"),
|
||||
("DarkWatch", ACCENT_BLUE, "Dark Web\nMonitoring", "24/7 scanning of\n150+ marketplaces\nfor your data"),
|
||||
("SpamShield", SUCCESS, "Spam Call &\nText Blocking", "AI-powered filtering\nof spam calls\nand text messages"),
|
||||
]
|
||||
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<linearGradient id="bgC" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="{DARK_BG}"/>
|
||||
<stop offset="100%" stop-color="#050812"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgC)"/>
|
||||
{brand_bar(w, 6)}
|
||||
|
||||
<text x="{w//2}" y="140" font-family="system-ui, sans-serif" font-size="42" font-weight="700" fill="{TEXT_PRIMARY}" text-anchor="middle">3 Ways ShieldAI Protects Your Family</text>
|
||||
<text x="{w//2}" y="185" font-family="system-ui, sans-serif" font-size="18" fill="{TEXT_SECONDARY}" text-anchor="middle">VoicePrint + DarkWatch + SpamShield</text>'''
|
||||
|
||||
for i, (name, color, title, desc) in enumerate(panels):
|
||||
px = start_x + i * (panel_w + gap)
|
||||
py = top_y
|
||||
cx = px + panel_w // 2
|
||||
icon_y = py + 60
|
||||
|
||||
svg += f'''
|
||||
<rect x="{px}" y="{py}" width="{panel_w}" height="{panel_h}" rx="16" fill="{CARD_BG}" stroke="{color}30" stroke-width="1.5"/>
|
||||
<circle cx="{cx}" cy="{icon_y}" r="40" fill="{color}22" stroke="{color}" stroke-width="2"/>
|
||||
<text x="{cx}" y="{icon_y + 5}" font-family="system-ui, sans-serif" font-size="18" font-weight="700" fill="{color}" text-anchor="middle">{name}</text>'''
|
||||
|
||||
lines = title.split('\n')
|
||||
for li, line in enumerate(lines):
|
||||
svg += f'''
|
||||
<text x="{cx}" y="{icon_y + 60 + li * 32}" font-family="system-ui, sans-serif" font-size="17" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">{line}</text>'''
|
||||
|
||||
desc_lines = desc.split('\n')
|
||||
for li, line in enumerate(desc_lines):
|
||||
svg += f'''
|
||||
<text x="{cx}" y="{icon_y + 120 + li * 25}" font-family="system-ui, sans-serif" font-size="14" fill="{TEXT_SECONDARY}" text-anchor="middle">{line}</text>'''
|
||||
|
||||
svg += f'''
|
||||
<rect x="{w//2 - 135}" y="760" width="270" height="52" rx="26" fill="{ACCENT_BLUE}"/>
|
||||
<text x="{w//2}" y="793" font-family="system-ui, sans-serif" font-size="18" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Join the Waitlist</text>
|
||||
|
||||
<text x="{w//2}" y="870" font-family="system-ui, sans-serif" font-size="15" fill="{TEXT_MUTED}" text-anchor="middle">Three critical protections, one powerful platform</text>
|
||||
<text x="{w//2}" y="900" font-family="system-ui, sans-serif" font-size="14" fill="{TEXT_MUTED}" text-anchor="middle">Start free. Launching soon.</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
# ============================================================
|
||||
# META CREATIVE D: Family Protection
|
||||
# ============================================================
|
||||
|
||||
def meta_d_base(w, h, small=False):
|
||||
"""Family protection — multi-generational family with digital shield overlay"""
|
||||
svg = f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
|
||||
<defs>
|
||||
<radialGradient id="shieldGlow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}30"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_BLUE}00"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="bgD" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="{DARK_BG}"/>
|
||||
<stop offset="60%" stop-color="#0d1a30"/>
|
||||
<stop offset="100%" stop-color="{DARK_BG}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="brandBar" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shieldGradD" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="{ACCENT_BLUE}"/>
|
||||
<stop offset="100%" stop-color="{ACCENT_CYAN}"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="{w}" height="{h}" fill="url(#bgD)"/>
|
||||
{brand_bar(w, 5)}
|
||||
|
||||
<!-- Digital shield overlay -->
|
||||
<circle cx="{w//2}" cy="{h//2}" r="{min(w,h)*0.38}" fill="url(#shieldGlow)"/>
|
||||
<g transform="translate({w//2}, {h//2 - 30})">
|
||||
<path d="M-60,-55 L60,-55 L65,15 Q65,55 35,75 L0,90 L-35,75 Q-65,55 -65,15 Z" fill="none" stroke="url(#shieldGradD)" stroke-width="3" opacity="0.8"/>
|
||||
<path d="M-25,-5 L0,25 L30,-15" fill="none" stroke="{SUCCESS}" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Family figures (simplified) -->
|
||||
{g_family_figures(w, h)}
|
||||
|
||||
<text x="{w//2}" y="{h - 160}" font-family="system-ui, sans-serif" font-size="32" font-weight="700" fill="{TEXT_PRIMARY}" text-anchor="middle">Protect Your Whole Family</text>
|
||||
<text x="{w//2}" y="{h - 115}" font-family="system-ui, sans-serif" font-size="17" fill="{TEXT_SECONDARY}" text-anchor="middle">AI voice clone detection + dark web monitoring + spam blocking</text>
|
||||
<text x="{w//2}" y="{h - 85}" font-family="system-ui, sans-serif" font-size="17" fill="{TEXT_SECONDARY}" text-anchor="middle">for up to unlimited family members on Premium</text>
|
||||
|
||||
<rect x="{w//2 - 115}" y="{h - 60}" width="230" height="46" rx="23" fill="{ACCENT_BLUE}"/>
|
||||
<text x="{w//2}" y="{h - 33}" font-family="system-ui, sans-serif" font-size="17" font-weight="600" fill="{TEXT_PRIMARY}" text-anchor="middle">Protect My Family</text>
|
||||
</svg>'''
|
||||
return svg
|
||||
|
||||
|
||||
def g_family_figures(w, h):
|
||||
"""Generate simple family figure silhouettes."""
|
||||
cx = w // 2
|
||||
base_y = h // 2 + 60
|
||||
return f'''
|
||||
<!-- Grandparent L -->
|
||||
<circle cx="{cx - 110}" cy="{base_y - 55}" r="22" fill="#33415580"/>
|
||||
<rect x="{cx - 125}" y="{base_y - 30}" width="30" height="50" rx="8" fill="#33415560"/>
|
||||
|
||||
<!-- Parent L -->
|
||||
<circle cx="{cx - 50}" cy="{base_y - 70}" r="25" fill="#47556980"/>
|
||||
<rect x="{cx - 68}" y="{base_y - 42}" width="36" height="65" rx="10" fill="#47556960"/>
|
||||
|
||||
<!-- Child -->
|
||||
<circle cx="{cx + 15}" cy="{base_y - 60}" r="18" fill="#64748b80"/>
|
||||
<rect x="{cx + 2}" y="{base_y - 40}" width="26" height="40" rx="8" fill="#64748b60"/>
|
||||
|
||||
<!-- Parent R -->
|
||||
<circle cx="{cx + 80}" cy="{base_y - 70}" r="25" fill="#47556980"/>
|
||||
<rect x="{cx + 62}" y="{base_y - 42}" width="36" height="65" rx="10" fill="#47556960"/>
|
||||
|
||||
<!-- Grandparent R -->
|
||||
<circle cx="{cx + 140}" cy="{base_y - 55}" r="22" fill="#33415580"/>
|
||||
<rect x="{cx + 125}" y="{base_y - 30}" width="30" height="50" rx="8" fill="#33415560"/>
|
||||
'''
|
||||
|
||||
|
||||
def meta_d_1x1():
|
||||
return meta_d_base(1080, 1080)
|
||||
|
||||
def meta_d_191():
|
||||
return meta_d_base(1200, 628)
|
||||
|
||||
def meta_d_45():
|
||||
return meta_d_base(1080, 1350)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# GENERATE ALL
|
||||
# ============================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
assets = [
|
||||
# Google Display
|
||||
("gd_square_1200x1200.svg", gd_square()),
|
||||
("gd_landscape_1200x628.svg", gd_landscape()),
|
||||
("gd_portrait_600x750.svg", gd_portrait()),
|
||||
# Meta Creative A
|
||||
("meta_a_1x1_1080x1080.svg", meta_a_1x1()),
|
||||
("meta_a_191_1200x628.svg", meta_a_191()),
|
||||
# Meta Creative B
|
||||
("meta_b_1x1_1080x1080.svg", meta_b_1x1()),
|
||||
("meta_b_45_1080x1350.svg", meta_b_45()),
|
||||
# Meta Creative C
|
||||
("meta_c_1x1_1080x1080.svg", meta_c_1x1()),
|
||||
# Meta Creative D
|
||||
("meta_d_1x1_1080x1080.svg", meta_d_1x1()),
|
||||
("meta_d_191_1200x628.svg", meta_d_191()),
|
||||
("meta_d_45_1080x1350.svg", meta_d_45()),
|
||||
]
|
||||
|
||||
for name, svg in assets:
|
||||
path = os.path.join(OUT, name)
|
||||
with open(path, 'w') as f:
|
||||
f.write(svg)
|
||||
print(f"Created: {name} ({len(svg)} bytes)")
|
||||
|
||||
print(f"\nDone. Generated {len(assets)} SVG files in {OUT}")
|
||||
Reference in New Issue
Block a user