Herramientas de ObraPro
Todo en páginas separadas, limpio y fácil de usar.
import os, zipfile, textwrap, pathlib base="/mnt/data/obrapro_limpio" os.makedirs(base, exist_ok=True) style = """*{box-sizing:border-box} :root{--dark:#061225;--dark2:#0b1d3a;--blue:#1f7aff;--green:#16b84e;--text:#0f172a;--muted:#64748b;--line:#e5e7eb;--card:#ffffff} body{margin:0;font-family:Arial,Helvetica,sans-serif;background:#f8fafc;color:var(--text)} a{text-decoration:none} .header{background:#061225;color:#fff;position:sticky;top:0;z-index:10;border-bottom:1px solid rgba(255,255,255,.08)} .nav{max-width:1180px;margin:auto;padding:16px 20px;display:flex;align-items:center;justify-content:space-between;gap:20px} .logo{font-size:30px;font-weight:900;color:#fff}.logo span{color:var(--blue)} .menu{display:flex;gap:20px;flex-wrap:wrap}.menu a{color:#fff;font-weight:700;font-size:14px} .btn{display:inline-block;background:var(--blue);color:#fff;padding:14px 20px;border-radius:10px;font-weight:800;border:0;cursor:pointer;margin:6px 4px} .btn.green{background:var(--green)}.btn.dark{background:#111827}.btn.outline{background:transparent;border:1px solid #fff}.btn.red{background:#ef4444}.btn.orange{background:#f97316} .hero{background:linear-gradient(90deg,rgba(6,18,37,.97),rgba(6,18,37,.88)),url('https://images.unsplash.com/photo-1503387762-592deb58ef4e?auto=format&fit=crop&w=1600&q=80');background-size:cover;background-position:center;color:#fff} .hero-inner{max-width:1180px;margin:auto;padding:70px 20px;display:grid;grid-template-columns:1.4fr .8fr;gap:35px;align-items:center} .hero h1{font-size:clamp(40px,6vw,66px);line-height:1.05;margin:0 0 18px}.hero h1 span{color:var(--blue)} .hero p{font-size:18px;line-height:1.7;max-width:720px} .hero-card{background:#fff;color:var(--text);border-radius:18px;padding:26px;box-shadow:0 20px 50px rgba(0,0,0,.35)} .container{max-width:1180px;margin:auto;padding:42px 20px} .center{text-align:center}.muted{color:var(--muted)} .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:18px} .card{background:#fff;border:1px solid var(--line);border-radius:16px;padding:24px;box-shadow:0 10px 25px rgba(15,23,42,.06)} .card h3{margin-top:0}.icon{width:62px;height:62px;border-radius:50%;display:grid;place-items:center;background:#dbeafe;color:var(--blue);font-size:28px;margin-bottom:15px} label{display:block;font-weight:800;margin-top:13px} input,select,textarea{width:100%;padding:13px;margin-top:7px;border:1px solid #cbd5e1;border-radius:10px;font-size:15px} .result{background:#f1f5f9;border-left:5px solid var(--green);padding:18px;border-radius:12px;margin-top:18px} .footer{background:#061225;color:#cbd5e1;text-align:center;padding:25px;margin-top:40px} .badge{display:inline-block;background:#dbeafe;color:#1d4ed8;padding:6px 10px;border-radius:999px;font-weight:800;font-size:13px} @media(max-width:850px){.hero-inner{grid-template-columns:1fr}.nav{display:block;text-align:center}.menu{justify-content:center;margin-top:12px}.hero-inner{padding:45px 18px}} """ app = """let ultimaCotizacion=null; function money(n){return "$"+Number(n||0).toFixed(2)} function calcularDrywall(){ const cliente=document.getElementById("cliente").value||"Cliente"; const telefono=document.getElementById("telefonoCliente").value||""; const ciudad=document.getElementById("ciudad").value||"No especificado"; const largo=parseFloat(document.getElementById("largo").value)||0; const alto=parseFloat(document.getElementById("alto").value)||0; const mano=parseFloat(document.getElementById("manoObra").value)||0; const margen=parseFloat(document.getElementById("margen").value)||0; if(largo<=0||alto<=0){alert("Coloca largo y alto válidos.");return;} const area=largo*alto, areaExtra=area*1.10; const laminas=Math.ceil(areaExtra/2.88); const perfiles=Math.ceil((largo*2+alto*2)/2.44); const parales=Math.ceil(largo/0.61)+1; const tornillos=Math.ceil(laminas*35); const masillaKg=Math.ceil(areaExtra*.35); const cintaM=Math.ceil(areaExtra*1.2); const pL=parseFloat(document.getElementById("precioLamina").value)||12; const pP=parseFloat(document.getElementById("precioPerfil").value)||4; const pPar=parseFloat(document.getElementById("precioParal").value)||4; const pT=parseFloat(document.getElementById("precioTornillo").value)||.03; const pM=parseFloat(document.getElementById("precioMasilla").value)||1.5; const pC=parseFloat(document.getElementById("precioCinta").value)||.12; const materiales=laminas*pL+perfiles*pP+parales*pPar+tornillos*pT+masillaKg*pM+cintaM*pC; const manoObra=area*mano; const subtotal=materiales+manoObra; const ganancia=subtotal*(margen/100); const total=subtotal+ganancia; ultimaCotizacion={cliente,telefono,ciudad,area,laminas,perfiles,parales,tornillos,masillaKg,cintaM,materiales,manoObra,ganancia,total,fecha:new Date().toLocaleString()}; localStorage.setItem("ultimaCotizacionObraPro",JSON.stringify(ultimaCotizacion)); document.getElementById("resultado").innerHTML=`
Cliente: ${cliente}
Área: ${area.toFixed(2)} m²
Láminas: ${laminas}
Perfiles: ${perfiles}
Parales: ${parales}
Tornillos: ${tornillos}
Masilla: ${masillaKg} kg
Cinta: ${cintaM} m
Materiales: ${money(materiales)}
Mano de obra: ${money(manoObra)}
Ganancia: ${money(ganancia)}
Todavía no hay contratistas registrados. El primero aparecerá aquí después de llenar el formulario.
Registrar empresa${c.cliente} - ${c.ciudad}
Área: ${c.area.toFixed(2)} m²
${c.ciudad}
${c.servicios}
${c.whatsapp}
${c.plan}ObraPro ayuda a contratistas y clientes en LATAM a calcular materiales, crear presupuestos profesionales, descargar PDF y contactar por WhatsApp.
Ir a calculadora Buscar contratistas Registrar mi empresaCalcula área, láminas, perfiles, tornillos, masilla, cinta, mano de obra y ganancia.
✅ Cálculo automático
✅ PDF profesional
✅ WhatsApp automático
Calcular ahoraTodo en páginas separadas, limpio y fácil de usar.
Calcula materiales, mano de obra, ganancia, PDF y WhatsApp.