"""Ilustrações técnicas SVG (substituíveis por fotografias — ver README)."""
import math, os

INK = "#0B2A3A"; BLUE = "#1677A6"; SKY = "#39A9DB"; GREEN = "#69B34C"; MUTED = "#5A7380"

def frame(body, w=800, h=560, dark=False, grid=True):
    bg1, bg2 = ("#0E3347", "#0B2A3A") if dark else ("#F7FAFB", "#E9F1F4")
    gl = "rgba(255,255,255,0.05)" if dark else "rgba(11,42,58,0.055)"
    g = f'<rect width="{w}" height="{h}" fill="url(#gp)"/>' if grid else ""
    return f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" width="{w}" height="{h}" role="img">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="{bg1}"/><stop offset="1" stop-color="{bg2}"/></linearGradient>
<linearGradient id="flow" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="{SKY}"/><stop offset="1" stop-color="{GREEN}"/></linearGradient>
<linearGradient id="flowv" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="{SKY}"/><stop offset="1" stop-color="{GREEN}" stop-opacity="0.2"/></linearGradient>
<linearGradient id="warm" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="{BLUE}"/><stop offset="1" stop-color="{SKY}"/></linearGradient>
<pattern id="gp" width="32" height="32" patternUnits="userSpaceOnUse"><path d="M32 0H0V32" fill="none" stroke="{gl}" stroke-width="1"/></pattern>
</defs>
<rect width="{w}" height="{h}" fill="url(#bg)"/>{g}
{body}
</svg>'''

def label(x, y, t, anchor="start", dark=False, size=12):
    c = "#9FC3D4" if dark else MUTED
    return f'<text x="{x}" y="{y}" font-family="Inter, Arial, sans-serif" font-size="{size}" letter-spacing="1.6" fill="{c}" text-anchor="{anchor}">{t}</text>'

def leader(x1, y1, x2, y2, dark=False):
    c = "#5F8EA3" if dark else "#9DB3BE"
    return f'<path d="M{x1} {y1}L{x2} {y2}" stroke="{c}" stroke-width="1"/><circle cx="{x1}" cy="{y1}" r="3" fill="{SKY}"/>'

def fan(cx, cy, r, stroke=INK, n=5):
    s = f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="none" stroke="{stroke}" stroke-width="2"/>'
    for k in range(1, 4):
        s += f'<circle cx="{cx}" cy="{cy}" r="{r*k/4:.1f}" fill="none" stroke="{stroke}" stroke-opacity="0.18" stroke-width="1"/>'
    for i in range(n):
        a = 2 * math.pi * i / n
        x1, y1 = cx + r * 0.15 * math.cos(a), cy + r * 0.15 * math.sin(a)
        x2, y2 = cx + r * 0.85 * math.cos(a + 0.5), cy + r * 0.85 * math.sin(a + 0.5)
        qx, qy = cx + r * 0.7 * math.cos(a - 0.1), cy + r * 0.7 * math.sin(a - 0.1)
        s += f'<path d="M{x1:.1f} {y1:.1f}Q{qx:.1f} {qy:.1f} {x2:.1f} {y2:.1f}" fill="none" stroke="{stroke}" stroke-width="2" stroke-linecap="round"/>'
    s += f'<circle cx="{cx}" cy="{cy}" r="{r*0.12:.1f}" fill="{stroke}"/>'
    return s

def outdoor_unit(x, y, w=220, h=170, stroke=INK, fill="#fff", tag=""):
    r = min(h * 0.36, w * 0.22)
    s = f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="6" fill="{fill}" stroke="{stroke}" stroke-width="2"/>'
    s += fan(x + w * 0.4, y + h / 2, r, stroke)
    gx = x + w * 0.74
    for i in range(9):
        yy = y + 18 + i * (h - 36) / 8
        s += f'<path d="M{gx} {yy:.1f}H{x + w - 16}" stroke="{stroke}" stroke-opacity="0.45" stroke-width="1.5"/>'
    s += f'<rect x="{x+10}" y="{y+h}" width="18" height="10" fill="{stroke}"/><rect x="{x+w-28}" y="{y+h}" width="18" height="10" fill="{stroke}"/>'
    return s

def flowlines(x, y, n=5, length=240, dy=16, curve=40, grad="url(#flow)", op=1):
    s = ""
    for i in range(n):
        yy = y + i * dy
        s += f'<path d="M{x} {yy}C{x+length*0.35} {yy+curve*0.2} {x+length*0.55} {yy+curve} {x+length} {yy+curve+i*6}" fill="none" stroke="{grad}" stroke-width="{2.2-i*0.25:.2f}" stroke-linecap="round" opacity="{op*(1-i*0.13):.2f}"/>'
    return s

def split_indoor(x, y, w=300, h=86, stroke=INK):
    s = f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="22" fill="#fff" stroke="{stroke}" stroke-width="2"/>'
    s += f'<path d="M{x+18} {y+h-20}H{x+w-18}" stroke="{stroke}" stroke-opacity="0.35" stroke-width="1.5"/>'
    s += f'<rect x="{x+w-46}" y="{y+18}" width="20" height="6" rx="3" fill="{GREEN}"/>'
    return s

# ---------------------------------------------------------------- cenas
def hero():
    d = True; L = "#8FB8CC"
    b = f'<path d="M40 500H760" stroke="{L}" stroke-opacity="0.5" stroke-width="1.5"/>'
    # casa em corte
    b += f'<path d="M110 500V196H560V500" fill="rgba(255,255,255,0.03)" stroke="{L}" stroke-width="2"/>'
    b += f'<rect x="96" y="178" width="490" height="20" fill="{L}" fill-opacity="0.25" stroke="{L}" stroke-width="1.5"/>'
    b += f'<rect x="110" y="338" width="450" height="12" fill="{L}" fill-opacity="0.2" stroke="{L}" stroke-width="1"/>'
    b += f'<path d="M470 210V328M470 362V490" stroke="{L}" stroke-opacity="0.5"/><path d="M500 210V328M530 210V328M500 362V490M530 362V490" stroke="{L}" stroke-opacity="0.25"/>'
    # unidade interior + fluxo
    b += f'<rect x="150" y="222" width="170" height="44" rx="14" fill="#123E54" stroke="{SKY}" stroke-width="2"/><rect x="290" y="234" width="14" height="5" rx="2.5" fill="{GREEN}"/>'
    b += flowlines(170, 274, n=6, length=270, dy=9, curve=46)
    # piso inferior — ventiloconvector de chão e sofá
    b += f'<rect x="150" y="452" width="120" height="38" rx="6" fill="#123E54" stroke="{L}" stroke-width="1.5"/>'
    for i in range(6):
        b += f'<path d="M{162+i*18} 460V482" stroke="{L}" stroke-opacity="0.5"/>'
    b += f'<path d="M210 446C230 420 250 410 280 404" fill="none" stroke="url(#flow)" stroke-width="2" stroke-linecap="round"/><path d="M200 446C214 414 236 396 262 386" fill="none" stroke="url(#flow)" stroke-width="1.6" stroke-linecap="round" opacity=".7"/>'
    b += f'<path d="M330 490V462H430V490M330 462V446H430V462" fill="none" stroke="{L}" stroke-opacity="0.45" stroke-width="1.5"/>'
    # bomba de calor exterior + tubagem
    b += outdoor_unit(600, 392, 150, 98, stroke=L, fill="#0F3A50")
    b += f'<path d="M600 430H560M600 446H560" stroke="{SKY}" stroke-width="2"/><path d="M560 430H330V270M560 446H344V270" fill="none" stroke="{SKY}" stroke-opacity="0.35" stroke-width="1.5" stroke-dasharray="4 5"/>'
    # cotas / etiquetas
    b += leader(320, 244, 360, 140, d) + label(366, 136, "UNIDADE INTERIOR", dark=d)
    b += leader(675, 392, 675, 330, d) + label(675, 318, "BOMBA DE CALOR", "middle", d)
    b += label(430, 300, "21 °C", dark=d, size=22) + label(430, 318, "CONFORTO", dark=d, size=10)
    b += f'<path d="M110 532H560" stroke="{L}" stroke-opacity="0.5"/><path d="M110 526V538M560 526V538" stroke="{L}" stroke-opacity="0.5"/>' + label(335, 552, "CORTE TRANSVERSAL — HABITAÇÃO", "middle", d, 10)
    return frame(b, dark=True)

def ar_condicionado():
    b = '<path d="M0 120H800" stroke="#C9D7DE" stroke-width="1"/>'
    b += split_indoor(250, 140)
    b += flowlines(290, 238, n=6, length=330, dy=12, curve=120)
    b += '<rect x="96" y="320" width="70" height="140" rx="12" fill="#fff" stroke="#0B2A3A" stroke-width="2"/><rect x="108" y="336" width="46" height="34" rx="4" fill="#E9F1F4" stroke="#0B2A3A" stroke-opacity=".3"/>'
    b += f'<text x="131" y="360" font-family="Inter, Arial, sans-serif" font-size="16" font-weight="600" fill="{BLUE}" text-anchor="middle">22°</text>'
    b += ''.join(f'<circle cx="{118+ (i%3)*13}" cy="{392+(i//3)*14}" r="4" fill="none" stroke="#0B2A3A" stroke-opacity=".5"/>' for i in range(9))
    b += leader(400, 140, 400, 92) + label(400, 80, "UNIDADE INTERIOR · MURAL", "middle")
    b += label(660, 470, "DISTRIBUIÇÃO DE AR", "end") + leader(620, 360, 660, 452)
    return frame(b)

def manutencao_preventiva():
    b = outdoor_unit(110, 190, 300, 220)
    # calendário
    x, y = 480, 150
    b += f'<rect x="{x}" y="{y}" width="230" height="250" rx="10" fill="#fff" stroke="{INK}" stroke-width="2"/><rect x="{x}" y="{y}" width="230" height="44" rx="10" fill="{INK}"/><rect x="{x}" y="{y+30}" width="230" height="14" fill="{INK}"/>'
    b += label(x+20, y+28, "PLANO ANUAL", size=11).replace(MUTED, "#CFE3EC")
    for i in range(12):
        cx, cy = x + 30 + (i % 4) * 56, y + 82 + (i // 4) * 62
        on = i in (0, 3, 6, 9)
        b += f'<rect x="{cx-18}" y="{cy-18}" width="36" height="36" rx="8" fill="{"#EAF5E4" if on else "#F4F7F8"}" stroke="{GREEN if on else "#C9D7DE"}"/>'
        if on:
            b += f'<path d="M{cx-8} {cy}l6 6 11-12" fill="none" stroke="{GREEN}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>'
    b += label(110, 460, "INSPECÇÃO · LIMPEZA · VERIFICAÇÃO DE DESEMPENHO")
    return frame(b)

def gauge(cx, cy, r, val, color):
    s = f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="#fff" stroke="{INK}" stroke-width="2.5"/><circle cx="{cx}" cy="{cy}" r="{r-10}" fill="none" stroke="#C9D7DE"/>'
    for i in range(21):
        a = math.radians(135 + i * 13.5)
        r1 = r - 12; r2 = r - (24 if i % 5 == 0 else 18)
        s += f'<path d="M{cx+r1*math.cos(a):.1f} {cy+r1*math.sin(a):.1f}L{cx+r2*math.cos(a):.1f} {cy+r2*math.sin(a):.1f}" stroke="{INK}" stroke-width="{2 if i%5==0 else 1}"/>'
    a = math.radians(135 + val * 270)
    s += f'<path d="M{cx} {cy}L{cx+(r-30)*math.cos(a):.1f} {cy+(r-30)*math.sin(a):.1f}" stroke="{color}" stroke-width="3" stroke-linecap="round"/><circle cx="{cx}" cy="{cy}" r="6" fill="{INK}"/>'
    return s

def manutencao_correctiva():
    b = '<rect x="190" y="250" width="420" height="70" rx="12" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
    b += gauge(290, 200, 82, 0.35, BLUE) + gauge(510, 200, 82, 0.7, GREEN)
    b += f'<path d="M250 320C230 420 160 440 120 470" fill="none" stroke="{BLUE}" stroke-width="7" stroke-linecap="round"/>'
    b += f'<path d="M400 320C400 420 400 440 400 490" fill="none" stroke="#9DB3BE" stroke-width="7" stroke-linecap="round"/>'
    b += f'<path d="M550 320C570 420 640 440 680 470" fill="none" stroke="{GREEN}" stroke-width="7" stroke-linecap="round"/>'
    b += label(290, 100, "BAIXA PRESSÃO", "middle") + label(510, 100, "ALTA PRESSÃO", "middle")
    b += label(400, 530, "DIAGNÓSTICO DO CIRCUITO FRIGORÍFICO", "middle")
    return frame(b)

def assistencia():
    b = '<rect x="150" y="110" width="320" height="360" rx="22" fill="#fff" stroke="#0B2A3A" stroke-width="2"/><rect x="172" y="140" width="276" height="250" rx="8" fill="#F4F7F8" stroke="#C9D7DE"/>'
    b += label(190, 170, "DIAGNÓSTICO", size=11)
    b += f'<path d="M190 300 L230 300 L250 250 L270 330 L290 220 L310 300 L430 300" fill="none" stroke="{BLUE}" stroke-width="2.5" stroke-linejoin="round"/>'
    b += f'<path d="M190 360H330" stroke="{GREEN}" stroke-width="8" stroke-linecap="round"/><path d="M330 360H430" stroke="#D5E1E6" stroke-width="8" stroke-linecap="round"/>'
    b += '<circle cx="310" cy="430" r="18" fill="none" stroke="#0B2A3A" stroke-width="2"/>'
    b += outdoor_unit(520, 300, 200, 150)
    b += f'<path d="M470 250C520 250 560 230 600 300" fill="none" stroke="{SKY}" stroke-width="2" stroke-dasharray="5 6"/>'
    b += label(620, 280, "LEITURA", "middle")
    return frame(b)

def bombas_de_calor():
    b = outdoor_unit(80, 200, 300, 220)
    b += '<rect x="520" y="110" width="170" height="330" rx="80" ry="40" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
    b += f'<rect x="545" y="150" width="120" height="120" rx="10" fill="url(#flowv)" opacity=".35"/>'
    b += f'<path d="M380 270H450V200H520" fill="none" stroke="{BLUE}" stroke-width="5" stroke-linejoin="round"/><path d="M380 330H470V380H520" fill="none" stroke="{SKY}" stroke-width="5" stroke-linejoin="round"/>'
    b += f'<path d="M605 110V70H720" fill="none" stroke="{GREEN}" stroke-width="5"/>'
    b += label(605, 470, "ÁGUAS QUENTES SANITÁRIAS", "middle") + label(230, 470, "UNIDADE EXTERIOR", "middle")
    b += label(720, 60, "CONSUMO", "end")
    return frame(b)

def ventiloconvectores():
    b = '<path d="M0 140H800" stroke="#0B2A3A" stroke-opacity=".4" stroke-width="2"/><rect x="0" y="100" width="800" height="40" fill="#E1EAEE"/>'
    b += '<rect x="260" y="140" width="280" height="40" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
    b += '<rect x="230" y="180" width="340" height="22" rx="4" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
    for i in range(14):
        b += f'<path d="M{250+i*22} 186V196" stroke="#0B2A3A" stroke-opacity=".5"/>'
    b += '<rect x="340" y="186" width="120" height="10" fill="#F4F7F8" stroke="#0B2A3A" stroke-opacity=".3"/>'
    for s in (-1, 1):
        for i in range(4):
            x0 = 400 + s * (110 + i * 10)
            b += f'<path d="M{x0} 206C{x0+s*30} {260+i*10} {x0+s*70} {320+i*20} {x0+s*90} {420+i*20}" fill="none" stroke="url(#flowv)" stroke-width="{2.2-i*0.4:.1f}" stroke-linecap="round"/>'
    b += leader(400, 202, 400, 300) + label(400, 318, "VENTILOCONVECTOR TIPO CASSETE", "middle")
    b += label(60, 90, "TECTO FALSO")
    return frame(b)

def vmc():
    b = '<rect x="290" y="200" width="220" height="160" rx="10" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
    b += '<path d="M290 200L510 360M510 200L290 360" stroke="#0B2A3A" stroke-opacity=".35" stroke-width="1.5"/><rect x="360" y="240" width="80" height="80" transform="rotate(45 400 280)" fill="#F4F7F8" stroke="#0B2A3A" stroke-width="1.5"/>'
    ducts = [(90, 230, "AR NOVO", SKY, 1), (90, 330, "EXAUSTÃO", "#9DB3BE", -1), (510, 230, "INSUFLAÇÃO", GREEN, 1), (510, 330, "EXTRACÇÃO", BLUE, -1)]
    for x, y, t, c, d in ducts:
        b += f'<rect x="{x}" y="{y-20}" width="200" height="40" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
        ax = x + 100
        if d > 0:
            b += f'<path d="M{ax-30} {y}H{ax+30}M{ax+18} {y-10}l12 10-12 10" fill="none" stroke="{c}" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>'
        else:
            b += f'<path d="M{ax+30} {y}H{ax-30}M{ax-18} {y-10}l-12 10 12 10" fill="none" stroke="{c}" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>'
        b += label(x + 100, y + (-34 if y < 280 else 48), t, "middle", size=11)
    b += label(400, 410, "RECUPERADOR DE CALOR", "middle")
    return frame(b)

def higienizacao():
    b = split_indoor(140, 120, 360, 100)
    b += '<rect x="250" y="270" width="300" height="170" rx="6" fill="#fff" stroke="#0B2A3A" stroke-width="2" transform="rotate(-8 400 355)"/>'
    for i in range(12):
        b += f'<path d="M{270+i*24} 290V420" stroke="#0B2A3A" stroke-opacity=".25" transform="rotate(-8 400 355)"/>'
    for i in range(6):
        b += f'<path d="M{270} {300+i*22}H{530}" stroke="#0B2A3A" stroke-opacity=".15" transform="rotate(-8 400 355)"/>'
    import random; random.seed(4)
    for i in range(26):
        x, y = random.uniform(560, 730), random.uniform(160, 460)
        b += f'<circle cx="{x:.0f}" cy="{y:.0f}" r="{random.uniform(1.5,4.5):.1f}" fill="#9DB3BE" opacity="{max(0.15,0.8-(x-560)/220):.2f}"/>'
    b += f'<path d="M560 330C610 300 650 300 720 320" fill="none" stroke="url(#flow)" stroke-width="2.5" stroke-linecap="round"/>'
    b += label(400, 500, "FILTROS · PERMUTADORES · TABULEIROS DE CONDENSADOS", "middle")
    return frame(b)

def eficiencia():
    cls = [("A+++", "#2F9E44", 230), ("A++", "#69B34C", 270), ("A+", "#A6CE39", 310), ("A", "#E7E33B", 350), ("B", "#F9B233", 390), ("C", "#EE7D2F", 430), ("D", "#E3352B", 470)]
    b = ""
    for i, (t, c, w) in enumerate(cls):
        y = 110 + i * 50
        b += f'<path d="M150 {y}H{150+w}l20 20-20 20H150z" fill="{c}" opacity="{1 if i<2 else 0.35}"/>'
        b += f'<text x="166" y="{y+27}" font-family="Manrope, Arial, sans-serif" font-weight="800" font-size="18" fill="#fff">{t}</text>'
    b += f'<path d="M520 135H600" stroke="{INK}" stroke-width="2"/><path d="M600 120l20 15-20 15z" fill="{INK}" transform="rotate(180 610 135)"/>'
    b += label(630, 140, "CLASSE ENERGÉTICA", size=11)
    b += label(150, 490, "ESCALA DE EFICIÊNCIA ENERGÉTICA · REFERÊNCIA ILUSTRATIVA")
    return frame(b)

def pre_instalacao():
    b = '<rect x="120" y="90" width="560" height="380" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
    b += '<rect x="140" y="110" width="520" height="340" fill="none" stroke="#0B2A3A" stroke-opacity=".2" stroke-dasharray="6 6"/>'
    b += f'<path d="M560 170H260V420" fill="none" stroke="{BLUE}" stroke-width="5"/><path d="M560 190H280V420" fill="none" stroke="{SKY}" stroke-width="5"/><path d="M560 210H300V420" fill="none" stroke="#9DB3BE" stroke-width="3" stroke-dasharray="8 6"/>'
    b += '<rect x="520" y="150" width="120" height="80" rx="8" fill="#F4F7F8" stroke="#0B2A3A" stroke-width="1.5" stroke-dasharray="5 5"/>'
    b += '<path d="M240 420H320V470" fill="none" stroke="#0B2A3A" stroke-opacity=".4"/>'
    b += label(580, 250, "CAIXA DE ESPERA", "middle", size=11) + label(330, 320, "FRIGORÍFICO · CONDENSADOS · ALIMENTAÇÃO", size=11)
    b += '<path d="M120 500H680M120 494V506M680 494V506" stroke="#9DB3BE"/>' + label(400, 525, "TRAÇADO TÉCNICO", "middle", size=11)
    return frame(b)

def building(kind):
    b = '<path d="M40 470H760" stroke="#9DB3BE" stroke-width="1.5"/>'
    if kind == "residencial":
        b += '<path d="M180 470V250H470V470" fill="#fff" stroke="#0B2A3A" stroke-width="2"/><rect x="160" y="230" width="330" height="22" fill="#E1EAEE" stroke="#0B2A3A" stroke-width="2"/>'
        b += '<path d="M470 470V330H640V470" fill="#fff" stroke="#0B2A3A" stroke-width="2"/><rect x="455" y="314" width="200" height="18" fill="#E1EAEE" stroke="#0B2A3A" stroke-width="2"/>'
        b += '<rect x="210" y="290" width="140" height="130" fill="#EAF3F7" stroke="#0B2A3A" stroke-width="1.5"/><path d="M280 290V420" stroke="#0B2A3A" stroke-opacity=".4"/>'
        b += '<rect x="380" y="300" width="60" height="170" fill="#EAF3F7" stroke="#0B2A3A" stroke-width="1.5"/>'
        b += outdoor_unit(530, 400, 90, 60)
        b += flowlines(220, 270, 3, 120, 8, 20, op=.9)
    elif kind == "comercial":
        for i, (x, h) in enumerate([(170, 330), (360, 260), (540, 200)]):
            w = 170 if i < 2 else 150
            b += f'<rect x="{x}" y="{470-h}" width="{w}" height="{h}" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
            for r in range(int(h // 34)):
                b += f'<path d="M{x+12} {470-h+24+r*34}H{x+w-12}" stroke="{SKY}" stroke-opacity=".45" stroke-width="6"/>'
        b += outdoor_unit(190, 106, 60, 34) + outdoor_unit(270, 106, 60, 34)
    else:
        b += '<path d="M120 470V260L270 200V260L420 200V260L570 200V470Z" fill="#fff" stroke="#0B2A3A" stroke-width="2" stroke-linejoin="round"/>'
        b += '<rect x="570" y="300" width="110" height="170" fill="#fff" stroke="#0B2A3A" stroke-width="2"/>'
        b += '<path d="M150 380H540" stroke="#0B2A3A" stroke-opacity=".25"/><path d="M180 300H520V320H180z" fill="#E1EAEE" stroke="#0B2A3A" stroke-width="1.5"/>'
        for i in range(5):
            b += f'<path d="M{220+i*70} 320V360" stroke="#0B2A3A" stroke-opacity=".5"/><path d="M{205+i*70} 360h30l-6 10h-18z" fill="#0B2A3A" opacity=".6"/>'
        b += outdoor_unit(580, 230, 90, 60) + '<rect x="160" y="410" width="120" height="60" fill="#EAF3F7" stroke="#0B2A3A" stroke-width="1.5"/>'
        b += flowlines(200, 380, 3, 300, 8, 10, op=.8)
    return frame(b)

def empresa():
    # planta com traçado de condutas
    b = '<rect x="90" y="80" width="620" height="400" fill="#fff" stroke="#0B2A3A" stroke-width="3"/>'
    b += '<path d="M330 80V260M330 320V480M330 260H90M520 80V200M520 260V480M520 260H710" stroke="#0B2A3A" stroke-width="2"/>'
    b += f'<path d="M140 290H660" stroke="{BLUE}" stroke-width="12" stroke-opacity=".25"/><path d="M140 290H660" stroke="{BLUE}" stroke-width="2"/>'
    for x in (210, 420, 610):
        b += f'<path d="M{x} 290V{170}" stroke="{SKY}" stroke-width="8" stroke-opacity=".3"/><rect x="{x-22}" y="150" width="44" height="22" fill="#fff" stroke="{SKY}" stroke-width="2"/>'
        b += f'<path d="M{x} 290V{400}" stroke="{GREEN}" stroke-width="8" stroke-opacity=".3"/><rect x="{x-22}" y="400" width="44" height="22" fill="#fff" stroke="{GREEN}" stroke-width="2"/>'
    b += label(100, 60, "PLANTA · REDE DE CONDUTAS", size=11) + label(700, 512, "ESC. 1:100", "end", size=11)
    return frame(b)

SCENES = {
    "hero": hero, "ar-condicionado": ar_condicionado, "manutencao-preventiva": manutencao_preventiva,
    "manutencao-correctiva": manutencao_correctiva, "assistencia-tecnica-avac": assistencia,
    "bombas-de-calor": bombas_de_calor, "ventiloconvectores": ventiloconvectores,
    "ventilacao-mecanica-controlada": vmc, "higienizacao-de-equipamentos": higienizacao,
    "eficiencia-energetica": eficiencia, "pre-instalacoes": pre_instalacao,
    "residencial": lambda: building("residencial"), "comercial": lambda: building("comercial"),
    "industrial": lambda: building("industrial"), "empresa": empresa,
}

def write_all(outdir):
    os.makedirs(outdir, exist_ok=True)
    for k, f in SCENES.items():
        with open(os.path.join(outdir, k + ".svg"), "w") as fh:
            fh.write(f())

if __name__ == "__main__":
    write_all("src/assets/img/ilustracoes")
