{"id":17433,"date":"2026-10-09T21:20:52","date_gmt":"2026-10-10T03:20:52","guid":{"rendered":"https:\/\/velaproducciones.com\/calculadora-de-precios\/"},"modified":"2026-10-16T14:17:26","modified_gmt":"2026-10-16T20:17:26","slug":"calculadora-de-precios","status":"publish","type":"page","link":"https:\/\/velaproducciones.com\/en\/calculadora-de-precios\/","title":{"rendered":"Pricing Calculator"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"17433\" class=\"elementor elementor-17433 elementor-bc-flex-widget\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4b0f51aa elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4b0f51aa\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5775012a\" data-id=\"5775012a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-44bee938 elementor-widget elementor-widget-html\" data-id=\"44bee938\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- Calculadora de precios y punto de equilibrio \u00b7 Vela Producciones \u00b7 generado por generar.py (editar las piezas de la carpeta, no este archivo) -->\n<!-- Tipograf\u00eda Inter, la misma del Generador de Buyer Persona. -->\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap\" rel=\"stylesheet\">\n<style>\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   SISTEMA DE DISE\u00d1O DE LAS HERRAMIENTAS DE VELA PRODUCCIONES\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Es el mismo lenguaje visual del Generador de Buyer Persona y del test\n   \u00abArquitectura del Emprendedor\u00bb: Inter, fondo #f9f8ff, tarjetas blancas con\n   sombra profunda, degradados \u00edndigo (#6254e7 \u2192 #9289f1) y esmeralda\n   (#10b981 \u2192 #34d399), notas post-it.\n\n   Este archivo es la \u00daNICA fuente del dise\u00f1o: cada herramienta lo toma y a\u00f1ade\n   lo suyo al final en su propio `<style>`. As\u00ed las tres (y las que vengan) se\n   ven iguales sin copiar el CSS tres veces.\n\n   Todo va bajo el contenedor `.vh` \u2026 hmm, no: el contenedor es `.vh` (vela\n   herramientas) para no chocar con la clase de la herramienta de Arquitectura,\n   que ya est\u00e1 publicada.\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n\/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   ARQUITECTURA DEL EMPRENDEDOR \u00b7 Vela Producciones\n   Mismo lenguaje visual que el Generador de Buyer Persona:\n   Inter \u00b7 fondo #f9f8ff \u00b7 tarjetas blancas con sombra profunda \u00b7 degradados\n   \u00edndigo (#6254e7 \u2192 #9289f1) y esmeralda (#10b981 \u2192 #34d399) \u00b7 notas post-it.\n   Sin Tailwind ni librer\u00edas: todo el CSS va aqu\u00ed, as\u00ed la herramienta no depende\n   de ninguna CDN para verse bien.\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n:root{\n  --indigo:#6254e7; --indigo-claro:#9289f1; --indigo-oscuro:#4a3ccb; --indigo-suave:#f4f2ff;\n  --esmeralda:#10b981; --esmeralda-claro:#34d399;\n  --ambar:#f59e0b; --rojo:#e11d48;\n  --slate-900:#0f172a; --slate-700:#334155; --slate-500:#696687; --slate-300:#cbd5e1; --slate-200:#e2ddf9;\n  --fondo:#f9f8ff; --blanco:#fff;\n  --sombra:0 20px 25px -5px rgb(0 0 0 \/ .1), 0 8px 10px -6px rgb(0 0 0 \/ .1);\n  --sombra-suave:0 4px 14px 0 rgb(0 0 0 \/ .1);\n}\n*{box-sizing:border-box}\n.vh{\n  margin:0; padding:0; font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;\n  background:var(--fondo); color:var(--slate-700); line-height:1.6; -webkit-font-smoothing:antialiased;\n}\n\/* El tema del sitio (ewebot) impone su tipograf\u00eda a los t\u00edtulos con reglas m\u00e1s espec\u00edficas\n   (`.elementor-widget-heading h1.elementor-heading-title {font-family:Nunito}`), as\u00ed que aqu\u00ed\n   Inter va con !important: la herramienta tiene que verse igual que el Generador de Buyer Persona\n   aunque el tema cambie sus fuentes. Es el \u00fanico !important del archivo y est\u00e1 acotado a .vh. *\/\n.vh, .vh *{font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif !important}\n.vh-contenedor{max-width:1100px; margin:0 auto; padding:2rem 1rem 4rem}\n.vh h1,.vh h2,.vh h3,.vh h4{color:var(--slate-900); line-height:1.25; margin:0 0 .75rem}\n.vh h1{font-size:clamp(1.75rem,4vw,2.5rem); font-weight:800; letter-spacing:-.02em}\n.vh h2{font-size:clamp(1.35rem,3vw,1.75rem); font-weight:800; letter-spacing:-.01em}\n.vh h3{font-size:1.125rem; font-weight:700}\n.vh h4{font-size:1rem; font-weight:700}\n.vh p{margin:0 0 1rem}\n.vh a{color:var(--indigo-oscuro)}\n.vh .gris{color:var(--slate-500)}\n.vh .chico{font-size:.875rem}\n.vh .micro{font-size:.8rem}\n.vh .oculto{display:none !important}\n\n\/* \u2500\u2500 tarjetas \u2500\u2500 *\/\n.blanco{background:var(--blanco); border-radius:1rem; padding:2rem; box-shadow:var(--sombra); margin-bottom:1.5rem}\n.blanco.ajustado{padding:1.25rem}\n.post-it{box-shadow:10px 10px 25px rgba(0,0,0,.1); transition:transform .3s ease, box-shadow .3s ease;\n  padding:1.5rem; border-radius:.75rem; margin-bottom:1.5rem}\n.post-it:hover{transform:rotate(0deg) translateY(-3px) !important; box-shadow:14px 14px 30px rgba(0,0,0,.14)}\n.post-it-amarillo{background:#fef9c3; transform:rotate(-1.2deg)}\n.post-it-rosa{background:#fce7f3; transform:rotate(1deg)}\n.post-it-azul{background:#dbeafe; transform:rotate(-.8deg)}\n.post-it-verde{background:#dcfce7; transform:rotate(1.1deg)}\n.post-it-morado{background:#e2ddf9; transform:rotate(-.5deg)}\n\n\/* \u2500\u2500 encabezado \u2500\u2500 *\/\n.cabecera{display:flex; flex-wrap:wrap; gap:1.5rem; align-items:center; justify-content:space-between;\n  border-bottom:1px solid var(--slate-200); padding-bottom:1.5rem; margin-bottom:1.5rem}\n.cabecera .titulos{flex:1 1 320px}\n.etiqueta{display:inline-block; font-size:.75rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase;\n  color:var(--indigo-oscuro); background:var(--indigo-suave); padding:.35rem .75rem; border-radius:999px; margin-bottom:.75rem}\n.marcador{text-align:center; min-width:190px}\n.marcador .numero{font-size:2.75rem; font-weight:900; color:var(--slate-900); line-height:1}\n.marcador .de{font-size:.9rem; color:var(--slate-500); font-weight:600}\n.barra{height:.75rem; background:var(--slate-200); border-radius:999px; overflow:hidden; margin:.75rem 0 .5rem}\n.barra > span{display:block; height:100%; width:0; border-radius:999px; transition:width .4s ease, background-color .3s}\n.barra-indigo > span{background:linear-gradient(to right,var(--indigo),var(--indigo-claro))}\n.barra-verde > span{background:linear-gradient(to right,var(--esmeralda),var(--esmeralda-claro))}\n.barra-ambar > span{background:linear-gradient(to right,#f59e0b,#fbbf24)}\n.barra-rojo > span{background:linear-gradient(to right,#e11d48,#fb7185)}\n.pastilla{display:inline-block; font-size:.75rem; font-weight:700; padding:.25rem .75rem; border-radius:999px; border:1px solid}\n.pastilla-verde{background:#d1fae5; color:#065f46; border-color:#6ee7b7}\n.pastilla-ambar{background:#fef3c7; color:#92400e; border-color:#fcd34d}\n.pastilla-rojo{background:#ffe4e6; color:#9f1239; border-color:#fda4af}\n.pastilla-indigo{background:var(--indigo-suave); color:var(--indigo-oscuro); border-color:#e2ddf9}\n.pastilla-gris{background:#f1f5f9; color:var(--slate-500); border-color:var(--slate-300)}\n\n\/* \u2500\u2500 pesta\u00f1as \u2500\u2500 *\/\n.pestanas{display:flex; flex-wrap:wrap; gap:.5rem; margin-bottom:1.5rem}\n.pestana{background:var(--blanco); border:1px solid var(--slate-200); color:var(--slate-700); font-weight:700;\n  font-size:.9rem; padding:.7rem 1.1rem; border-radius:.75rem; cursor:pointer; transition:all .2s; box-shadow:var(--sombra-suave)}\n.pestana:hover{border-color:#e2ddf9; transform:translateY(-2px)}\n.pestana.activa{background-image:linear-gradient(to right,var(--indigo),var(--indigo-claro)); color:#fff; border-color:transparent}\n.pestana .num{display:inline-block; background:rgba(255,255,255,.25); border-radius:.4rem; padding:0 .4rem; margin-right:.4rem; font-weight:800}\n.pestana:not(.activa) .num{background:var(--indigo-suave); color:var(--indigo-oscuro)}\n\n\/* \u2500\u2500 formulario \u2500\u2500 *\/\n.form-label{font-weight:600; color:var(--slate-700); margin-bottom:.75rem; display:block}\n.form-input,.form-select,.form-textarea{width:100%; border:1px solid #d1d5db; border-radius:.75rem; padding:.75rem 1rem;\n  color:var(--slate-700); transition:all .2s ease-in-out; background-color:#f9fafb; font-family:inherit; font-size:1rem}\n.form-input:focus,.form-select:focus,.form-textarea:focus{outline:none; border-color:#4f46e5; box-shadow:0 0 0 3px rgba(79,70,229,.2); background:#fff}\n\n\/* \u2500\u2500 preguntas \u2500\u2500 *\/\n.pregunta{border:1px solid var(--slate-200); border-radius:1rem; padding:1.5rem; margin-bottom:1.5rem; background:var(--blanco);\n  transition:border-color .2s, box-shadow .2s}\n.pregunta.respondida{border-color:#e2ddf9; box-shadow:0 8px 20px -12px rgba(79,70,229,.45)}\n.pregunta-cabecera{display:flex; flex-wrap:wrap; gap:.75rem; align-items:center; justify-content:space-between; margin-bottom:.75rem}\n.pregunta-numero{display:flex; align-items:center; justify-content:center; width:2.25rem; height:2.25rem; border-radius:.75rem;\n  background-image:linear-gradient(to right,var(--indigo),var(--indigo-claro)); color:#fff; font-weight:800; flex:0 0 auto}\n.pregunta-titulo{display:flex; gap:.85rem; align-items:flex-start; flex:1 1 260px}\n.pregunta-titulo h3{margin:0}\n.dilema{font-weight:600; color:var(--slate-900); margin:.25rem 0 1rem}\n.realidad{background:#fff7ed; border-left:4px solid #fb923c; border-radius:.5rem; padding:.85rem 1rem; margin-bottom:1.25rem; font-size:.9rem; color:#7c2d12}\n.realidad strong{color:#9a3412}\n.opciones{display:grid; gap:.6rem}\n.opcion{display:flex; gap:.75rem; align-items:flex-start; border:2px solid var(--slate-200); border-radius:.75rem;\n  padding:.85rem 1rem; cursor:pointer; transition:all .2s ease-in-out; background:var(--blanco); text-align:left; font:inherit; color:inherit; width:100%}\n.opcion:hover{border-color:#e2ddf9; transform:translateY(-2px)}\n.opcion .nivel{flex:0 0 auto; width:1.75rem; height:1.75rem; border-radius:.5rem; background:#f1f5f9; color:var(--slate-500);\n  display:flex; align-items:center; justify-content:center; font-weight:800; font-size:.85rem}\n.opcion .texto{font-size:.925rem}\n.opcion[aria-pressed=\"true\"]{background:var(--indigo-suave); border-color:var(--indigo); color:var(--indigo-oscuro); font-weight:600}\n.opcion[aria-pressed=\"true\"] .nivel{background:var(--indigo); color:#fff}\n.opcion:focus-visible{outline:3px solid rgba(99,102,241,.4); outline-offset:2px}\n.consejo{background:var(--indigo-suave); border-radius:.75rem; padding:1rem 1.25rem; margin-top:1rem; font-size:.9rem}\n.consejo strong{color:var(--indigo-oscuro)}\n.primer-paso{background:#ecfdf5; border-left:4px solid var(--esmeralda); border-radius:.5rem; padding:.75rem 1rem; margin-top:.75rem; font-size:.9rem; color:#065f46}\n\n\/* \u2500\u2500 botones \u2500\u2500 *\/\n.btn{font-weight:700; padding:1rem 2rem; border-radius:.75rem; transition:all .2s; border:none; cursor:pointer;\n  box-shadow:var(--sombra-suave); display:inline-flex; align-items:center; justify-content:center; gap:.6rem; font-family:inherit; font-size:1rem}\n.btn:disabled{opacity:.7; cursor:not-allowed}\n.btn-primario{background-image:linear-gradient(to right,var(--indigo),var(--indigo-claro)); color:#fff}\n.btn-primario:hover:not(:disabled){transform:translateY(-2px); box-shadow:0 10px 20px -5px rgba(99,102,241,.4)}\n.btn-secundario{background-image:linear-gradient(to right,var(--esmeralda),var(--esmeralda-claro)); color:#fff}\n.btn-secundario:hover:not(:disabled){transform:translateY(-2px); box-shadow:0 10px 20px -5px rgba(16,185,129,.4)}\n.btn-neutro{background:var(--blanco); color:var(--slate-700); border:1px solid var(--slate-200)}\n.btn-neutro:hover:not(:disabled){border-color:#e2ddf9; color:var(--indigo-oscuro); transform:translateY(-2px)}\n.btn-bloque{width:100%}\n.acciones{display:flex; flex-wrap:wrap; gap:.75rem; margin-top:1.5rem}\n.acciones .btn{flex:1 1 200px}\n.spinner{border:3px solid rgba(255,255,255,.3); width:20px; height:20px; border-radius:50%; border-left-color:#fff; animation:girar 1s linear infinite}\n@keyframes girar{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}\n\n\/* \u2500\u2500 resultados \u2500\u2500 *\/\n.rejilla{display:grid; gap:1.25rem}\n@media(min-width:760px){.rejilla-2{grid-template-columns:1fr 1fr}.rejilla-4{grid-template-columns:repeat(4,1fr)}}\n.dimension{border:1px solid var(--slate-200); border-radius:.85rem; padding:1rem; background:var(--blanco)}\n.dimension .encabezado{display:flex; justify-content:space-between; align-items:baseline; gap:.5rem; margin-bottom:.35rem}\n.dimension .nombre{font-weight:700; font-size:.9rem; color:var(--slate-900)}\n.dimension .valor{font-weight:800; color:var(--slate-900)}\n.fortaleza,.alerta{border-radius:.75rem; padding:.9rem 1rem; font-size:.9rem; margin-bottom:.6rem}\n.fortaleza{background:#ecfdf5; border-left:4px solid var(--esmeralda); color:#065f46}\n.alerta{background:#fff1f2; border-left:4px solid var(--rojo); color:#9f1239}\n.prioridad{display:flex; gap:.85rem; align-items:flex-start; padding:.85rem 0; border-bottom:1px dashed var(--slate-200)}\n.prioridad:last-child{border-bottom:none}\n.prioridad .orden{flex:0 0 auto; width:1.9rem; height:1.9rem; border-radius:.6rem; background-image:linear-gradient(to right,var(--indigo),var(--indigo-claro));\n  color:#fff; font-weight:800; display:flex; align-items:center; justify-content:center; font-size:.85rem}\n.lista{list-style:none; padding:0; margin:0}\n.lista li{position:relative; padding-left:1.6rem; margin-bottom:.6rem}\n.lista li:before{content:'\u25b8'; position:absolute; left:.35rem; color:var(--indigo); font-weight:800}\n.pasos{list-style:none; padding:0; margin:0}\n.pasos li{display:flex; gap:.85rem; margin-bottom:.85rem}\n.pasos .cuando{flex:0 0 auto; font-weight:800; color:var(--indigo-oscuro); background:var(--indigo-suave); border-radius:.5rem; padding:.15rem .6rem; font-size:.8rem; height:fit-content}\n.tarjeta-modulo{border:1px solid var(--slate-200); border-radius:1rem; padding:1.5rem; background:var(--blanco); margin-bottom:1.25rem}\n.numero-modulo{display:inline-flex; align-items:center; justify-content:center; width:2.5rem; height:2.5rem; border-radius:.85rem;\n  background-image:linear-gradient(to right,var(--esmeralda),var(--esmeralda-claro)); color:#fff; font-weight:900; font-size:1.1rem; margin-bottom:.75rem}\n.tarea{display:flex; gap:.75rem; align-items:flex-start; padding:.6rem .75rem; border:1px solid var(--slate-200); border-radius:.6rem; margin-bottom:.5rem; cursor:pointer; transition:all .2s}\n.tarea:hover{border-color:#a7f3d0; background:#f0fdf4}\n.tarea input{margin-top:.3rem; accent-color:var(--esmeralda); width:1.1rem; height:1.1rem}\n.tarea.hecha{opacity:.65; text-decoration:line-through}\n.kpi{display:flex; justify-content:space-between; gap:1rem; padding:.6rem 0; border-bottom:1px dashed var(--slate-200); font-size:.9rem}\n.kpi:last-child{border-bottom:none}\n.nota{font-size:.85rem; color:var(--slate-500); background:#f9f8ff; border:1px dashed var(--slate-300); border-radius:.75rem; padding:.85rem 1rem}\n.aviso{background:#fffbeb; border-left:4px solid #f59e0b; border-radius:.5rem; padding:.85rem 1rem; font-size:.9rem; color:#78350f; margin-bottom:1rem}\n.aviso.ok{background:#ecfdf5; border-left-color:var(--esmeralda); color:#065f46}\n\n\/* \u2500\u2500 aviso flotante (toast) \u2500\u2500 *\/\n.brindis{position:fixed; left:50%; bottom:1.5rem; transform:translateX(-50%) translateY(150%);\n  background:var(--slate-900); color:#fff; padding:.85rem 1.4rem; border-radius:.75rem; font-weight:600; font-size:.9rem;\n  box-shadow:0 12px 30px rgba(0,0,0,.35); transition:transform .35s ease; z-index:9999; max-width:90vw}\n.brindis.visible{transform:translateX(-50%) translateY(0)}\n\n\/* \u2500\u2500 impresi\u00f3n \/ PDF \u2500\u2500 *\/\n@media print{\n  .vh{background:#fff}\n  .pestanas,.acciones,.no-imprimir{display:none !important}\n  .blanco,.post-it,.pregunta,.tarjeta-modulo{box-shadow:none !important; border:1px solid #e2ddf9; transform:none !important; page-break-inside:avoid}\n  .vh-contenedor{max-width:100%; padding:0}\n  a[href]:after{content:''}\n}\n@media (prefers-reduced-motion:reduce){*{animation:none !important; transition:none !important}}\n\n\/* \u2500\u2500 anti-desborde \u2500\u2500 *\/\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   ANTI-DESBORDE \u2014 texto que no cabe dentro de su cuadro\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   POR QU\u00c9 EXISTE (medido el 2026-10-10, reportado por Carla): en la ficha del Buyer\n   Persona las etiquetas del perfil llevan `w-24` (ancho fijo de 96 px) y textos como\n   \u00abCanales de Contacto Preferidos:\u00bb miden m\u00e1s del doble: se sal\u00edan del cuadro y se\n   montaban encima del valor. En m\u00f3vil, adem\u00e1s, la lista no pod\u00eda partirse en dos\n   l\u00edneas porque el <li> era `flex` sin `wrap`.\n\n   Las cuatro reglas que resuelven el 90% de estos casos:\n     1. `min-width: 0` en los hijos de flex y grid: sin esto, un hijo nunca se encoge\n        por debajo del tama\u00f1o de su contenido (el desborde cl\u00e1sico de flexbox).\n     2. `flex-wrap: wrap` para que el valor baje a la l\u00ednea siguiente.\n     3. `overflow-wrap: anywhere` para palabras largu\u00edsimas (correos, URLs, nombres).\n     4. Anchos fijos fuera: `width: auto` con `min-width`, en lugar de un ancho cerrado.\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n\/* 1 \u00b7 los hijos de flex y grid pueden encogerse *\/\n.rejilla > *, .fila-campos > *, .grid > *, .flex > * { min-width: 0; }\n.rejilla, .fila-campos { grid-auto-columns: minmax(0, 1fr); }\n\n\/* 2 \u00b7 el texto largo se parte en vez de salirse *\/\n.aemp, .vh, .aemp p, .vh p, .aemp li, .vh li, .aemp td, .vh td,\n.aemp .dato, .vh .dato, .aemp .titulo, .vh .titulo {\n  overflow-wrap: anywhere;\n  word-break: normal;\n}\n\n\/* 3 \u00b7 etiquetas y valores que se acomodan solos (fichas de datos) *\/\n.pareja { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .15rem .45rem; }\n.pareja .rotulo { flex: 0 1 auto; min-width: 5.5rem; font-weight: 700; }\n.pareja .valor { flex: 1 1 8rem; min-width: 0; }\n\n\/* 4 \u00b7 t\u00edtulos con espacio para las letras que bajan (g, j, p, y) *\/\n.aemp h1, .vh h1, .aemp h2, .vh h2, .aemp h3, .vh h3 { line-height: 1.25; padding-bottom: .1em; }\n\n\/* 5 \u00b7 pastillas y botones: nunca cortan su texto *\/\n.pastilla, .btn, .pestana { overflow-wrap: anywhere; }\n.btn { white-space: normal; }\n\n\/* 6 \u00b7 tablas anchas: se desplazan en horizontal, no se salen de la pantalla *\/\n.tabla-contenedor { overflow-x: auto; -webkit-overflow-scrolling: touch; }\n\n\/* 7 \u00b7 en pantallas peque\u00f1as, menos relleno y todo a una columna *\/\n@media (max-width: 640px) {\n  .blanco { padding: 1.25rem; }\n  .post-it { padding: 1.15rem; }\n  .acciones .btn, .acciones-resultado .btn { flex: 1 1 100%; }\n  .metric .dato, .metrica .dato { font-size: 1.35rem; }\n}\n\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   8 \u00b7 BOTONES: el tema del sitio les pone altura fija\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   MEDIDO el 2026-10-10 (la causa del \u00abtexto cortado por la mitad\u00bb que report\u00f3 Carla):\n   el tema ewebot trae en su hoja de estilos\n\n       button, input[type=\"submit\"] { height: 50px; }\n\n   Con eso, cada bot\u00f3n de nuestras herramientas quedaba clavado en 50 px de alto.\n   Las opciones del test \u2014que llevan una frase entera\u2014 necesitaban entre 85 y 132 px,\n   as\u00ed que se ve\u00edan cortadas a la mitad. Lo mismo val\u00eda para cualquier bot\u00f3n con dos\n   l\u00edneas de texto.\n\n   Estas reglas devuelven la altura autom\u00e1tica a TODO lo que sea nuestro, sin tocar el\n   tema ni los botones del resto del sitio.\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n.aemp button, .aemp .btn, .aemp .opcion, .aemp .pestana, .aemp .tarea,\n.vh button, .vh .btn, .vh .opcion, .vh .pestana, .vh .tarea {\n  height: auto !important;\n  min-height: 0;\n  max-height: none;\n  overflow: visible;\n}\n\/* El tema tambi\u00e9n pone los botones en MAY\u00daSCULAS: aqu\u00ed manda la tipograf\u00eda de la\n   herramienta, que es la misma del Generador de Buyer Persona. *\/\n.aemp button, .aemp .btn, .aemp .opcion, .aemp .pestana,\n.vh button, .vh .btn, .vh .opcion, .vh .pestana { text-transform: none; }\n\/* Y los botones no parten su texto en dos l\u00edneas raras: se acomodan y crecen. *\/\n.aemp .btn, .vh .btn { white-space: normal; }\n\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   9 \u00b7 CAMPOS Y BOTONES: el tema tambi\u00e9n les pisa el relleno y el ancho\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   MEDIDO el 2026-10-10 (reportado por Carla): en la hoja del tema hay reglas como\n\n       input[type=\"text\"], select { height: 41px; padding: 8px 0; }\n\n   que ganan por especificidad a nuestras clases. Resultado: los campos perd\u00edan el\n   relleno lateral \u2014el texto quedaba pegado al borde, como si se saliera de la caja\u2014 y\n   la altura se fijaba en 41 px aunque el contenido pidiera m\u00e1s.\n\n   Y en las filas de botones, cada bot\u00f3n se estiraba a un ancho fijo y el texto se\n   apretaba dentro (en la calculadora, \u00abCopiar enlace con mis n\u00fameros\u00bb ocupaba todo el\n   bot\u00f3n). Ahora cada bot\u00f3n toma el ancho que su texto necesita y, si no cabe, baja a la\n   l\u00ednea siguiente.\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n\/* Campos: altura autom\u00e1tica, relleno de verdad y nada de recortes. *\/\n.aemp .form-input, .aemp .form-select, .aemp .form-textarea, .aemp input[type=\"text\"],\n.vh .form-input, .vh .form-select, .vh .form-textarea, .vh input[type=\"text\"], .vh input[type=\"number\"] {\n  height: auto !important;\n  min-height: 3rem !important;\n  max-height: none !important;\n  padding: .8rem 1rem !important;\n  line-height: 1.45 !important;\n  box-sizing: border-box !important;\n  overflow: visible !important;\n}\/* Los desplegables necesitan adem\u00e1s que el texto no se corte por abajo. *\/\n.aemp select, .vh select { text-overflow: ellipsis; overflow: visible !important; }\n.aemp textarea, .vh textarea { min-height: 4.5rem !important; }\n\n\/* Filas de botones: el ancho lo pone el texto, no el dise\u00f1o. *\/\n.acciones, .acciones-superiores { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; }\n.acciones > *, .acciones-superiores > * { min-width: 0; }\n.acciones .btn, .acciones-superiores .btn {\n  flex: 0 1 auto;            \/* el bot\u00f3n crece con su texto y nunca se aprieta *\/\n  width: auto;\n  max-width: 100%;\n  padding: .9rem 1.35rem;\n  white-space: normal;\n  overflow-wrap: anywhere;\n  text-align: center;\n}\n@media (max-width: 640px) {\n  .acciones .btn, .acciones-superiores .btn { flex: 1 1 100%; }\n}\n\n\/* \u2500\u2500 paleta pastel y color por funci\u00f3n \u2500\u2500 *\/\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   PALETA PASTEL Y COLOR POR FUNCI\u00d3N \u00b7 Herramientas de Vela Producciones\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Pedido de Carla (2026-10-10): \u00abasignar colores espec\u00edficos a todos los botones y\n   tarjetas de cada herramienta, asegurando coherencia visual entre ellas\u2026 y aplicar\n   sombras tanto a las tarjetas como a los botones para aportar profundidad\u00bb.\n   Referencia de color: las tarjetas (post-it) del Generador de Buyer Persona, que ya\n   usaban esta paleta suave:\n       amarillo #fef9c3 \u00b7 rosa #fce7f3 \u00b7 azul #dbeafe \u00b7 verde #dcfce7 \u00b7 lila #e2ddf9\n   (m\u00e1s el lila clar\u00edsimo #f4f2ff que la ficha ya usaba en la cita y el avatar).\n\n   ESTE ARCHIVO ES LA \u00daNICA FUENTE DE LA PALETA. Se inyecta, tal cual, en las cinco\n   herramientas:\n     \u00b7 las tres nuevas (Calculadora, Validador, Plan de contenido) \u2014 v\u00eda `generar.py`,\n       que ya pega `diseno.css` + `anti-desborde.css`;\n     \u00b7 \u00abArquitectura del Emprendedor\u00bb \u2014 v\u00eda `generar-snippet.py`;\n     \u00b7 el Generador de Buyer Persona \u2014 v\u00eda `parche-buyer-persona.py`.\n   Cambiar un color aqu\u00ed lo cambia en las cinco. Nada de copias.\n\n   \u2500\u2500 REGLA DE COLOR DE LOS BOTONES (una funci\u00f3n = un color) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     \u00edndigo   .btn-primario    producir el resultado: Generar, Calcular, Analizar, Armar plan\n     esmeralda .btn-secundario  sacar el documento: Imprimir, Descargar \/ Guardar en PDF\n     rosa     .btn-reiniciar    empezar de nuevo: Reiniciar, Borrar, Crear otro perfil\n     amarillo .btn-ejemplo      ver un ejemplo \/ cargar datos de muestra\n     azul     .btn-copiar       copiar al portapapeles (resumen, enlace, tabla)\n     lila     .btn-neutro       todo lo dem\u00e1s (volver, cerrar, ayuda, seg\u00fan)\n\n   \u2500\u2500 REGLA DE COLOR DE LAS TARJETAS (un significado = un color) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n     lila     .tono-lila        el resultado: lo que la persona se lleva\n     azul     .tono-azul        n\u00fameros, c\u00e1lculos, datos duros\n     verde    .tono-verde       lo que est\u00e1 bien, lo validado, el plan a seguir\n     amarillo .tono-amarillo    aviso, riesgo, cuidado, lo que hay que vigilar\n     rosa     .tono-rosa        pasos, proceso, personas\n     \u00edndigo   .tono-indigo      dato de entrada, nota neutral\n\n   Las sombras van en dos escalas (reposo y elevada) para que todo tenga la misma\n   profundidad: `--sombra-tarjeta` \/ `--sombra-tarjeta-alto` y `--sombra-boton` \/\n   `--sombra-boton-alto`.\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n\n:root{\n  \/* \u2500\u2500 paleta pastel (referencia: las tarjetas del Buyer Persona) \u2500\u2500 *\/\n  --p-lila:#e2ddf9;      --p-lila-borde:#ddd6fe;      --p-lila-texto:#5b21b6;\n  --p-azul:#dbeafe;      --p-azul-borde:#bfdbfe;      --p-azul-texto:#1e40af;\n  --p-verde:#dcfce7;     --p-verde-borde:#bbf7d0;     --p-verde-texto:#166534;\n  --p-amarillo:#fef9c3;  --p-amarillo-borde:#fde68a;  --p-amarillo-texto:#854d0e;\n  --p-rosa:#fce7f3;      --p-rosa-borde:#fbcfe8;      --p-rosa-texto:#9d174d;\n  --p-indigo:#f4f2ff;    --p-indigo-borde:#e2ddf9;    --p-indigo-texto:#3730a3;\n\n  \/* \u2500\u2500 sombras: la misma profundidad en todas las herramientas \u2500\u2500 *\/\n  --sombra-tarjeta:0 12px 28px -14px rgba(15,23,42,.30), 0 2px 6px -2px rgba(15,23,42,.06);\n  --sombra-tarjeta-alto:0 22px 40px -18px rgba(15,23,42,.34), 0 3px 8px -2px rgba(15,23,42,.07);\n  --sombra-post-it:10px 10px 25px rgba(0,0,0,.10);\n  --sombra-post-it-alto:14px 14px 30px rgba(0,0,0,.14);\n  --sombra-boton:0 4px 12px -2px rgba(15,23,42,.18);\n  --sombra-boton-alto:0 12px 22px -8px rgba(15,23,42,.34);\n}\n\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 TARJETAS: una sola profundidad \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   Todas las tarjetas de las cinco herramientas comparten radio y sombra. Los post-it del\n   Buyer Persona conservan su sombra desplazada y su inclinaci\u00f3n: es su se\u00f1o de identidad. *\/\n.blanco,.tarjeta-modulo,.pregunta,.dimension,.metrica,.consejo,.nota,.aviso,.realidad,\n.pasos-vacio,.resultado-caja,\n\/* las tarjetas de la ficha del Buyer Persona: misma profundidad que las dem\u00e1s *\/\n.whiteboard,.infographic-section,.strategy-item,.infographic-quote{\n  box-shadow:var(--sombra-tarjeta);\n  transition:transform .25s ease, box-shadow .25s ease;\n}\n.blanco:hover,.tarjeta-modulo:hover,.dimension:hover,.metrica:hover{\n  box-shadow:var(--sombra-tarjeta-alto);\n  transform:translateY(-2px);\n}\n.post-it{box-shadow:var(--sombra-post-it)}\n.post-it:hover{box-shadow:var(--sombra-post-it-alto)}\n\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 TONOS PASTEL DE TARJETA \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   Se pone la clase en la tarjeta (`.blanco.tono-azul`) y el color viene de aqu\u00ed. *\/\n.tono-lila{background:var(--p-lila); border:1px solid var(--p-lila-borde)}\n.tono-azul{background:var(--p-azul); border:1px solid var(--p-azul-borde)}\n.tono-verde{background:var(--p-verde); border:1px solid var(--p-verde-borde)}\n.tono-amarillo{background:var(--p-amarillo); border:1px solid var(--p-amarillo-borde)}\n.tono-rosa{background:var(--p-rosa); border:1px solid var(--p-rosa-borde)}\n.tono-indigo{background:var(--p-indigo); border:1px solid var(--p-indigo-borde)}\n\n\/* El texto de una tarjeta pastel pide m\u00e1s contraste que el gris pizarra normal. *\/\n.tono-lila h2,.tono-lila h3,.tono-lila h4,.tono-lila .rotulo,.tono-lila .nombre{color:var(--p-lila-texto)}\n.tono-azul h2,.tono-azul h3,.tono-azul h4,.tono-azul .rotulo,.tono-azul .nombre{color:var(--p-azul-texto)}\n.tono-verde h2,.tono-verde h3,.tono-verde h4,.tono-verde .rotulo,.tono-verde .nombre{color:var(--p-verde-texto)}\n.tono-amarillo h2,.tono-amarillo h3,.tono-amarillo h4,.tono-amarillo .rotulo,.tono-amarillo .nombre{color:var(--p-amarillo-texto)}\n.tono-rosa h2,.tono-rosa h3,.tono-rosa h4,.tono-rosa .rotulo,.tono-rosa .nombre{color:var(--p-rosa-texto)}\n.tono-indigo h2,.tono-indigo h3,.tono-indigo h4,.tono-indigo .rotulo,.tono-indigo .nombre{color:var(--p-indigo-texto)}\n.tono-lila .gris,.tono-azul .gris,.tono-verde .gris,.tono-amarillo .gris,.tono-rosa .gris,\n.tono-indigo .gris{color:#475569}\n\n\/* Los recuadros de dentro de una tarjeta pastel se quedan claros para que se distingan. *\/\n.tono-lila .consejo,.tono-azul .consejo,.tono-verde .consejo,.tono-amarillo .consejo,\n.tono-rosa .consejo,.tono-indigo .consejo{background:rgba(255,255,255,.65)}\n.tono-lila .nota,.tono-azul .nota,.tono-verde .nota,.tono-amarillo .nota,\n.tono-rosa .nota,.tono-indigo .nota{background:rgba(255,255,255,.65)}\n\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 BOTONES: un color por funci\u00f3n, con sombra \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n.btn{box-shadow:var(--sombra-boton)}\n\/* El relleno se declara DOS veces a prop\u00f3sito: el tema del sitio pinta los <button> con un gris\n   (#efefef) y, si el degradado tardara en pintarse, se ver\u00eda el gris por debajo. Con\n   `background-color` del mismo tono, el bot\u00f3n nunca aparece gris. *\/\n.btn-primario{background-color:#6254e7; background-image:linear-gradient(to right,#6254e7,#9289f1); color:#fff}\n.btn-primario:hover:not(:disabled){transform:translateY(-2px);\n  box-shadow:0 14px 26px -10px rgba(99,102,241,.65)}\n.btn-secundario{background-color:#10b981; background-image:linear-gradient(to right,#10b981,#34d399); color:#fff}\n.btn-secundario:hover:not(:disabled){transform:translateY(-2px);\n  box-shadow:0 14px 26px -10px rgba(16,185,129,.65)}\n.btn-reiniciar{background:var(--p-rosa); border:1px solid var(--p-rosa-borde); color:var(--p-rosa-texto);\n  box-shadow:0 8px 18px -8px rgba(236,72,153,.55)}\n.btn-reiniciar:hover:not(:disabled){transform:translateY(-2px); border-color:#f9a8d4;\n  box-shadow:0 14px 26px -10px rgba(236,72,153,.6)}\n.btn-ejemplo{background:var(--p-amarillo); border:1px solid var(--p-amarillo-borde); color:var(--p-amarillo-texto);\n  box-shadow:0 8px 18px -8px rgba(245,158,11,.55)}\n.btn-ejemplo:hover:not(:disabled){transform:translateY(-2px); border-color:#fcd34d;\n  box-shadow:0 14px 26px -10px rgba(245,158,11,.6)}\n.btn-copiar{background:var(--p-azul); border:1px solid var(--p-azul-borde); color:var(--p-azul-texto);\n  box-shadow:0 8px 18px -8px rgba(59,130,246,.55)}\n.btn-copiar:hover:not(:disabled){transform:translateY(-2px); border-color:#93c5fd;\n  box-shadow:0 14px 26px -10px rgba(59,130,246,.6)}\n.btn-neutro{background:var(--p-indigo); border:1px solid var(--p-indigo-borde); color:var(--p-indigo-texto);\n  box-shadow:0 8px 18px -8px rgba(99,102,241,.45)}\n.btn-neutro:hover:not(:disabled){transform:translateY(-2px); border-color:#a5b4fc; color:#312e81;\n  box-shadow:0 14px 26px -10px rgba(99,102,241,.5)}\n\n\/* Al pulsar, el bot\u00f3n se hunde: da sensaci\u00f3n de que respondi\u00f3. *\/\n.btn:active:not(:disabled){transform:translateY(0); box-shadow:var(--sombra-boton)}\n\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 PESTA\u00d1AS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   La pesta\u00f1a activa va en \u00edndigo (es la que produce), las dem\u00e1s en blanco con sombra. *\/\n.pestana{box-shadow:var(--sombra-boton)}\n.pestana.activa{box-shadow:0 10px 20px -8px rgba(99,102,241,.6)}\n\n\/* En impresi\u00f3n, nada de sombras ni elevaciones: el papel no las tiene. *\/\n@media print{\n  .blanco,.tarjeta-modulo,.pregunta,.dimension,.metrica,.consejo,.nota,.aviso,.post-it,.pestana,.btn{\n    box-shadow:none !important; transform:none !important;\n  }\n}\n@media (prefers-reduced-motion:reduce){\n  .blanco,.tarjeta-modulo,.dimension,.metrica,.post-it,.btn,.pestana{transition:none !important}\n}\n\n\/* \u2500\u2500 CSS propio de esta herramienta \u2500\u2500 *\/\n\/* \u2500\u2500 Piezas propias de la calculadora de precios \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n\n.fila-campos{display:grid; gap:1rem}\n@media(min-width:760px){\n  .fila-campos.dos{grid-template-columns:1fr 1fr}\n  .fila-campos.tres{grid-template-columns:repeat(3,1fr)}\n}\n\n\/* tarjetas de resultado\n   Cada estado lleva su tono pastel (Carla, 2026-10-10): verde = vas bien \u00b7 amarillo = ojo \u00b7\n   rosa = hay que corregir \u00b7 lila = el dato que m\u00e1s importa. La franja de la izquierda mantiene\n   el color fuerte para que el estado se lea de un golpe. *\/\n.metrica{background:#fff; border:1px solid var(--slate-200); border-radius:.85rem; padding:1rem;\n  border-left:4px solid var(--slate-300)}\n.metrica .rotulo{font-size:.72rem; text-transform:uppercase; letter-spacing:.05em; color:var(--slate-500); font-weight:800}\n.metrica .dato{font-size:1.55rem; font-weight:900; color:var(--slate-900); line-height:1.2; margin:.2rem 0}\n.metrica .pista{font-size:.8rem; color:var(--slate-500)}\n.metrica.ok{background:var(--p-verde); border-color:var(--p-verde-borde); border-left-color:var(--esmeralda)}\n.metrica.ojo{background:var(--p-amarillo); border-color:var(--p-amarillo-borde); border-left-color:var(--ambar)}\n.metrica.mal{background:var(--p-rosa); border-color:var(--p-rosa-borde); border-left-color:var(--rojo)}\n.metrica.destacada{background:var(--p-lila); border-color:var(--p-lila-borde); border-left-color:var(--indigo)}\n\n\/* tabla de escenarios *\/\n.tabla{width:100%; border-collapse:collapse; font-size:.88rem}\n\/* Solo la tabla de escenarios necesita ancho m\u00ednimo: tiene cinco columnas.\n   La de \u00abcuenta paso a paso\u00bb tiene dos y debe caber en un tel\u00e9fono. *\/\n.tabla.escenarios{min-width:540px}\n\/* El contenedor con scroll horizontal: la tabla se desliza, no se sale de la pantalla. *\/\n.tabla-contenedor{overflow-x:auto; -webkit-overflow-scrolling:touch; margin:0 -0.25rem; padding:0 .25rem}\n@media (max-width:640px){\n  .tabla{font-size:.82rem}\n  .tabla th,.tabla td{padding:.5rem .35rem}\n  .tabla td.num{white-space:normal}\n}\n.tabla th,.tabla td{padding:.6rem .5rem; border-bottom:1px solid var(--slate-200); text-align:left}\n.tabla th{font-size:.72rem; text-transform:uppercase; letter-spacing:.04em; color:var(--slate-500); font-weight:800}\n.tabla td.num{text-align:right; font-weight:700; color:var(--slate-900); white-space:nowrap}\n.tabla tr.fila-base td{background:#f9f8ff}\n.tabla tr.fila-base td:first-child{font-weight:700}\n.tabla td .mejora{color:#047857; font-weight:700}\n.tabla td .empeora{color:#b91c1c; font-weight:700}\n\n\/* barra de comparaci\u00f3n *\/\n.comparacion{margin-top:1rem}\n.comparacion .linea{display:flex; align-items:center; gap:.75rem; margin-bottom:.5rem; font-size:.85rem}\n.comparacion .nombre{flex:0 0 150px; color:var(--slate-700)}\n.comparacion .valor{font-weight:800; color:var(--slate-900); white-space:nowrap}\n<\/style>\n<div class=\"vh\">\n<div class=\"vh-contenedor\">\n<!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 CABECERA \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n  <div class=\"blanco\">\n    <span class=\"etiqueta\">Herramienta gratuita \u00b7 Vela Producciones<\/span>\n    <h1>\u00bfCu\u00e1nto debo cobrar?<\/h1>\n    <p class=\"gris\" style=\"margin:.25rem 0 1rem\">Calculadora de precios y punto de equilibrio.\n      Te dice si tu precio te deja ganancia, cu\u00e1nto necesitas vender para no perder y qu\u00e9 pasa si cambias\n      un n\u00famero. <strong>Sin registros y sin enviar nada<\/strong>: todo se calcula en tu navegador.<\/p>\n\n    <div class=\"pestanas no-imprimir\" role=\"tablist\" style=\"margin-bottom:0\">\n      <button class=\"pestana activa\" role=\"tab\" aria-selected=\"true\" data-panel=\"panel-producto\">\n        <span class=\"num\">1<\/span>Vendo productos<\/button>\n      <button class=\"pestana\" role=\"tab\" aria-selected=\"false\" data-panel=\"panel-hora\">\n        <span class=\"num\">2<\/span>Vendo mi tiempo o mis servicios<\/button>\n    <\/div>\n  <\/div>\n\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 MODO 1: PRODUCTOS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n  <section id=\"panel-producto\" role=\"tabpanel\">\n    <div class=\"blanco tono-indigo\">\n      <h2>Tus n\u00fameros del mes<\/h2>\n      <p class=\"gris chico\">Escribe cantidades sin s\u00edmbolos: <strong>1500<\/strong> o <strong>1500.50<\/strong>.\n        Si un campo no aplica, d\u00e9jalo en cero.<\/p>\n\n      <div class=\"fila-campos dos\">\n        <div>\n          <label class=\"form-label\" for=\"p-fijos\">1 \u00b7 Costos fijos del mes (Q)<\/label>\n          <input class=\"form-input\" id=\"p-fijos\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Lo que pagas aunque no vendas nada: renta, sueldos, luz, internet, contador.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"p-variable\">2 \u00b7 Costo de una unidad (Q)<\/label>\n          <input class=\"form-input\" id=\"p-variable\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Lo que te cuesta hacer o comprar <em>una<\/em> unidad: material, empaque, env\u00edo.<\/p>\n        <\/div>\n      <\/div>\n\n      <div class=\"fila-campos dos\" style=\"margin-top:1rem\">\n        <div>\n          <label class=\"form-label\" for=\"p-precio\">3 \u00b7 Precio al que vendes hoy (Q)<\/label>\n          <input class=\"form-input\" id=\"p-precio\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Lo que paga el cliente por unidad, antes de comisiones e impuestos.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"p-unidades\">4 \u00b7 Unidades que vendes al mes<\/label>\n          <input class=\"form-input\" id=\"p-unidades\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Un promedio normal, no el mejor mes.<\/p>\n        <\/div>\n      <\/div>\n\n      <div class=\"fila-campos tres\" style=\"margin-top:1rem\">\n        <div>\n          <label class=\"form-label\" for=\"p-comision\">5 \u00b7 Comisi\u00f3n que pagas (%)<\/label>\n          <input class=\"form-input\" id=\"p-comision\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Tarjeta, plataforma de pago, vendedor, marketplaces.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"p-impuesto\">6 \u00b7 Impuestos sobre la venta (%)<\/label>\n          <input class=\"form-input\" id=\"p-impuesto\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"12\">\n          <p class=\"micro gris\">En Guatemala el IVA es 12%. Si ya lo tienes incluido en el precio, escr\u00edbelo aqu\u00ed.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"p-margen\">7 \u00b7 Margen que quieres ganar (%)<\/label>\n          <input class=\"form-input\" id=\"p-margen\" type=\"text\" inputmode=\"decimal\" placeholder=\"40\" value=\"40\">\n          <p class=\"micro gris\">Sobre el costo de la unidad. Un 40-60% es lo normal en producto propio.<\/p>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <div id=\"p-veredicto\"><\/div>\n\n    <div class=\"blanco tono-lila\">\n      <h2>Lo que dicen tus n\u00fameros<\/h2>\n      <div class=\"rejilla rejilla-4\" id=\"p-tarjetas\"><\/div>\n      <div id=\"p-desglose\" style=\"margin-top:1.5rem\"><\/div>\n    <\/div>\n\n    <div class=\"blanco tono-azul\">\n      <h2>Qu\u00e9 pasa si cambio algo<\/h2>\n      <p class=\"gris chico\">El mismo negocio con un cambio peque\u00f1o. Este cuadro es donde suele estar el\n        dinero que no ves.<\/p>\n      <div class=\"tabla-contenedor\"><table class=\"tabla escenarios\" id=\"p-escenarios\"><\/table><\/div>\n    <\/div>\n\n    <div class=\"blanco tono-verde\">\n      <h2>C\u00f3mo leer esto<\/h2>\n      <ul class=\"lista chico\">\n        <li><strong>Precio m\u00ednimo:<\/strong> el precio m\u00e1s bajo al que puedes vender sin perder dinero. Por\n          debajo de ah\u00ed, cada venta te cuesta.<\/li>\n        <li><strong>Precio recomendado:<\/strong> el que te deja el margen que pediste. Es tu meta, no una\n          obligaci\u00f3n: si el mercado no lo aguanta, el problema suele estar en el costo o en la propuesta,\n          no en el margen.<\/li>\n        <li><strong>Punto de equilibrio:<\/strong> cu\u00e1ntas unidades al mes cubren tus costos fijos. Antes de\n          esa unidad no ganas: apenas empiezas.<\/li>\n        <li><strong>Costos fijos:<\/strong> si tu punto de equilibrio te asusta, mira primero los fijos. Bajar\n          un fijo vale m\u00e1s que bajar diez costos peque\u00f1os.<\/li>\n      <\/ul>\n    <\/div>\n  <\/section>\n\n  <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 MODO 2: HORAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n  <section id=\"panel-hora\" role=\"tabpanel\" class=\"oculto\">\n    <div class=\"blanco tono-indigo\">\n      <h2>Tu mes, en horas<\/h2>\n      <p class=\"gris chico\">Para quien cobra por hora o por proyecto: consultores, dise\u00f1adores, fot\u00f3grafos,\n        desarrolladores, entrenadores, contadores.<\/p>\n\n      <div class=\"fila-campos dos\">\n        <div>\n          <label class=\"form-label\" for=\"h-fijos\">1 \u00b7 Costos fijos del mes (Q)<\/label>\n          <input class=\"form-input\" id=\"h-fijos\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Oficina, internet, software, publicidad, contador, seguro.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"h-sueldo\">2 \u00b7 Cu\u00e1nto quieres ganarte al mes (Q)<\/label>\n          <input class=\"form-input\" id=\"h-sueldo\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Tu sueldo, no la ganancia del negocio. Cu\u00e9ntalo como un costo m\u00e1s.<\/p>\n        <\/div>\n      <\/div>\n\n      <div class=\"fila-campos dos\" style=\"margin-top:1rem\">\n        <div>\n          <label class=\"form-label\" for=\"h-horas\">3 \u00b7 Horas que facturas al mes<\/label>\n          <input class=\"form-input\" id=\"h-horas\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">De 40 horas semanales casi nadie factura 160. Cuenta las que de verdad cobras.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"h-tarifa\">4 \u00b7 Tu tarifa por hora hoy (Q)<\/label>\n          <input class=\"form-input\" id=\"h-tarifa\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Si todav\u00eda no tienes tarifa, d\u00e9jalo en cero.<\/p>\n        <\/div>\n      <\/div>\n\n      <div class=\"fila-campos tres\" style=\"margin-top:1rem\">\n        <div>\n          <label class=\"form-label\" for=\"h-imprevistos\">5 \u00b7 Colch\u00f3n para imprevistos (%)<\/label>\n          <input class=\"form-input\" id=\"h-imprevistos\" type=\"text\" inputmode=\"decimal\" placeholder=\"10\" value=\"10\">\n          <p class=\"micro gris\">Revisiones, retrasos, pruebas. Un 10-20% evita trabajar gratis.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"h-comision\">6 \u00b7 Comisi\u00f3n que pagas (%)<\/label>\n          <input class=\"form-input\" id=\"h-comision\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Si cobras por plataformas o con intermediarios.<\/p>\n        <\/div>\n        <div>\n          <label class=\"form-label\" for=\"h-horas-proyecto\">7 \u00b7 Horas de un proyecto t\u00edpico<\/label>\n          <input class=\"form-input\" id=\"h-horas-proyecto\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Para ver tambi\u00e9n el precio del proyecto completo.<\/p>\n        <\/div>\n      <\/div>\n      <div class=\"fila-campos dos\" style=\"margin-top:1rem\">\n        <div>\n          <label class=\"form-label\" for=\"h-gastos\">8 \u00b7 Gastos directos del proyecto (Q)<\/label>\n          <input class=\"form-input\" id=\"h-gastos\" type=\"text\" inputmode=\"decimal\" placeholder=\"0\" value=\"0\">\n          <p class=\"micro gris\">Materiales, transporte, licencias que pagas por ese trabajo.<\/p>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <div id=\"h-veredicto\"><\/div>\n\n    <div class=\"blanco tono-lila\">\n      <h2>Lo que dicen tus n\u00fameros<\/h2>\n      <div class=\"rejilla rejilla-4\" id=\"h-tarjetas\"><\/div>\n      <div id=\"h-desglose\" style=\"margin-top:1.5rem\"><\/div>\n    <\/div>\n\n    <div class=\"blanco tono-azul\">\n      <h2>Qu\u00e9 pasa si cambio algo<\/h2>\n      <div class=\"tabla-contenedor\"><table class=\"tabla escenarios\" id=\"h-escenarios\"><\/table><\/div>\n    <\/div>\n\n    <div class=\"blanco tono-verde\">\n      <h2>C\u00f3mo leer esto<\/h2>\n      <ul class=\"lista chico\">\n        <li><strong>Tarifa m\u00ednima:<\/strong> lo que necesitas cobrar por hora solo para cubrir costos y tu\n          sueldo. Por debajo de ah\u00ed est\u00e1s pagando por trabajar.<\/li>\n        <li><strong>Tarifa recomendada:<\/strong> la m\u00ednima m\u00e1s el colch\u00f3n de imprevistos y comisiones. Es la\n          que deber\u00edas poner en tus propuestas.<\/li>\n        <li><strong>Horas facturables:<\/strong> es el n\u00famero que m\u00e1s cambia el resultado. Si facturas 60 horas\n          al mes en lugar de 100, tu hora tiene que valer mucho m\u00e1s.<\/li>\n        <li><strong>Cobrar por proyecto:<\/strong> multiplica tu tarifa recomendada por las horas que te lleva\n          y s\u00famale los gastos. Nunca cotices contando solo el trabajo bonito: cuenta tambi\u00e9n lo que no se ve.<\/li>\n      <\/ul>\n    <\/div>\n  <\/section>\n\n  <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 ACCIONES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n  <div class=\"acciones no-imprimir\">\n    <button class=\"btn btn-copiar\" id=\"btn-copiar\">Copiar mi resumen<\/button>\n    <button class=\"btn btn-copiar\" id=\"btn-enlace\">Copiar enlace con mis n\u00fameros<\/button>\n    <button class=\"btn btn-secundario\" id=\"btn-imprimir\">Imprimir \/ Guardar en PDF<\/button>\n    <button class=\"btn btn-ejemplo\" id=\"btn-ejemplo\">Ver un ejemplo<\/button>\n    <button class=\"btn btn-reiniciar\" id=\"btn-reiniciar\">Borrar y empezar de nuevo<\/button>\n  <\/div>\n\n  <p class=\"nota no-imprimir\">El resumen que copias o imprimes lleva tus n\u00fameros y los resultados: sirve\n    para llevarlo a tu contador o para compararlo con tu socio.<\/p>\n  <p class=\"micro gris\" style=\"text-align:center; margin-top:2rem\">\n    Herramienta de <strong>Vela Producciones<\/strong> \u00b7 Tus n\u00fameros no salen de tu navegador: no se env\u00edan a ning\u00fan sitio. C\u00e1lculo orientativo, no sustituye a tu contador.\n  <\/p>\n<\/div>\n<\/div>\n<div class=\"brindis\" id=\"brindis\" role=\"status\" aria-live=\"polite\"><\/div>\n<script>\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   UTILIDADES COMPARTIDAS DE LAS HERRAMIENTAS DE VELA\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Lo que TODAS necesitan y no vale la pena escribir tres veces: avisos flotantes,\n   escapar texto, copiar al portapapeles, guardar en el navegador, leer y escribir el\n   enlace compartible, y dar formato a los n\u00fameros en quetzales.\n\n   Se expone como `window.VH`. Cada herramienta la usa as\u00ed:\n       VH.avisar('Listo');\n       VH.moneda(1234.5)   \u2192  'Q1,234.50'\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\nwindow.VH = (function () {\n  'use strict';\n\n  function $(sel, raiz) { return (raiz || document).querySelector(sel); }\n  function $$(sel, raiz) { return Array.prototype.slice.call((raiz || document).querySelectorAll(sel)); }\n\n  \/** Texto seguro para insertar en el HTML. *\/\n  function escapar(s) {\n    return String(s == null ? '' : s)\n      .replace(\/&\/g, '&amp;').replace(\/<\/g, '&lt;').replace(\/>\/g, '&gt;')\n      .replace(\/\"\/g, '&quot;').replace(\/'\/g, '&#39;');\n  }\n\n  \/** Aviso flotante abajo en el centro. *\/\n  function avisar(texto) {\n    const t = $('#brindis');\n    if (!t) { return; }\n    t.textContent = texto;\n    t.classList.add('visible');\n    clearTimeout(avisar._t);\n    avisar._t = setTimeout(() => t.classList.remove('visible'), 2800);\n  }\n\n  \/** Copia al portapapeles, con respaldo para navegadores viejos. *\/\n  function copiar(texto, mensaje) {\n    const listo = () => avisar(mensaje || 'Copiado.');\n    const viejo = () => {\n      const ta = document.createElement('textarea');\n      ta.value = texto;\n      ta.setAttribute('readonly', '');\n      ta.style.position = 'absolute';\n      ta.style.left = '-9999px';\n      document.body.appendChild(ta);\n      ta.select();\n      try { document.execCommand('copy'); listo(); }\n      catch (e) { avisar('No se pudo copiar: selecciona el texto a mano.'); }\n      document.body.removeChild(ta);\n    };\n    if (navigator.clipboard && navigator.clipboard.writeText) {\n      navigator.clipboard.writeText(texto).then(listo, viejo);\n    } else {\n      viejo();\n    }\n  }\n\n  \/* \u2500\u2500 guardado en el navegador (nada sale del equipo del visitante) \u2500\u2500 *\/\n  function guardar(clave, datos) {\n    try { localStorage.setItem(clave, JSON.stringify(datos)); } catch (e) { \/* modo privado *\/ }\n  }\n  function cargar(clave) {\n    try {\n      const crudo = localStorage.getItem(clave);\n      return crudo ? (JSON.parse(crudo) || null) : null;\n    } catch (e) { return null; }\n  }\n  function borrarGuardado(clave) {\n    try { localStorage.removeItem(clave); } catch (e) { \/* nada *\/ }\n  }\n\n  \/* \u2500\u2500 enlace compartible: #d=campo-1,campo2-3 \u2026 \u2500\u2500 *\/\n  function enlaceConHash(prefijo, pares) {\n    const base = window.location.href.split('#')[0];\n    const partes = Object.keys(pares)\n      .filter((k) => pares[k] !== '' && pares[k] != null)\n      .map((k) => k + '-' + encodeURIComponent(pares[k]));\n    return partes.length ? base + '#' + prefijo + '=' + partes.join(',') : base;\n  }\n  function leerHash(prefijo) {\n    try {\n      const m = decodeURIComponent(window.location.hash || '').match(new RegExp(prefijo + '=([^&]+)'));\n      if (!m) { return null; }\n      const salida = {};\n      m[1].split(',').forEach((par) => {\n        const i = par.indexOf('-');\n        if (i > 0) { salida[par.slice(0, i)] = decodeURIComponent(par.slice(i + 1)); }\n      });\n      return Object.keys(salida).length ? salida : null;\n    } catch (e) { return null; }\n  }\n  function limpiarHash() {\n    try { window.history.replaceState(null, '', window.location.href.split('#')[0]); } catch (e) { \/* nada *\/ }\n  }\n\n  \/* \u2500\u2500 n\u00fameros \u2500\u2500 *\/\n  \/** Lee un n\u00famero escrito por una persona: acepta \u00ab1.234,56\u00bb, \u00ab1,234.56\u00bb y vac\u00edos. *\/\n  function numero(valor) {\n    if (typeof valor === 'number') { return isFinite(valor) ? valor : 0; }\n    let s = String(valor == null ? '' : valor).trim().replace(\/\\s\/g, '').replace(\/Q\/gi, '');\n    if (!s) { return 0; }\n    if (s.indexOf(',') > -1 && s.indexOf('.') > -1) {\n      \/\/ el \u00faltimo separador que aparece es el decimal\n      s = (s.lastIndexOf(',') > s.lastIndexOf('.')) ? s.replace(\/\\.\/g, '').replace(',', '.') : s.replace(\/,\/g, '');\n    } else if (s.indexOf(',') > -1) {\n      s = (s.split(',').pop().length === 3) ? s.replace(\/,\/g, '') : s.replace(',', '.');\n    }\n    const n = parseFloat(s.replace(\/[^0-9.\\-]\/g, ''));\n    return isFinite(n) ? n : 0;\n  }\n\n  \/** Da formato de quetzales: 1234.5 \u2192 \u00abQ1,234.50\u00bb. *\/\n  function moneda(n, decimales) {\n    const d = (decimales === undefined) ? 2 : decimales;\n    const v = isFinite(n) ? n : 0;\n    const neg = v < 0;\n    const partes = Math.abs(v).toFixed(d).split('.');\n    partes[0] = partes[0].replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, ',');\n    return (neg ? '-Q' : 'Q') + partes.join('.');\n  }\n\n  \/** Da formato a un n\u00famero normal (sin quetzales). *\/\n  function cifra(n, decimales) {\n    const d = (decimales === undefined) ? 0 : decimales;\n    const v = isFinite(n) ? n : 0;\n    const partes = v.toFixed(d).split('.');\n    partes[0] = partes[0].replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, ',');\n    return partes.join('.');\n  }\n\n  function porcentaje(parte, total) {\n    if (!total) { return 0; }\n    return Math.round((parte \/ total) * 100);\n  }\n\n  function limitar(n, minimo, maximo) {\n    return Math.min(maximo, Math.max(minimo, n));\n  }\n\n  \/** Imprime (el CSS de impresi\u00f3n ya oculta pesta\u00f1as y botones). *\/\n  function imprimir() { window.print(); }\n\n  return {\n    $: $, $$: $$, escapar: escapar, avisar: avisar, copiar: copiar,\n    guardar: guardar, cargar: cargar, borrarGuardado: borrarGuardado,\n    enlaceConHash: enlaceConHash, leerHash: leerHash, limpiarHash: limpiarHash,\n    numero: numero, moneda: moneda, cifra: cifra, porcentaje: porcentaje,\n    limitar: limitar, imprimir: imprimir\n  };\n})();\n<\/script>\n<script>\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n   CALCULADORA DE PRECIOS Y PUNTO DE EQUILIBRIO\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Todo el c\u00e1lculo es matem\u00e1tica simple y ocurre en el navegador del visitante:\n   no hay llamadas a ning\u00fan servidor, ni IA, ni registros. Los n\u00fameros son suyos.\n\n   Dos modos, porque son dos negocios distintos:\n     \u00b7 PRODUCTOS  \u2192 cu\u00e1nto deja cada unidad y cu\u00e1ntas hay que vender para cubrir los fijos.\n     \u00b7 HORAS      \u2192 cu\u00e1nto vale tu hora para cubrir costos, tu sueldo y los imprevistos.\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\n(function () {\n  'use strict';\n\n  const VH = window.VH;\n  const CLAVE = 'vela_precios_v1';\n\n  \/* Campos de cada modo. El id es el mismo del HTML: as\u00ed el guardado y el enlace\n     compartible se arman solos, sin listas paralelas que se desincronizan. *\/\n  const CAMPOS = {\n    producto: ['p-fijos', 'p-variable', 'p-precio', 'p-unidades', 'p-comision', 'p-impuesto', 'p-margen'],\n    hora: ['h-fijos', 'h-sueldo', 'h-horas', 'h-tarifa', 'h-imprevistos', 'h-comision',\n           'h-horas-proyecto', 'h-gastos']\n  };\n  const TODOS = CAMPOS.producto.concat(CAMPOS.hora);\n  const PANELES = { producto: 'panel-producto', hora: 'panel-hora' };\n\n  const EJEMPLO = {\n    'p-fijos': '4500', 'p-variable': '18', 'p-precio': '45', 'p-unidades': '260',\n    'p-comision': '4', 'p-impuesto': '12', 'p-margen': '50',\n    'h-fijos': '3200', 'h-sueldo': '9000', 'h-horas': '90', 'h-tarifa': '150',\n    'h-imprevistos': '15', 'h-comision': '0', 'h-horas-proyecto': '12', 'h-gastos': '350'\n  };\n\n  let modo = 'producto';\n\n  \/* \u2500\u2500 leer y escribir los campos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function valor(id) { return VH.numero((VH.$('#' + id) || {}).value); }\n  function escribir(id, v) { const el = VH.$('#' + id); if (el) { el.value = v; } }\n\n  function leerCampos() {\n    const datos = {};\n    TODOS.forEach((id) => { datos[id] = (VH.$('#' + id) || {}).value || ''; });\n    return datos;\n  }\n\n  function aplicarCampos(datos) {\n    if (!datos) { return; }\n    Object.keys(datos).forEach((id) => { if (TODOS.indexOf(id) > -1) { escribir(id, datos[id]); } });\n  }\n\n  \/* \u2500\u2500 matem\u00e1tica del modo producto \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function calcularProducto() {\n    const fijos = valor('p-fijos');\n    const costo = valor('p-variable');\n    const precio = valor('p-precio');\n    const unidades = valor('p-unidades');\n    const comision = VH.limitar(valor('p-comision'), 0, 95);\n    const impuesto = VH.limitar(valor('p-impuesto'), 0, 95);\n    const margen = VH.limitar(valor('p-margen'), 0, 500);\n    const cargas = VH.limitar(comision + impuesto, 0, 95) \/ 100;\n\n    const comisionQ = precio * (comision \/ 100);\n    const impuestoQ = precio * (impuesto \/ 100);\n    const neto = precio - comisionQ - impuestoQ;\n    const ganancia = neto - costo;\n    const margenReal = precio > 0 ? (ganancia \/ precio) * 100 : 0;\n    const precioMinimo = cargas < 1 ? costo \/ (1 - cargas) : Infinity;\n    const precioRecomendado = cargas < 1 ? (costo * (1 + margen \/ 100)) \/ (1 - cargas) : Infinity;\n    const equilibrio = ganancia > 0 ? fijos \/ ganancia : Infinity;\n    const gananciaMes = ganancia * unidades - fijos;\n\n    return {\n      modo: 'producto', fijos, costo, precio, unidades, comision, impuesto, margen,\n      comisionQ, impuestoQ, neto, ganancia, margenReal, precioMinimo, precioRecomendado,\n      equilibrio, gananciaMes, cargas\n    };\n  }\n\n  \/* \u2500\u2500 matem\u00e1tica del modo horas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function calcularHora() {\n    const fijos = valor('h-fijos');\n    const sueldo = valor('h-sueldo');\n    const horas = valor('h-horas');\n    const tarifa = valor('h-tarifa');\n    const imprevistos = VH.limitar(valor('h-imprevistos'), 0, 200);\n    const comision = VH.limitar(valor('h-comision'), 0, 95);\n    const horasProyecto = valor('h-horas-proyecto');\n    const gastosProyecto = valor('h-gastos');\n    const factorComision = 1 - comision \/ 100;\n\n    const costoHora = horas > 0 ? (fijos + sueldo) \/ horas : Infinity;\n    const tarifaMinima = horas > 0 && factorComision > 0 ? costoHora \/ factorComision : Infinity;\n    const tarifaRecomendada = tarifaMinima * (1 + imprevistos \/ 100);\n    const sueldoReal = tarifa * horas * factorComision - fijos;\n    const horasParaSueldo = tarifa > 0 && factorComision > 0\n      ? (fijos + sueldo) \/ (tarifa * factorComision) : Infinity;\n    const precioProyecto = horasProyecto > 0 ? tarifaRecomendada * horasProyecto + gastosProyecto : 0;\n    const precioProyectoMinimo = horasProyecto > 0 ? tarifaMinima * horasProyecto + gastosProyecto : 0;\n\n    return {\n      modo: 'hora', fijos, sueldo, horas, tarifa, imprevistos, comision, horasProyecto,\n      gastosProyecto, costoHora, tarifaMinima, tarifaRecomendada, sueldoReal, horasParaSueldo,\n      precioProyecto, precioProyectoMinimo, factorComision\n    };\n  }\n\n  \/* \u2500\u2500 sem\u00e1foro: el texto del veredicto \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function veredictoProducto(r) {\n    if (r.precio <= 0 || r.costo <= 0) {\n      return { tono: 'gris', estilo: 'post-it-azul', titulo: 'Empieza por los tres primeros campos',\n        texto: 'Con el costo de una unidad y tu precio actual ya te digo si ganas o pierdes. Los dem\u00e1s campos mejoran el c\u00e1lculo.' };\n    }\n    if (r.ganancia <= 0) {\n      return { tono: 'mal', estilo: 'post-it-rosa', titulo: 'A este precio est\u00e1s perdiendo ' +\n        VH.moneda(Math.abs(r.ganancia)) + ' en cada venta',\n        texto: 'Tu precio no cubre ni el costo de la unidad m\u00e1s comisiones e impuestos. Tu precio m\u00ednimo para no perder es ' +\n          VH.moneda(r.precioMinimo) + '. Cada venta por debajo de ah\u00ed sale de tu bolsillo.' };\n    }\n    if (r.precio < r.precioRecomendado - 0.5) {\n      const falta = r.precioRecomendado - r.precio;\n      return { tono: 'ojo', estilo: 'post-it-amarillo', titulo: 'Ganas, pero menos de lo que buscabas',\n        texto: 'Cada unidad te deja ' + VH.moneda(r.ganancia) + '. Para ganar el ' + Math.round(r.margen) +\n          '% sobre el costo tendr\u00edas que cobrar ' + VH.moneda(r.precioRecomendado) + ': te faltan ' +\n          VH.moneda(falta) + ' por unidad. Sube el precio a ese n\u00famero o baja el costo.' };\n    }\n    const base = 'Cada unidad te deja ' + VH.moneda(r.ganancia) + ' (' + Math.round(r.margenReal) +\n      '% del precio). Tu precio recomendado era ' + VH.moneda(r.precioRecomendado) + ' y cobras ' +\n      VH.moneda(r.precio) + ', as\u00ed que vas por encima de tu meta.';\n    if (r.gananciaMes < 0 && isFinite(r.equilibrio)) {\n      return { tono: 'ojo', estilo: 'post-it-amarillo', titulo: 'Tu precio est\u00e1 bien, pero el volumen no alcanza',\n        texto: base + ' El problema no es el precio: con ' + VH.cifra(r.unidades) + ' unidades al mes todav\u00eda no ' +\n          'cubres los ' + VH.moneda(r.fijos) + ' de costos fijos. Te faltan ' +\n          VH.cifra(Math.ceil(r.equilibrio - r.unidades)) + ' unidades para no perder.' };\n    }\n    return { tono: 'ok', estilo: 'post-it-verde', titulo: 'Tu precio est\u00e1 donde debe estar',\n      texto: base + ' Ahora el trabajo es vender m\u00e1s unidades, no tocar el precio.' };\n  }\n\n  function veredictoHora(r) {\n    if (r.horas <= 0 || (r.fijos + r.sueldo) <= 0) {\n      return { tono: 'gris', estilo: 'post-it-azul', titulo: 'Empieza por tus costos y tus horas',\n        texto: 'Con tus costos fijos, el sueldo que quieres ganar y las horas que facturas al mes te digo cu\u00e1nto vale tu hora.' };\n    }\n    if (r.tarifa <= 0) {\n      return { tono: 'gris', estilo: 'post-it-azul', titulo: 'Tu hora tendr\u00eda que valer ' + VH.moneda(r.tarifaRecomendada),\n        texto: 'Con ' + VH.cifra(r.horas) + ' horas facturables al mes, por debajo de ' + VH.moneda(r.tarifaMinima) +\n          ' la hora no cubres costos ni tu sueldo. Con el colch\u00f3n del ' + Math.round(r.imprevistos) +\n          '% recomendado, tu tarifa es ' + VH.moneda(r.tarifaRecomendada) + '.' };\n    }\n    if (r.tarifa < r.tarifaMinima - 0.5) {\n      return { tono: 'mal', estilo: 'post-it-rosa', titulo: 'Con esa tarifa est\u00e1s pagando por trabajar',\n        texto: 'Cobras ' + VH.moneda(r.tarifa) + ' y necesitas al menos ' + VH.moneda(r.tarifaMinima) +\n          ' la hora para cubrir tus costos y tu sueldo. Ajusta la tarifa o baja los costos: con ' +\n          VH.cifra(r.horas) + ' horas al mes te faltan ' + VH.moneda((r.tarifaMinima - r.tarifa) * r.horas) + '.' };\n    }\n    if (r.tarifa < r.tarifaRecomendada - 0.5) {\n      return { tono: 'ojo', estilo: 'post-it-amarillo', titulo: 'Cubres costos, pero sin colch\u00f3n',\n        texto: 'Tu tarifa de ' + VH.moneda(r.tarifa) + ' pasa el m\u00ednimo (' + VH.moneda(r.tarifaMinima) +\n          '), pero no llega al recomendado (' + VH.moneda(r.tarifaRecomendada) +\n          '). Ese ' + Math.round(r.imprevistos) + '% es lo que evita que trabajes gratis en las revisiones.' };\n    }\n    return { tono: 'ok', estilo: 'post-it-verde', titulo: 'Tu tarifa est\u00e1 bien puesta',\n      texto: 'Con ' + VH.moneda(r.tarifa) + ' la hora cubres tus costos, tu sueldo y el colch\u00f3n de imprevistos.' +\n        (r.sueldo > 0 ? ' Te quedan ' + VH.moneda(r.sueldoReal) + ' al mes de sueldo para ti.' : '') };\n  }\n\n  \/* \u2500\u2500 pintar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function tarjeta(rotulo, dato, pista, clase) {\n    return '<div class=\"metrica ' + (clase || '') + '\"><div class=\"rotulo\">' + VH.escapar(rotulo) +\n      '<\/div><div class=\"dato\">' + VH.escapar(dato) + '<\/div><div class=\"pista\">' + VH.escapar(pista) + '<\/div><\/div>';\n  }\n\n  function pintarProducto(r) {\n    const v = veredictoProducto(r);\n    VH.$('#p-veredicto').innerHTML = '<div class=\"post-it ' + v.estilo + '\"><h3 style=\"margin-bottom:.35rem\">' +\n      VH.escapar(v.titulo) + '<\/h3><p style=\"margin:0\">' + VH.escapar(v.texto) + '<\/p><\/div>';\n\n    const faltan = r.equilibrio === Infinity ? null : Math.max(0, Math.ceil(r.equilibrio - r.unidades));\n    VH.$('#p-tarjetas').innerHTML =\n      tarjeta('Ganas por unidad', VH.moneda(r.ganancia),\n        r.precio > 0 ? Math.round(r.margenReal) + '% de tu precio de venta' : 'completa tus n\u00fameros',\n        r.ganancia > 0 ? 'ok' : 'mal') +\n      tarjeta('Precio m\u00ednimo', VH.moneda(r.precioMinimo), 'por debajo de aqu\u00ed pierdes dinero', 'ojo') +\n      tarjeta('Precio recomendado', VH.moneda(r.precioRecomendado),\n        'para ganar el ' + Math.round(r.margen) + '% sobre el costo', 'destacada') +\n      tarjeta('Unidades para no perder',\n        r.equilibrio === Infinity ? '\u2014' : VH.cifra(Math.ceil(r.equilibrio)),\n        r.equilibrio === Infinity ? 'con este precio no hay punto de equilibrio' :\n          'al mes, para cubrir ' + VH.moneda(r.fijos) + ' de costos fijos',\n        r.equilibrio === Infinity ? 'mal' : (r.unidades >= r.equilibrio ? 'ok' : 'ojo'));\n\n    const lineas = [\n      ['Precio de venta', VH.moneda(r.precio)],\n      ['\u2212 Comisi\u00f3n (' + Math.round(r.comision) + '%)', '\u2212 ' + VH.moneda(r.comisionQ)],\n      ['\u2212 Impuestos (' + Math.round(r.impuesto) + '%)', '\u2212 ' + VH.moneda(r.impuestoQ)],\n      ['\u2212 Costo de la unidad', '\u2212 ' + VH.moneda(r.costo)],\n      ['<strong>Ganancia por unidad<\/strong>', '<strong>' + VH.moneda(r.ganancia) + '<\/strong>'],\n      ['\u00d7 Unidades al mes', VH.cifra(r.unidades)],\n      ['\u2212 Costos fijos del mes', '\u2212 ' + VH.moneda(r.fijos)],\n      ['<strong>' + (r.gananciaMes >= 0 ? 'Ganancia del mes' : 'P\u00e9rdida del mes') + '<\/strong>',\n        '<strong>' + VH.moneda(r.gananciaMes) + '<\/strong>']\n    ];\n    VH.$('#p-desglose').innerHTML = '<h3>Cuenta paso a paso<\/h3><div class=\"tabla-contenedor\"><table class=\"tabla\">' + lineas.map((l) =>\n      '<tr><td>' + l[0] + '<\/td><td class=\"num\">' + l[1] + '<\/td><\/tr>').join('') + '<\/table><\/div>' +\n      (faltan === null ? '' :\n        '<p class=\"' + (faltan > 0 ? 'alerta' : 'fortaleza') + '\" style=\"margin-top:1rem\">' +\n        (faltan > 0\n          ? 'Te faltan <strong>' + VH.cifra(faltan) + ' unidades<\/strong> al mes para cubrir tus costos fijos. De tu punto de equilibrio en adelante, todo lo que vendes es ganancia.'\n          : 'Vas <strong>' + VH.cifra(Math.max(0, Math.ceil(r.unidades - r.equilibrio))) +\n            ' unidades<\/strong> por encima de tu punto de equilibrio. Cada unidad extra son ' +\n            VH.moneda(r.ganancia) + ' de ganancia.') + '<\/p>');\n\n    pintarEscenariosProducto(r);\n  }\n\n  function pintarEscenariosProducto(r) {\n    if (r.precio <= 0 || r.costo <= 0) {\n      VH.$('#p-escenarios').className = 'tabla escenarios';\n    VH.$('#p-escenarios').innerHTML = '<tr><td class=\"gris\">Completa tu precio y tu costo para ver escenarios.<\/td><\/tr>';\n      return;\n    }\n    const variantes = [\n      { nombre: 'Como est\u00e1s hoy', precio: r.precio, costo: r.costo, fijos: r.fijos, comision: r.comision, base: true },\n      { nombre: 'Subes el precio 10%', precio: r.precio * 1.1, costo: r.costo, fijos: r.fijos, comision: r.comision },\n      { nombre: 'Bajas el costo de la unidad 10%', precio: r.precio, costo: r.costo * 0.9, fijos: r.fijos, comision: r.comision },\n      { nombre: 'Bajas los costos fijos 10%', precio: r.precio, costo: r.costo, fijos: r.fijos * 0.9, comision: r.comision }\n    ];\n    if (r.comision >= 2) {\n      variantes.push({ nombre: 'Pagas 2 puntos menos de comisi\u00f3n', precio: r.precio, costo: r.costo,\n        fijos: r.fijos, comision: r.comision - 2 });\n    }\n\n    const cargas = r.cargas;\n    const filas = variantes.map((x) => {\n      const gananciaU = x.precio * (1 - cargas) - x.costo;\n      const eq = gananciaU > 0 ? x.fijos \/ gananciaU : Infinity;\n      const mes = gananciaU * r.unidades - x.fijos;\n      const marca = (v) => (v.dif - x.base ? '' : '');\n      return { x, gananciaU, eq, mes };\n    });\n\n    const base = filas[0];\n    const celda = (actual, referencia, invertir) => {\n      if (!isFinite(actual) || !isFinite(referencia)) { return '<td class=\"num\">\u2014<\/td>'; }\n      const dif = actual - referencia;\n      if (Math.abs(dif) < 0.01) { return '<td class=\"num\">' + '' + '<\/td>'; }\n      const mejor = invertir ? dif < 0 : dif > 0;\n      return '<td class=\"num\"><span class=\"' + (mejor ? 'mejora' : 'empeora') + '\">' +\n        (mejor ? '\u25b2 ' : '\u25bc ') + (invertir ? VH.cifra(Math.abs(dif), 1) : VH.moneda(Math.abs(dif))) + '<\/span><\/td>';\n    };\n\n    VH.$('#p-escenarios').innerHTML =\n      '<thead><tr><th>Escenario<\/th><th>Ganancia por unidad<\/th><th>Unidades para no perder<\/th>' +\n      '<th>Ganancia del mes<\/th><th>Diferencia al mes<\/th><\/tr><\/thead><tbody>' +\n      filas.map((f) => '<tr class=\"' + (f.x.base ? 'fila-base' : '') + '\">' +\n        '<td>' + VH.escapar(f.x.nombre) + '<\/td>' +\n        '<td class=\"num\">' + VH.moneda(f.gananciaU) + '<\/td>' +\n        '<td class=\"num\">' + (isFinite(f.eq) ? VH.cifra(Math.ceil(f.eq)) : '\u2014') + '<\/td>' +\n        '<td class=\"num\">' + VH.moneda(f.mes) + '<\/td>' +\n        (f.x.base ? '<td class=\"num gris\">\u2014<\/td>' : celda(f.mes, base.mes, false)) + '<\/tr>').join('') +\n      '<\/tbody>';\n  }\n\n  function pintarHora(r) {\n    const v = veredictoHora(r);\n    VH.$('#h-veredicto').innerHTML = '<div class=\"post-it ' + v.estilo + '\"><h3 style=\"margin-bottom:.35rem\">' +\n      VH.escapar(v.titulo) + '<\/h3><p style=\"margin:0\">' + VH.escapar(v.texto) + '<\/p><\/div>';\n\n    const cuarta = r.horasProyecto > 0\n      ? tarjeta('Precio del proyecto', VH.moneda(r.precioProyecto),\n          VH.cifra(r.horasProyecto) + ' horas + ' + VH.moneda(r.gastosProyecto) + ' de gastos', 'destacada')\n      : tarjeta('Horas para tu sueldo',\n          isFinite(r.horasParaSueldo) ? VH.cifra(Math.ceil(r.horasParaSueldo)) : '\u2014',\n          'al mes con tu tarifa actual', 'ojo');\n\n    VH.$('#h-tarjetas').innerHTML =\n      tarjeta('Tu tarifa m\u00ednima', VH.moneda(r.tarifaMinima), 'por hora, para no perder', 'ojo') +\n      tarjeta('Tu tarifa recomendada', VH.moneda(r.tarifaRecomendada),\n        'con ' + Math.round(r.imprevistos) + '% de colch\u00f3n para imprevistos', 'destacada') +\n      tarjeta('Tu sueldo real al mes', VH.moneda(r.sueldoReal),\n        'despu\u00e9s de costos fijos y comisiones',\n        r.sueldoReal >= r.sueldo ? 'ok' : (r.sueldoReal > 0 ? 'ojo' : 'mal')) +\n      cuarta;\n\n    const lineas = [\n      ['Costos fijos del mes', VH.moneda(r.fijos)],\n      ['Sueldo que quieres ganarte', VH.moneda(r.sueldo)],\n      ['\u00f7 Horas que facturas al mes', VH.cifra(r.horas)],\n      ['<strong>Costo de tu hora<\/strong>', '<strong>' + VH.moneda(r.costoHora) + '<\/strong>'],\n      ['+ Colch\u00f3n de imprevistos (' + Math.round(r.imprevistos) + '%)', '+ ' + VH.moneda(r.tarifaRecomendada - r.tarifaMinima)],\n      ['<strong>Tarifa recomendada<\/strong>', '<strong>' + VH.moneda(r.tarifaRecomendada) + '<\/strong>'],\n      ['Con tu tarifa actual (' + VH.moneda(r.tarifa) + ' \u00d7 ' + VH.cifra(r.horas) + ' h)',\n        VH.moneda(r.tarifa * r.horas * r.factorComision)],\n      ['\u2212 Costos fijos', '\u2212 ' + VH.moneda(r.fijos)],\n      ['<strong>Lo que te queda<\/strong>', '<strong>' + VH.moneda(r.sueldoReal) + '<\/strong>']\n    ];\n    VH.$('#h-desglose').innerHTML = '<h3>Cuenta paso a paso<\/h3><div class=\"tabla-contenedor\"><table class=\"tabla\">' + lineas.map((l) =>\n      '<tr><td>' + l[0] + '<\/td><td class=\"num\">' + l[1] + '<\/td><\/tr>').join('') + '<\/table><\/div>' +\n      (r.sueldo > 0 && r.tarifa > 0\n        ? '<p class=\"' + (r.sueldoReal >= r.sueldo ? 'fortaleza' : 'alerta') + '\" style=\"margin-top:1rem\">' +\n          (r.sueldoReal >= r.sueldo\n            ? 'Con tu tarifa actual te queda m\u00e1s de lo que quer\u00edas ganarte: ' + VH.moneda(r.sueldoReal) + '.'\n            : 'Te faltan ' + VH.moneda(r.sueldo - r.sueldoReal) + ' al mes para llegar al sueldo que quieres. Con ' +\n              VH.cifra(r.horas) + ' horas facturables, son ' +\n              VH.moneda((r.sueldo - r.sueldoReal) \/ Math.max(1, r.horas * r.factorComision)) + ' m\u00e1s por hora.') +\n          '<\/p>'\n        : '');\n\n    pintarEscenariosHora(r);\n  }\n\n  function pintarEscenariosHora(r) {\n    if (r.horas <= 0) {\n      VH.$('#h-escenarios').className = 'tabla escenarios';\n    VH.$('#h-escenarios').innerHTML = '<tr><td class=\"gris\">Escribe tus horas facturables para ver escenarios.<\/td><\/tr>';\n      return;\n    }\n    const filas = [\n      { nombre: 'Como est\u00e1s hoy', tarifa: r.tarifa || r.tarifaRecomendada, horas: r.horas, fijos: r.fijos, base: true },\n      { nombre: 'Subes tu tarifa 10%', tarifa: (r.tarifa || r.tarifaRecomendada) * 1.1, horas: r.horas, fijos: r.fijos },\n      { nombre: 'Facturas 20% m\u00e1s horas', tarifa: r.tarifa || r.tarifaRecomendada, horas: r.horas * 1.2, fijos: r.fijos },\n      { nombre: 'Bajas los costos fijos 10%', tarifa: r.tarifa || r.tarifaRecomendada, horas: r.horas, fijos: r.fijos * 0.9 }\n    ].map((f) => ({ ...f, sueldo: f.tarifa * f.horas * r.factorComision - f.fijos }));\n\n    const base = filas[0];\n    VH.$('#h-escenarios').innerHTML =\n      '<thead><tr><th>Escenario<\/th><th>Tarifa por hora<\/th><th>Horas al mes<\/th><th>Tu sueldo al mes<\/th><th>Diferencia<\/th><\/tr><\/thead><tbody>' +\n      filas.map((f) => {\n        const dif = f.sueldo - base.sueldo;\n        const marca = f.base || Math.abs(dif) < 0.01 ? '<td class=\"num gris\">\u2014<\/td>'\n          : '<td class=\"num\"><span class=\"' + (dif > 0 ? 'mejora' : 'empeora') + '\">' +\n            (dif > 0 ? '\u25b2 ' : '\u25bc ') + VH.moneda(Math.abs(dif)) + '<\/span><\/td>';\n        return '<tr class=\"' + (f.base ? 'fila-base' : '') + '\"><td>' + VH.escapar(f.nombre) + '<\/td>' +\n          '<td class=\"num\">' + VH.moneda(f.tarifa) + '<\/td>' +\n          '<td class=\"num\">' + VH.cifra(f.horas) + '<\/td>' +\n          '<td class=\"num\">' + VH.moneda(f.sueldo) + '<\/td>' + marca + '<\/tr>';\n      }).join('') + '<\/tbody>';\n  }\n\n  \/* \u2500\u2500 refrescar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function refrescar(guardarAhora) {\n    if (modo === 'producto') { pintarProducto(calcularProducto()); }\n    else { pintarHora(calcularHora()); }\n    if (guardarAhora !== false) { VH.guardar(CLAVE, { campos: leerCampos(), modo: modo }); }\n  }\n\n  function mostrarModo(nuevo) {\n    modo = nuevo;\n    Object.keys(PANELES).forEach((k) => {\n      const el = VH.$('#' + PANELES[k]);\n      if (el) { el.classList.toggle('oculto', k !== modo); }\n    });\n    VH.$$('.pestana').forEach((b) => {\n      const activa = b.dataset.panel === PANELES[modo];\n      b.classList.toggle('activa', activa);\n      b.setAttribute('aria-selected', String(activa));\n    });\n    refrescar();\n  }\n\n  \/* \u2500\u2500 resumen para copiar o imprimir \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function resumen() {\n    const l = [];\n    l.push('C\u00c1LCULO DE PRECIOS \u2014 Vela Producciones');\n    l.push(new Date().toLocaleDateString('es-GT'));\n    l.push('');\n    if (modo === 'producto') {\n      const r = calcularProducto();\n      const v = veredictoProducto(r);\n      l.push('MODO: PRODUCTOS');\n      l.push('Costos fijos del mes: ' + VH.moneda(r.fijos));\n      l.push('Costo de una unidad: ' + VH.moneda(r.costo));\n      l.push('Precio actual: ' + VH.moneda(r.precio) + '  \u00b7  Unidades al mes: ' + VH.cifra(r.unidades));\n      l.push('Comisi\u00f3n: ' + Math.round(r.comision) + '%  \u00b7  Impuestos: ' + Math.round(r.impuesto) +\n        '%  \u00b7  Margen buscado: ' + Math.round(r.margen) + '%');\n      l.push('');\n      l.push('Ganancia por unidad: ' + VH.moneda(r.ganancia) + ' (' + Math.round(r.margenReal) + '% del precio)');\n      l.push('Precio m\u00ednimo: ' + VH.moneda(r.precioMinimo));\n      l.push('Precio recomendado: ' + VH.moneda(r.precioRecomendado));\n      l.push('Unidades para cubrir costos fijos: ' +\n        (isFinite(r.equilibrio) ? VH.cifra(Math.ceil(r.equilibrio)) : 'no hay punto de equilibrio'));\n      l.push((r.gananciaMes >= 0 ? 'Ganancia del mes: ' : 'P\u00e9rdida del mes: ') + VH.moneda(r.gananciaMes));\n      l.push('');\n      l.push('Lectura: ' + v.titulo + '. ' + v.texto);\n    } else {\n      const r = calcularHora();\n      const v = veredictoHora(r);\n      l.push('MODO: HORAS \/ SERVICIOS');\n      l.push('Costos fijos del mes: ' + VH.moneda(r.fijos));\n      l.push('Sueldo deseado: ' + VH.moneda(r.sueldo));\n      l.push('Horas facturables al mes: ' + VH.cifra(r.horas));\n      l.push('Tarifa actual: ' + VH.moneda(r.tarifa) + ' por hora');\n      l.push('Colch\u00f3n de imprevistos: ' + Math.round(r.imprevistos) + '%  \u00b7  Comisi\u00f3n: ' + Math.round(r.comision) + '%');\n      l.push('');\n      l.push('Tarifa m\u00ednima: ' + VH.moneda(r.tarifaMinima) + ' por hora');\n      l.push('Tarifa recomendada: ' + VH.moneda(r.tarifaRecomendada) + ' por hora');\n      l.push('Sueldo real al mes: ' + VH.moneda(r.sueldoReal));\n      if (r.horasProyecto > 0) {\n        l.push('Proyecto de ' + VH.cifra(r.horasProyecto) + ' horas: ' + VH.moneda(r.precioProyecto) +\n          ' (m\u00ednimo ' + VH.moneda(r.precioProyectoMinimo) + ')');\n      }\n      l.push('');\n      l.push('Lectura: ' + v.titulo + '. ' + v.texto);\n    }\n    l.push('');\n    l.push('Herramienta gratuita de Vela Producciones \u00b7 velaproducciones.com');\n    return l.join('\\n');\n  }\n\n  \/* \u2500\u2500 arranque y eventos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n  function eventos() {\n    TODOS.forEach((id) => {\n      const el = VH.$('#' + id);\n      if (el) {\n        el.addEventListener('input', () => refrescar());\n        el.addEventListener('change', () => refrescar());\n      }\n    });\n\n    VH.$$('.pestana').forEach((b) => {\n      b.addEventListener('click', () => {\n        const destino = Object.keys(PANELES).find((k) => PANELES[k] === b.dataset.panel);\n        if (destino) { mostrarModo(destino); }\n      });\n    });\n\n    VH.$('#btn-copiar').addEventListener('click', () => VH.copiar(resumen(), 'Resumen copiado.'));\n    VH.$('#btn-imprimir').addEventListener('click', () => VH.imprimir());\n    VH.$('#btn-enlace').addEventListener('click', () => {\n      const url = VH.enlaceConHash('d', leerCampos());\n      try { window.history.replaceState(null, '', url); } catch (e) { \/* nada *\/ }\n      VH.copiar(url, 'Enlace copiado: quien lo abra ver\u00e1 tus n\u00fameros.');\n    });\n    VH.$('#btn-ejemplo').addEventListener('click', () => {\n      aplicarCampos(EJEMPLO);\n      refrescar();\n      VH.avisar('Ejemplo cargado: una panader\u00eda peque\u00f1a que vende por redes.');\n    });\n    VH.$('#btn-reiniciar').addEventListener('click', () => {\n      if (!window.confirm('\u00bfBorrar tus n\u00fameros y empezar de cero?')) { return; }\n      aplicarCampos({});\n      TODOS.forEach((id) => escribir(id, id.indexOf('impuesto') > -1 ? '12' : (id === 'p-margen' ? '40' : (id === 'h-imprevistos' ? '10' : '0'))));\n      VH.borrarGuardado(CLAVE);\n      VH.limpiarHash();\n      refrescar();\n      VH.avisar('Listo: todo en blanco.');\n    });\n  }\n\n  function arrancar() {\n    const guardado = VH.cargar(CLAVE);\n    const delEnlace = VH.leerHash('d');\n    if (delEnlace) {\n      aplicarCampos(delEnlace);\n      VH.avisar('N\u00fameros cargados desde el enlace.');\n    } else if (guardado && guardado.campos) {\n      aplicarCampos(guardado.campos);\n      if (guardado.modo === 'hora') { modo = 'hora'; }\n    }\n    eventos();\n    mostrarModo(modo);\n  }\n\n  arrancar();\n})();\n<\/script>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":5,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-17433","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Calculadora de precios: cu\u00e1nto cobrar y punto de equilibrio | Vela Producciones<\/title>\n<meta name=\"description\" content=\"Calcula gratis cu\u00e1nto cobrar por tu producto o tu hora: precio m\u00ednimo, precio recomendado, cu\u00e1ntas unidades necesitas para no perder y qu\u00e9 pasa si cambias tus n\u00fameros.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/velaproducciones.com\/en\/calculadora-de-precios\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Calculadora de precios: cu\u00e1nto cobrar y punto de equilibrio | Vela Producciones\" \/>\n<meta property=\"og:description\" content=\"Calcula gratis cu\u00e1nto cobrar por tu producto o tu hora: precio m\u00ednimo, precio recomendado, cu\u00e1ntas unidades necesitas para no perder y qu\u00e9 pasa si cambias tus n\u00fameros.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/velaproducciones.com\/en\/calculadora-de-precios\/\" \/>\n<meta property=\"og:site_name\" content=\"Vela Producciones\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-16T20:17:26+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/velaproducciones.com\/wp-content\/uploads\/2024\/11\/vela-producciones.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1080\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/calculadora-de-precios\\\/\",\"url\":\"https:\\\/\\\/velaproducciones.com\\\/calculadora-de-precios\\\/\",\"name\":\"Calculadora de precios: cu\u00e1nto cobrar y punto de equilibrio | Vela Producciones\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/#website\"},\"datePublished\":\"2026-10-10T03:20:52+00:00\",\"dateModified\":\"2026-10-16T20:17:26+00:00\",\"description\":\"Calcula gratis cu\u00e1nto cobrar por tu producto o tu hora: precio m\u00ednimo, precio recomendado, cu\u00e1ntas unidades necesitas para no perder y qu\u00e9 pasa si cambias tus n\u00fameros.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/calculadora-de-precios\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/velaproducciones.com\\\/calculadora-de-precios\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/calculadora-de-precios\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/velaproducciones.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Calculadora de Precios\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/#website\",\"url\":\"https:\\\/\\\/velaproducciones.com\\\/\",\"name\":\"Vela Producciones\",\"description\":\"Creaci\u00f3n y Manejo de P\u00e1ginas WEB, Optimizaci\u00f3n SEO y de Estrategias de Marketing Digital\",\"publisher\":{\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/#organization\"},\"alternateName\":\"VelaWeb\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/velaproducciones.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Organization\",\"LocalBusiness\",\"ProfessionalService\"],\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/#organization\",\"name\":\"Vela Producciones\",\"alternateName\":[\"Grupo Vela S.A.\",\"Vela Producciones Guatemala\"],\"url\":\"https:\\\/\\\/velaproducciones.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/velaproducciones.com\\\/wp-content\\\/uploads\\\/2024\\\/11\\\/Logo_Vela_Producciones-500x500-1.png\",\"contentUrl\":\"https:\\\/\\\/velaproducciones.com\\\/wp-content\\\/uploads\\\/2024\\\/11\\\/Logo_Vela_Producciones-500x500-1.png\",\"width\":540,\"height\":540,\"caption\":\"Grupo Vela S.A.\"},\"image\":{\"@id\":\"https:\\\/\\\/velaproducciones.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/company\\\/velaproducciones\",\"https:\\\/\\\/www.instagram.com\\\/velawebproducciones\\\/\",\"https:\\\/\\\/www.facebook.com\\\/VelaWebProducciones\"],\"legalName\":\"Grupo Vela S.A.\",\"description\":\"Vela Producciones es la divisi\u00f3n comercial de Grupo Vela S.A. para marketing digital, producci\u00f3n audiovisual y eventos, en Ciudad de Guatemala. Estrategia, contenido, posicionamiento (SEO y visibilidad en asistentes de IA), pauta y producci\u00f3n, con medici\u00f3n.\",\"address\":{\"@type\":\"PostalAddress\",\"streetAddress\":\"Edificio 01010, oficina 702\",\"addressLocality\":\"Ciudad de Guatemala\",\"addressRegion\":\"Guatemala\",\"postalCode\":\"01010\",\"addressCountry\":\"GT\"},\"telephone\":\"+502 2220-9556\",\"contactPoint\":[{\"@type\":\"ContactPoint\",\"contactType\":\"customer service\",\"telephone\":\"+502 2220-9556\",\"areaServed\":\"GT\",\"availableLanguage\":[\"es\"]},{\"@type\":\"ContactPoint\",\"contactType\":\"sales\",\"telephone\":\"+1 305 447-7124\",\"areaServed\":\"US\",\"availableLanguage\":[\"es\",\"en\"]}],\"areaServed\":[{\"@type\":\"Country\",\"name\":\"Guatemala\"},{\"@type\":\"Country\",\"name\":\"Estados Unidos\"}],\"openingHoursSpecification\":[{\"@type\":\"OpeningHoursSpecification\",\"dayOfWeek\":[\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\"],\"opens\":\"09:00\",\"closes\":\"17:00\"}],\"knowsAbout\":[\"Marketing digital\",\"Posicionamiento en buscadores (SEO)\",\"Visibilidad en asistentes de IA (GEO y AEO)\",\"Comercio electr\u00f3nico y WooCommerce\",\"Redes sociales\",\"Google Ads y Meta Ads\",\"Producci\u00f3n audiovisual\",\"Transmisi\u00f3n de eventos\",\"Fotograf\u00eda comercial\",\"Anal\u00edtica y medici\u00f3n\"],\"hasOfferCatalog\":{\"@type\":\"OfferCatalog\",\"name\":\"Servicios de Vela Producciones\",\"itemListElement\":[{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Desarrollo web y ecommerce\",\"description\":\"Sitios web, tiendas en l\u00ednea, optimizaci\u00f3n de velocidad y estructura t\u00e9cnica.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Posicionamiento SEO\",\"description\":\"Optimizaci\u00f3n org\u00e1nica: investigaci\u00f3n de palabras clave, contenido, enlazado interno y t\u00e9cnico.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"GEO y AEO (visibilidad en asistentes de IA)\",\"description\":\"Optimizaci\u00f3n para que ChatGPT, Gemini y Perplexity citen y recomienden la marca: datos estructurados, entidad consistente y medici\u00f3n.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Redes sociales\",\"description\":\"Estrategia, producci\u00f3n de contenido y calendarizaci\u00f3n para Instagram, Facebook, TikTok y LinkedIn.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Campa\u00f1as SEM y pauta digital\",\"description\":\"Google Ads, Meta Ads y TikTok Ads, con seguimiento de conversiones.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Producci\u00f3n de video corporativo\",\"description\":\"Spots publicitarios, videos institucionales, reels y piezas narrativas para marca.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Transmisiones y cobertura de eventos\",\"description\":\"Producci\u00f3n multic\u00e1mara, streaming en vivo y cobertura para eventos corporativos.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Fotograf\u00eda comercial\",\"description\":\"Producto, corporativa y de eventos.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Dise\u00f1o de marca e identidad visual\",\"description\":\"Logotipo, manual de marca y aplicaciones.\"}},{\"@type\":\"Offer\",\"itemOffered\":{\"@type\":\"Service\",\"name\":\"Anal\u00edtica y reportes\",\"description\":\"Configuraci\u00f3n de medici\u00f3n y reportes de resultados por canal.\"}}]}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Calculadora de precios: cu\u00e1nto cobrar y punto de equilibrio | Vela Producciones","description":"Calcula gratis cu\u00e1nto cobrar por tu producto o tu hora: precio m\u00ednimo, precio recomendado, cu\u00e1ntas unidades necesitas para no perder y qu\u00e9 pasa si cambias tus n\u00fameros.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/velaproducciones.com\/en\/calculadora-de-precios\/","og_locale":"en_US","og_type":"article","og_title":"Calculadora de precios: cu\u00e1nto cobrar y punto de equilibrio | Vela Producciones","og_description":"Calcula gratis cu\u00e1nto cobrar por tu producto o tu hora: precio m\u00ednimo, precio recomendado, cu\u00e1ntas unidades necesitas para no perder y qu\u00e9 pasa si cambias tus n\u00fameros.","og_url":"https:\/\/velaproducciones.com\/en\/calculadora-de-precios\/","og_site_name":"Vela Producciones","article_modified_time":"2026-10-16T20:17:26+00:00","og_image":[{"width":1080,"height":1080,"url":"https:\/\/velaproducciones.com\/wp-content\/uploads\/2024\/11\/vela-producciones.png","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/velaproducciones.com\/calculadora-de-precios\/","url":"https:\/\/velaproducciones.com\/calculadora-de-precios\/","name":"Calculadora de precios: cu\u00e1nto cobrar y punto de equilibrio | Vela Producciones","isPartOf":{"@id":"https:\/\/velaproducciones.com\/#website"},"datePublished":"2026-10-10T03:20:52+00:00","dateModified":"2026-10-16T20:17:26+00:00","description":"Calcula gratis cu\u00e1nto cobrar por tu producto o tu hora: precio m\u00ednimo, precio recomendado, cu\u00e1ntas unidades necesitas para no perder y qu\u00e9 pasa si cambias tus n\u00fameros.","breadcrumb":{"@id":"https:\/\/velaproducciones.com\/calculadora-de-precios\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/velaproducciones.com\/calculadora-de-precios\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/velaproducciones.com\/calculadora-de-precios\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/velaproducciones.com\/"},{"@type":"ListItem","position":2,"name":"Calculadora de Precios"}]},{"@type":"WebSite","@id":"https:\/\/velaproducciones.com\/#website","url":"https:\/\/velaproducciones.com\/","name":"Vela Producciones","description":"Creaci\u00f3n y Manejo de P\u00e1ginas WEB, Optimizaci\u00f3n SEO y de Estrategias de Marketing Digital","publisher":{"@id":"https:\/\/velaproducciones.com\/#organization"},"alternateName":"VelaWeb","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/velaproducciones.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Organization","LocalBusiness","ProfessionalService"],"@id":"https:\/\/velaproducciones.com\/#organization","name":"Vela Producciones","alternateName":["Grupo Vela S.A.","Vela Producciones Guatemala"],"url":"https:\/\/velaproducciones.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/velaproducciones.com\/#\/schema\/logo\/image\/","url":"https:\/\/velaproducciones.com\/wp-content\/uploads\/2024\/11\/Logo_Vela_Producciones-500x500-1.png","contentUrl":"https:\/\/velaproducciones.com\/wp-content\/uploads\/2024\/11\/Logo_Vela_Producciones-500x500-1.png","width":540,"height":540,"caption":"Grupo Vela S.A."},"image":{"@id":"https:\/\/velaproducciones.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/company\/velaproducciones","https:\/\/www.instagram.com\/velawebproducciones\/","https:\/\/www.facebook.com\/VelaWebProducciones"],"legalName":"Grupo Vela S.A.","description":"Vela Producciones es la divisi\u00f3n comercial de Grupo Vela S.A. para marketing digital, producci\u00f3n audiovisual y eventos, en Ciudad de Guatemala. Estrategia, contenido, posicionamiento (SEO y visibilidad en asistentes de IA), pauta y producci\u00f3n, con medici\u00f3n.","address":{"@type":"PostalAddress","streetAddress":"Edificio 01010, oficina 702","addressLocality":"Ciudad de Guatemala","addressRegion":"Guatemala","postalCode":"01010","addressCountry":"GT"},"telephone":"+502 2220-9556","contactPoint":[{"@type":"ContactPoint","contactType":"customer service","telephone":"+502 2220-9556","areaServed":"GT","availableLanguage":["es"]},{"@type":"ContactPoint","contactType":"sales","telephone":"+1 305 447-7124","areaServed":"US","availableLanguage":["es","en"]}],"areaServed":[{"@type":"Country","name":"Guatemala"},{"@type":"Country","name":"Estados Unidos"}],"openingHoursSpecification":[{"@type":"OpeningHoursSpecification","dayOfWeek":["Monday","Tuesday","Wednesday","Thursday","Friday"],"opens":"09:00","closes":"17:00"}],"knowsAbout":["Marketing digital","Posicionamiento en buscadores (SEO)","Visibilidad en asistentes de IA (GEO y AEO)","Comercio electr\u00f3nico y WooCommerce","Redes sociales","Google Ads y Meta Ads","Producci\u00f3n audiovisual","Transmisi\u00f3n de eventos","Fotograf\u00eda comercial","Anal\u00edtica y medici\u00f3n"],"hasOfferCatalog":{"@type":"OfferCatalog","name":"Servicios de Vela Producciones","itemListElement":[{"@type":"Offer","itemOffered":{"@type":"Service","name":"Desarrollo web y ecommerce","description":"Sitios web, tiendas en l\u00ednea, optimizaci\u00f3n de velocidad y estructura t\u00e9cnica."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Posicionamiento SEO","description":"Optimizaci\u00f3n org\u00e1nica: investigaci\u00f3n de palabras clave, contenido, enlazado interno y t\u00e9cnico."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"GEO y AEO (visibilidad en asistentes de IA)","description":"Optimizaci\u00f3n para que ChatGPT, Gemini y Perplexity citen y recomienden la marca: datos estructurados, entidad consistente y medici\u00f3n."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Redes sociales","description":"Estrategia, producci\u00f3n de contenido y calendarizaci\u00f3n para Instagram, Facebook, TikTok y LinkedIn."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Campa\u00f1as SEM y pauta digital","description":"Google Ads, Meta Ads y TikTok Ads, con seguimiento de conversiones."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Producci\u00f3n de video corporativo","description":"Spots publicitarios, videos institucionales, reels y piezas narrativas para marca."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Transmisiones y cobertura de eventos","description":"Producci\u00f3n multic\u00e1mara, streaming en vivo y cobertura para eventos corporativos."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Fotograf\u00eda comercial","description":"Producto, corporativa y de eventos."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Dise\u00f1o de marca e identidad visual","description":"Logotipo, manual de marca y aplicaciones."}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Anal\u00edtica y reportes","description":"Configuraci\u00f3n de medici\u00f3n y reportes de resultados por canal."}}]}}]}},"_links":{"self":[{"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/pages\/17433","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/comments?post=17433"}],"version-history":[{"count":1,"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/pages\/17433\/revisions"}],"predecessor-version":[{"id":17434,"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/pages\/17433\/revisions\/17434"}],"wp:attachment":[{"href":"https:\/\/velaproducciones.com\/en\/wp-json\/wp\/v2\/media?parent=17433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}