562 lines
28 KiB
HTML
562 lines
28 KiB
HTML
<title>Radiografía Marmotech</title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,700&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap">
|
||
<style>
|
||
:root{
|
||
--bg:#f2efe9; --surface:#fbfaf7; --surface-2:#f5f2ea;
|
||
--ink:#231f18; --muted:#726c60; --faint:#9a9284;
|
||
--line:#e4dfd4; --line-2:#efe9dd;
|
||
--accent:#9a6a2b; --accent-soft:#e9dcc4;
|
||
--pos:#2f7d57; --neg:#b3402a; --warn:#b1832a;
|
||
--grid:#eae4d8;
|
||
--shadow:0 1px 2px rgba(40,33,20,.05),0 8px 24px -12px rgba(40,33,20,.14);
|
||
--radius:14px;
|
||
}
|
||
@media (prefers-color-scheme:dark){
|
||
:root:not([data-theme="light"]){
|
||
--bg:#17150f; --surface:#211e16; --surface-2:#26221a;
|
||
--ink:#ece6da; --muted:#a69d8c; --faint:#7c7361;
|
||
--line:#332e24; --line-2:#2b271e;
|
||
--accent:#cd9c56; --accent-soft:#3a3020;
|
||
--pos:#4fb07f; --neg:#e0674e; --warn:#d5a34a;
|
||
--grid:#2a261d;
|
||
--shadow:0 1px 2px rgba(0,0,0,.4),0 10px 30px -14px rgba(0,0,0,.6);
|
||
}
|
||
}
|
||
:root[data-theme="dark"]{
|
||
--bg:#17150f; --surface:#211e16; --surface-2:#26221a;
|
||
--ink:#ece6da; --muted:#a69d8c; --faint:#7c7361;
|
||
--line:#332e24; --line-2:#2b271e;
|
||
--accent:#cd9c56; --accent-soft:#3a3020;
|
||
--pos:#4fb07f; --neg:#e0674e; --warn:#d5a34a;
|
||
--grid:#2a261d;
|
||
--shadow:0 1px 2px rgba(0,0,0,.4),0 10px 30px -14px rgba(0,0,0,.6);
|
||
}
|
||
*{box-sizing:border-box}
|
||
html,body{margin:0}
|
||
body{
|
||
background:var(--bg); color:var(--ink);
|
||
font-family:"IBM Plex Sans",system-ui,sans-serif;
|
||
font-size:15px; line-height:1.5;
|
||
-webkit-font-smoothing:antialiased;
|
||
}
|
||
.wrap{max-width:1220px; margin:0 auto; padding:22px 20px 60px}
|
||
.num{font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1}
|
||
|
||
/* Header */
|
||
header.top{display:flex; align-items:flex-end; justify-content:space-between; gap:20px; flex-wrap:wrap; margin-bottom:6px}
|
||
.brand{display:flex; align-items:center; gap:14px}
|
||
.mark{width:44px; height:44px; flex:0 0 auto}
|
||
.brand h1{font-family:"Fraunces",serif; font-weight:600; font-size:26px; letter-spacing:-.01em; margin:0; line-height:1.05}
|
||
.brand .sub{color:var(--muted); font-size:12.5px; letter-spacing:.14em; text-transform:uppercase; margin-top:3px}
|
||
.period{text-align:right}
|
||
.period .lbl{font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--faint)}
|
||
.period .val{font-family:"Fraunces",serif; font-size:19px; font-weight:500}
|
||
.period .note{font-size:11.5px; color:var(--muted)}
|
||
|
||
.rule{height:1px; background:linear-gradient(90deg,var(--accent),var(--line) 60%,transparent); margin:16px 0 18px; opacity:.7}
|
||
|
||
/* Tabs */
|
||
nav.tabs{display:flex; gap:4px; margin-bottom:20px; border-bottom:1px solid var(--line); flex-wrap:wrap}
|
||
nav.tabs button{
|
||
appearance:none; border:0; background:none; cursor:pointer; color:var(--muted);
|
||
font-family:inherit; font-size:14px; font-weight:500; padding:10px 15px; border-radius:8px 8px 0 0;
|
||
border-bottom:2px solid transparent; margin-bottom:-1px; display:flex; align-items:center; gap:8px;
|
||
}
|
||
nav.tabs button .idx{font-family:"IBM Plex Mono",monospace; font-size:11px; color:var(--faint)}
|
||
nav.tabs button:hover{color:var(--ink); background:var(--surface-2)}
|
||
nav.tabs button[aria-selected="true"]{color:var(--ink); border-bottom-color:var(--accent)}
|
||
nav.tabs button[aria-selected="true"] .idx{color:var(--accent)}
|
||
:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
|
||
|
||
.page{display:none; animation:fade .35s ease}
|
||
.page.active{display:block}
|
||
@keyframes fade{from{opacity:0; transform:translateY(4px)}to{opacity:1; transform:none}}
|
||
@media (prefers-reduced-motion:reduce){.page,.page.active{animation:none}}
|
||
|
||
/* Cards & grid */
|
||
.grid{display:grid; gap:14px}
|
||
.kpis{grid-template-columns:repeat(4,1fr)}
|
||
.card{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow); padding:16px 17px}
|
||
.card h3{margin:0 0 2px; font-size:11.5px; letter-spacing:.13em; text-transform:uppercase; color:var(--muted); font-weight:600}
|
||
.card .cap{font-size:11.5px; color:var(--faint); margin:0 0 12px}
|
||
.kpi .k-val{font-family:"Fraunces",serif; font-weight:600; font-size:29px; letter-spacing:-.01em; line-height:1.05; margin-top:6px}
|
||
.kpi .k-val small{font-size:14px; color:var(--muted); font-weight:500; font-family:"IBM Plex Sans"}
|
||
.kpi .k-sub{display:flex; align-items:center; gap:8px; margin-top:9px; font-size:12.5px; color:var(--muted)}
|
||
.delta{display:inline-flex; align-items:center; gap:4px; font-weight:600; font-variant-numeric:tabular-nums; padding:2px 7px; border-radius:20px; font-size:12px}
|
||
.delta.up{color:var(--pos); background:color-mix(in srgb,var(--pos) 12%,transparent)}
|
||
.delta.down{color:var(--neg); background:color-mix(in srgb,var(--neg) 12%,transparent)}
|
||
.delta.flat{color:var(--warn); background:color-mix(in srgb,var(--warn) 12%,transparent)}
|
||
.accent-bar{height:3px; border-radius:3px; background:var(--accent); opacity:.9; margin:-16px -17px 14px; border-radius:var(--radius) var(--radius) 0 0}
|
||
|
||
.row{display:grid; gap:14px; margin-top:14px}
|
||
.r-8-4{grid-template-columns:1.9fr 1.1fr}
|
||
.r-6-6{grid-template-columns:1fr 1fr}
|
||
.r-7-5{grid-template-columns:1.4fr 1fr}
|
||
|
||
/* Chart bits */
|
||
svg{display:block; width:100%; height:auto; overflow:visible}
|
||
.lgd{display:flex; gap:16px; flex-wrap:wrap; font-size:12px; color:var(--muted); margin-top:10px}
|
||
.lgd span{display:inline-flex; align-items:center; gap:6px}
|
||
.dot{width:10px; height:10px; border-radius:3px; display:inline-block}
|
||
|
||
table.tbl{width:100%; border-collapse:collapse; font-size:13px}
|
||
table.tbl th{text-align:left; font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--faint); font-weight:600; padding:7px 8px; border-bottom:1px solid var(--line)}
|
||
table.tbl td{padding:8px; border-bottom:1px solid var(--line-2); font-variant-numeric:tabular-nums}
|
||
table.tbl td.r,table.tbl th.r{text-align:right}
|
||
table.tbl tr:last-child td{border-bottom:0}
|
||
.barcell{position:relative}
|
||
.barcell .fill{position:absolute; left:0; top:50%; transform:translateY(-50%); height:60%; border-radius:3px; background:var(--accent-soft)}
|
||
.barcell span{position:relative}
|
||
|
||
.ratio{display:flex; align-items:baseline; gap:10px}
|
||
.ratio .big{font-family:"Fraunces",serif; font-weight:600; font-size:34px; letter-spacing:-.02em}
|
||
.foot{color:var(--muted); font-size:12px; margin-top:26px; border-top:1px solid var(--line); padding-top:14px}
|
||
.foot code{font-family:"IBM Plex Mono",monospace; font-size:11.5px; background:var(--surface-2); padding:1px 5px; border-radius:4px}
|
||
.pill{font-size:10.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--accent); background:var(--accent-soft); padding:3px 8px; border-radius:20px; font-weight:600}
|
||
|
||
@media(max-width:880px){
|
||
.kpis{grid-template-columns:repeat(2,1fr)}
|
||
.r-8-4,.r-6-6,.r-7-5{grid-template-columns:1fr}
|
||
}
|
||
</style>
|
||
|
||
<div class="wrap">
|
||
<header class="top">
|
||
<div class="brand">
|
||
<svg class="mark" viewBox="0 0 44 44" aria-hidden="true">
|
||
<rect x="1" y="1" width="42" height="42" rx="9" fill="none" stroke="var(--accent)" stroke-width="1.5"/>
|
||
<path d="M8 30 L17 15 L23 24 L29 12 L36 30 Z" fill="none" stroke="var(--accent)" stroke-width="1.6" stroke-linejoin="round"/>
|
||
<path d="M8 33 L36 33" stroke="var(--accent)" stroke-width="1.6"/>
|
||
<circle cx="29" cy="12" r="1.8" fill="var(--accent)"/>
|
||
</svg>
|
||
<div>
|
||
<h1>Radiografía de la Empresa</h1>
|
||
<div class="sub">Marmotech, S.A. · Cuadro de Mando de Presidencia</div>
|
||
</div>
|
||
</div>
|
||
<div class="period">
|
||
<div class="lbl">Periodo</div>
|
||
<div class="val num">Enero – Julio 2026</div>
|
||
<div class="note">acumulado del año · comparado vs. 2025</div>
|
||
</div>
|
||
</header>
|
||
<div class="rule"></div>
|
||
|
||
<nav class="tabs" role="tablist">
|
||
<button role="tab" aria-selected="true" data-p="p1"><span class="idx">01</span> Radiografía</button>
|
||
<button role="tab" aria-selected="false" data-p="p2"><span class="idx">02</span> Análisis de Gastos</button>
|
||
<button role="tab" aria-selected="false" data-p="p3"><span class="idx">03</span> Estructura Financiera</button>
|
||
</nav>
|
||
|
||
<!-- ============ PÁGINA 1 ============ -->
|
||
<section class="page active" id="p1" role="tabpanel">
|
||
<div class="grid kpis">
|
||
<div class="card kpi"><div class="accent-bar"></div>
|
||
<h3>Ventas Netas</h3>
|
||
<div class="k-val num">RD$ 1,375.3<small> M</small></div>
|
||
<div class="k-sub"><span class="delta down">▼ 1.3%</span> vs. 1,393.1 M (2025)</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Utilidad Bruta</h3>
|
||
<div class="k-val num">RD$ 706.9<small> M</small></div>
|
||
<div class="k-sub"><span class="delta down">▼ 1.4 pp</span> margen 51.4% <span style="color:var(--faint)">(52.8%)</span></div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Utilidad Operativa</h3>
|
||
<div class="k-val num">RD$ 292.1<small> M</small></div>
|
||
<div class="k-sub"><span class="delta flat">21.2%</span> margen operativo</div>
|
||
</div>
|
||
<div class="card kpi"><div class="accent-bar"></div>
|
||
<h3>Utilidad Neta</h3>
|
||
<div class="k-val num">RD$ 219.6<small> M</small></div>
|
||
<div class="k-sub"><span class="delta down">▼ 21.4%</span> margen 16.0% <span style="color:var(--faint)">(20.1%)</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row r-7-5">
|
||
<div class="card">
|
||
<h3>Estado de Resultados — Cascada</h3>
|
||
<p class="cap">De ventas a utilidad neta · acumulado 2026 (RD$ millones)</p>
|
||
<svg id="waterfall" viewBox="0 0 720 300" role="img" aria-label="Cascada del estado de resultados"></svg>
|
||
</div>
|
||
<div class="card">
|
||
<h3>Composición de cada RD$ vendido</h3>
|
||
<p class="cap">Estructura del peso de ventas · 2026</p>
|
||
<svg id="composition" viewBox="0 0 360 300" role="img" aria-label="Composición de ventas"></svg>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row r-7-5">
|
||
<div class="card">
|
||
<h3>Comportamiento del periodo actual</h3>
|
||
<p class="cap">Ventas netas (barras) y utilidad neta (línea) por mes · 2026</p>
|
||
<svg id="trend" viewBox="0 0 720 280" role="img" aria-label="Tendencia mensual 2026"></svg>
|
||
<div class="lgd">
|
||
<span><i class="dot" style="background:var(--accent-soft)"></i> Ventas netas</span>
|
||
<span><i class="dot" style="background:var(--accent)"></i> Utilidad neta</span>
|
||
<span><i class="dot" style="background:var(--pos)"></i> Margen neto %</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<h3>Trayectoria anual</h3>
|
||
<p class="cap">Ventas y utilidad neta por año (RD$ M) · 2026 parcial</p>
|
||
<svg id="annual" viewBox="0 0 360 280" role="img" aria-label="Comparativo anual"></svg>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ PÁGINA 2 ============ -->
|
||
<section class="page" id="p2" role="tabpanel">
|
||
<div class="grid kpis">
|
||
<div class="card kpi"><div class="accent-bar"></div>
|
||
<h3>Gastos Operativos</h3>
|
||
<div class="k-val num">RD$ 414.7<small> M</small></div>
|
||
<div class="k-sub"><span class="delta down">▲ 7.1%</span> vs. 387.2 M (2025)</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Gasto / Ventas</h3>
|
||
<div class="k-val num">30.2<small> %</small></div>
|
||
<div class="k-sub"><span class="delta down">▲ 2.4 pp</span> vs. 27.8% (2025)</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Gerencia mayor peso</h3>
|
||
<div class="k-val" style="font-size:22px">Ventas y Mercadeo</div>
|
||
<div class="k-sub num">RD$ 184.5 M · 44% del gasto</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Mayor alza YoY</h3>
|
||
<div class="k-val" style="font-size:22px">Admin. y Materiales</div>
|
||
<div class="k-sub num"><span class="delta down">▲ 13.3%</span> +12.3 M</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row r-6-6">
|
||
<div class="card">
|
||
<h3>Gasto por gerencia</h3>
|
||
<p class="cap">2026 vs. 2025 · acumulado ene–jul (RD$ M)</p>
|
||
<svg id="ger" viewBox="0 0 380 300" role="img" aria-label="Gasto por gerencia"></svg>
|
||
<div class="lgd">
|
||
<span><i class="dot" style="background:var(--accent)"></i> 2026</span>
|
||
<span><i class="dot" style="background:var(--accent-soft)"></i> 2025</span>
|
||
</div>
|
||
</div>
|
||
<div class="card">
|
||
<h3>Naturaleza del gasto</h3>
|
||
<p class="cap">Por subgrupo contable · 2026 (RD$ M)</p>
|
||
<table class="tbl">
|
||
<thead><tr><th>Subgrupo</th><th class="r">Monto</th><th class="r">% ventas</th></tr></thead>
|
||
<tbody id="subg"></tbody>
|
||
</table>
|
||
<p class="cap" style="margin-top:12px">El subgrupo <b>76 Cierre de gastos de fabricación</b> (−325.7 M) es una absorción a costo; reduce el gasto neto operativo.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<div class="card">
|
||
<h3>Gasto mensual — control de eficiencia</h3>
|
||
<p class="cap">Gasto operativo por mes y su relación con las ventas · 2026</p>
|
||
<svg id="gtrend" viewBox="0 0 720 250" role="img" aria-label="Gasto mensual"></svg>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ PÁGINA 3 ============ -->
|
||
<section class="page" id="p3" role="tabpanel">
|
||
<div class="grid kpis">
|
||
<div class="card kpi"><div class="accent-bar"></div>
|
||
<h3>Activos Totales</h3>
|
||
<div class="k-val num">RD$ 6,435<small> M</small></div>
|
||
<div class="k-sub">al 31-jul-2026</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Razón Corriente</h3>
|
||
<div class="k-val num">2.29<small> ×</small></div>
|
||
<div class="k-sub"><span class="delta up">sólida</span> activo cte. 3,250 / pasivo cte. 1,420</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Capital de Trabajo</h3>
|
||
<div class="k-val num">RD$ 1,830<small> M</small></div>
|
||
<div class="k-sub">holgura de liquidez operativa</div>
|
||
</div>
|
||
<div class="card kpi">
|
||
<h3>Endeudamiento</h3>
|
||
<div class="k-val num">36<small> %</small></div>
|
||
<div class="k-sub"><span class="delta up">conservador</span> pasivo / activo</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row r-6-6">
|
||
<div class="card">
|
||
<h3>De dónde viene y dónde está el capital</h3>
|
||
<p class="cap">Activos = Pasivos + Patrimonio + resultado del ejercicio (RD$ M)</p>
|
||
<svg id="bal" viewBox="0 0 380 300" role="img" aria-label="Estructura del balance"></svg>
|
||
</div>
|
||
<div class="card">
|
||
<h3>Composición del activo</h3>
|
||
<p class="cap">al 31-jul-2026 (RD$ M)</p>
|
||
<table class="tbl">
|
||
<thead><tr><th>Rubro</th><th class="r">Saldo</th></tr></thead>
|
||
<tbody id="act"></tbody>
|
||
</table>
|
||
<h3 style="margin-top:18px">Composición del pasivo</h3>
|
||
<table class="tbl">
|
||
<thead><tr><th>Rubro</th><th class="r">Saldo</th></tr></thead>
|
||
<tbody id="pas"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="foot">
|
||
<span class="pill">Prototipo de diseño</span>
|
||
Vista previa del tablero de Power BI. Fuente: <code>MarmotechBI.presidencia.vwPLMensual</code>, <code>vwGastosDepto</code>, <code>vwBalanceMensual</code> —
|
||
reproduce el Mayor General Analítico (cgprrp008) y el Análisis de Gastos (cgprrp009). Cifras validadas contra el sistema al 31-jul-2026.
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function(){
|
||
var css=getComputedStyle(document.documentElement);
|
||
var C=function(n){return css.getPropertyValue(n).trim()};
|
||
function col(n){return C(n)}
|
||
var money=function(v){return v.toLocaleString('en-US',{minimumFractionDigits:1,maximumFractionDigits:1})};
|
||
|
||
/* tabs */
|
||
var btns=document.querySelectorAll('nav.tabs button');
|
||
btns.forEach(function(b){
|
||
b.addEventListener('click',function(){
|
||
btns.forEach(function(x){x.setAttribute('aria-selected','false')});
|
||
b.setAttribute('aria-selected','true');
|
||
document.querySelectorAll('.page').forEach(function(p){p.classList.remove('active')});
|
||
document.getElementById(b.dataset.p).classList.add('active');
|
||
});
|
||
});
|
||
|
||
var NS='http://www.w3.org/2000/svg';
|
||
function el(t,a){var e=document.createElementNS(NS,t);for(var k in a)e.setAttribute(k,a[k]);return e;}
|
||
function txt(x,y,s,o){o=o||{};var t=el('text',{x:x,y:y});t.textContent=s;
|
||
t.setAttribute('fill',o.fill||col('--muted'));
|
||
t.setAttribute('font-size',o.fs||11);
|
||
t.setAttribute('font-family',o.mono?'"IBM Plex Mono",monospace':'"IBM Plex Sans",sans-serif');
|
||
t.setAttribute('font-weight',o.fw||400);
|
||
if(o.anchor)t.setAttribute('text-anchor',o.anchor);
|
||
t.setAttribute('font-variant-numeric','tabular-nums');
|
||
return t;}
|
||
|
||
/* ---------- WATERFALL ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('waterfall'); if(!svg)return;
|
||
var W=720,H=300,padL=8,padR=8,base=250,top=20;
|
||
var steps=[
|
||
{l:'Ventas',v:1375.3,type:'start'},
|
||
{l:'Costo',v:-668.4,type:'neg'},
|
||
{l:'Ut. Bruta',v:706.9,type:'sub'},
|
||
{l:'Gastos',v:-414.7,type:'neg'},
|
||
{l:'Ut. Operat.',v:292.1,type:'sub'},
|
||
{l:'Otros/ISR',v:-72.5,type:'neg'},
|
||
{l:'Ut. Neta',v:219.6,type:'end'}
|
||
];
|
||
var max=1375.3, sc=(base-top)/max;
|
||
var n=steps.length, gap=14, bw=(W-padL-padR-gap*(n-1))/n;
|
||
var run=0;
|
||
steps.forEach(function(s,i){
|
||
var x=padL+i*(bw+gap), h, y, fill;
|
||
if(s.type==='start'||s.type==='sub'||s.type==='end'){
|
||
h=s.v*sc; y=base-h; run=s.v;
|
||
fill = s.type==='end'?col('--accent') : (s.type==='start'?col('--accent'):col('--ink'));
|
||
if(s.type==='sub')fill=col('--faint');
|
||
}else{
|
||
h=Math.abs(s.v)*sc; y=base-(run*sc); run=run+s.v;
|
||
fill=col('--neg');
|
||
}
|
||
svg.appendChild(el('rect',{x:x,y:y,width:bw,height:Math.max(2,h),rx:3,fill:fill,opacity:s.type==='sub'?0.5:0.92}));
|
||
svg.appendChild(txt(x+bw/2,base+16,s.l,{anchor:'middle',fs:10.5,fill:col('--muted')}));
|
||
svg.appendChild(txt(x+bw/2,y-6,(s.v>0?'':'−')+money(Math.abs(s.v)),{anchor:'middle',fs:11,mono:true,fw:600,fill:col('--ink')}));
|
||
});
|
||
})();
|
||
|
||
/* ---------- COMPOSITION (stacked bar of one peso) ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('composition'); if(!svg)return;
|
||
var parts=[
|
||
{l:'Costo de ventas',p:48.6,c:col('--neg')},
|
||
{l:'Gastos operativos',p:30.2,c:col('--warn')},
|
||
{l:'Otros / ISR',p:5.3,c:col('--faint')},
|
||
{l:'Utilidad neta',p:16.0,c:col('--pos')}
|
||
];
|
||
var x=90,y=24,w=54,H=250,total=100,sc=H/total,cy=y;
|
||
parts.forEach(function(p){
|
||
var h=p.p*sc;
|
||
svg.appendChild(el('rect',{x:x,y:cy,width:w,height:h,fill:p.c,opacity:.9}));
|
||
svg.appendChild(txt(x-10,cy+h/2+4,p.p.toFixed(1)+'%',{anchor:'end',mono:true,fs:12,fw:600,fill:col('--ink')}));
|
||
svg.appendChild(txt(x+w+10,cy+h/2+4,p.l,{fs:11.5,fill:col('--muted')}));
|
||
cy+=h;
|
||
});
|
||
svg.appendChild(txt(x+w/2,y-8,'RD$ 1.00',{anchor:'middle',fs:10,fill:col('--faint')}));
|
||
})();
|
||
|
||
/* ---------- TREND (bars + line) ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('trend'); if(!svg)return;
|
||
var data=[
|
||
{m:'Ene',v:132.4,u:2.5},{m:'Feb',v:169.9,u:7.2},{m:'Mar',v:224.8,u:56.3},
|
||
{m:'Abr',v:224.3,u:52.6},{m:'May',v:190.8,u:33.0},{m:'Jun',v:225.0,u:37.8},
|
||
{m:'Jul',v:208.1,u:30.2}
|
||
];
|
||
var W=720,base=230,top=18,padL=34,padR=12;
|
||
var max=240, sc=(base-top)/max;
|
||
[0,60,120,180,240].forEach(function(g){
|
||
var y=base-g*sc;
|
||
svg.appendChild(el('line',{x1:padL,y1:y,x2:W-padR,y2:y,stroke:col('--grid'),'stroke-width':1}));
|
||
svg.appendChild(txt(padL-6,y+3,g,{anchor:'end',fs:9.5,fill:col('--faint'),mono:true}));
|
||
});
|
||
var n=data.length, gap=18, bw=(W-padL-padR-gap*(n-1))/n;
|
||
var pts=[];
|
||
data.forEach(function(d,i){
|
||
var x=padL+i*(bw+gap);
|
||
var h=d.v*sc;
|
||
svg.appendChild(el('rect',{x:x,y:base-h,width:bw,height:h,rx:3,fill:col('--accent-soft')}));
|
||
svg.appendChild(txt(x+bw/2,base+15,d.m,{anchor:'middle',fs:10.5}));
|
||
svg.appendChild(txt(x+bw/2,base-h-6,d.v.toFixed(0),{anchor:'middle',fs:10,mono:true,fill:col('--muted')}));
|
||
pts.push([x+bw/2, base-d.u*sc]);
|
||
});
|
||
var dpath='M'+pts.map(function(p){return p[0]+','+p[1]}).join(' L');
|
||
svg.appendChild(el('path',{d:dpath,fill:'none',stroke:col('--accent'),'stroke-width':2.4,'stroke-linejoin':'round'}));
|
||
pts.forEach(function(p){svg.appendChild(el('circle',{cx:p[0],cy:p[1],r:3.4,fill:col('--surface'),stroke:col('--accent'),'stroke-width':2}));});
|
||
})();
|
||
|
||
/* ---------- ANNUAL ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('annual'); if(!svg)return;
|
||
var data=[{y:'2024',v:2401,u:462},{y:'2025',v:2401,u:457},{y:"2026*",v:1375,u:220}];
|
||
var W=360,base=230,top=18,padL=30,padR=10;
|
||
var max=2500,sc=(base-top)/max;
|
||
var n=data.length,gap=40,grp=(W-padL-padR-gap*(n-1))/n, bw=grp/2-3;
|
||
data.forEach(function(d,i){
|
||
var x=padL+i*(grp+gap);
|
||
var h1=d.v*sc,h2=d.u*sc;
|
||
svg.appendChild(el('rect',{x:x,y:base-h1,width:bw,height:h1,rx:3,fill:col('--accent-soft')}));
|
||
svg.appendChild(el('rect',{x:x+bw+6,y:base-h2,width:bw,height:h2,rx:3,fill:col('--accent')}));
|
||
svg.appendChild(txt(x+grp/2,base+15,d.y,{anchor:'middle',fs:11}));
|
||
svg.appendChild(txt(x+bw/2,base-h1-5,(d.v/1000).toFixed(2)+'k',{anchor:'middle',fs:9.5,mono:true,fill:col('--muted')}));
|
||
svg.appendChild(txt(x+bw+6+bw/2,base-h2-5,d.u,{anchor:'middle',fs:9.5,mono:true,fill:col('--muted')}));
|
||
});
|
||
svg.appendChild(txt(padL,top-4,'RD$ M',{fs:9.5,fill:col('--faint')}));
|
||
})();
|
||
|
||
/* ---------- GERENCIA (grouped horizontal) ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('ger'); if(!svg)return;
|
||
var data=[
|
||
{l:'Ventas y Mercadeo',a:184.5,b:178.3},
|
||
{l:'Admin. y Materiales',a:104.8,b:92.5},
|
||
{l:'Planta / Producción',a:78.1,b:79.9},
|
||
{l:'Gerencia General',a:41.3,b:36.4},
|
||
{l:'Planta Agregados',a:4.4,b:0},
|
||
{l:'Caribbean',a:1.6,b:0}
|
||
];
|
||
var W=380,padL=8,padR=44,top=6,rowH=46,x0=padL, maxW=W-padL-padR, max=190, sc=maxW/max;
|
||
data.forEach(function(d,i){
|
||
var y=top+i*rowH;
|
||
svg.appendChild(txt(x0,y+11,d.l,{fs:11,fw:500,fill:col('--ink')}));
|
||
svg.appendChild(el('rect',{x:x0,y:y+16,width:Math.max(2,d.a*sc),height:9,rx:2,fill:col('--accent')}));
|
||
svg.appendChild(el('rect',{x:x0,y:y+27,width:Math.max(2,d.b*sc),height:9,rx:2,fill:col('--accent-soft')}));
|
||
svg.appendChild(txt(x0+d.a*sc+6,y+24,money(d.a),{fs:10,mono:true,fill:col('--muted')}));
|
||
});
|
||
})();
|
||
|
||
/* ---------- SUBGRUPO table ---------- */
|
||
(function(){
|
||
var tb=document.getElementById('subg'); if(!tb)return;
|
||
var rows=[
|
||
['74 · Otros gastos y servicios',304.1,22.1],
|
||
['71 · Compensación empleados',293.8,21.4],
|
||
['73 · Gastos fijos',114.7,8.3],
|
||
['72 · Otros rel. a empleados',27.8,2.0],
|
||
['76 · Cierre fabricación (absorción)',-325.7,-23.7]
|
||
];
|
||
var max=310;
|
||
rows.forEach(function(r){
|
||
var tr=document.createElement('tr');
|
||
var w=Math.abs(r[1])/max*100;
|
||
tr.innerHTML='<td class="barcell"><div class="fill" style="width:'+w+'%;background:'+(r[1]<0?'color-mix(in srgb,var(--neg) 20%,transparent)':'var(--accent-soft)')+'"></div><span>'+r[0]+'</span></td>'+
|
||
'<td class="r num" style="font-weight:600;color:'+(r[1]<0?'var(--neg)':'var(--ink)')+'">'+(r[1]<0?'−':'')+money(Math.abs(r[1]))+'</td>'+
|
||
'<td class="r num" style="color:var(--muted)">'+r[2].toFixed(1)+'%</td>';
|
||
tb.appendChild(tr);
|
||
});
|
||
})();
|
||
|
||
/* ---------- GASTO TREND ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('gtrend'); if(!svg)return;
|
||
var data=[
|
||
{m:'Ene',g:55.1,r:41.6},{m:'Feb',g:54.8,r:32.2},{m:'Mar',g:59.2,r:26.3},
|
||
{m:'Abr',g:59.9,r:26.7},{m:'May',g:57.7,r:30.3},{m:'Jun',g:61.5,r:27.3},{m:'Jul',g:66.6,r:32.0}
|
||
];
|
||
var W=720,base=200,top=16,padL=34,padR=40;
|
||
var max=80,sc=(base-top)/max;
|
||
[0,20,40,60,80].forEach(function(g){var y=base-g*sc;
|
||
svg.appendChild(el('line',{x1:padL,y1:y,x2:W-padR,y2:y,stroke:col('--grid')}));
|
||
svg.appendChild(txt(padL-6,y+3,g,{anchor:'end',fs:9.5,mono:true,fill:col('--faint')}));});
|
||
var n=data.length,gap=20,bw=(W-padL-padR-gap*(n-1))/n, rpts=[];
|
||
data.forEach(function(d,i){
|
||
var x=padL+i*(bw+gap),h=d.g*sc;
|
||
svg.appendChild(el('rect',{x:x,y:base-h,width:bw,height:h,rx:3,fill:col('--accent')}));
|
||
svg.appendChild(txt(x+bw/2,base+15,d.m,{anchor:'middle',fs:10.5}));
|
||
svg.appendChild(txt(x+bw/2,base-h-5,d.g.toFixed(0),{anchor:'middle',fs:9.5,mono:true,fill:col('--muted')}));
|
||
rpts.push([x+bw/2, base-(d.r/ (80/60) )*sc]); // scale % on right (0-60 mapped)
|
||
});
|
||
// right axis % (gasto/ventas), scale 0-60 across same height
|
||
var rsc=(base-top)/60;
|
||
rpts=[];data.forEach(function(d,i){var x=padL+i*(bw+gap);rpts.push([x+bw/2, base-d.r*rsc]);});
|
||
var dp='M'+rpts.map(function(p){return p[0]+','+p[1]}).join(' L');
|
||
svg.appendChild(el('path',{d:dp,fill:'none',stroke:col('--pos'),'stroke-width':2.2,'stroke-dasharray':'1 0'}));
|
||
rpts.forEach(function(p,i){svg.appendChild(el('circle',{cx:p[0],cy:p[1],r:3,fill:col('--surface'),stroke:col('--pos'),'stroke-width':2}));
|
||
svg.appendChild(txt(p[0],p[1]-8,data[i].r.toFixed(0)+'%',{anchor:'middle',fs:9,mono:true,fill:col('--pos')}));});
|
||
svg.appendChild(txt(padL,top-4,'RD$ M',{fs:9.5,fill:col('--faint')}));
|
||
svg.appendChild(txt(W-padR+4,top+4,'% ventas',{fs:9.5,fill:col('--pos')}));
|
||
})();
|
||
|
||
/* ---------- BALANCE stacked ---------- */
|
||
(function(){
|
||
var svg=document.getElementById('bal'); if(!svg)return;
|
||
var W=380,base=250,top=20,bw=88;
|
||
var max=6435, sc=(base-top)/max;
|
||
// col 1 activos
|
||
var xA=60;
|
||
svg.appendChild(el('rect',{x:xA,y:base-6435*sc,width:bw,height:6435*sc,rx:4,fill:col('--accent'),opacity:.9}));
|
||
svg.appendChild(txt(xA+bw/2,base-6435*sc-8,'6,435',{anchor:'middle',fs:12,mono:true,fw:600,fill:col('--ink')}));
|
||
svg.appendChild(txt(xA+bw/2,base+16,'Activos',{anchor:'middle',fs:11}));
|
||
// col 2 pasivo+patrimonio+result
|
||
var xB=xA+bw+70, parts=[{l:'Pasivos',v:2322,c:col('--neg')},{l:'Patrimonio',v:3894,c:col('--pos')},{l:'Result. ejerc.',v:219,c:col('--warn')}];
|
||
var cy=base;
|
||
parts.forEach(function(p){var h=p.v*sc;cy-=h;
|
||
svg.appendChild(el('rect',{x:xB,y:cy,width:bw,height:h,fill:p.c,opacity:.85}));
|
||
svg.appendChild(txt(xB+bw+8,cy+h/2+4,p.l+' '+p.v.toLocaleString('en-US'),{fs:10.5,fill:col('--muted')}));
|
||
});
|
||
svg.appendChild(txt(xB+bw/2,base+16,'Pas. + Patrim.',{anchor:'middle',fs:11}));
|
||
})();
|
||
|
||
/* ---------- ACTIVO / PASIVO tables ---------- */
|
||
(function(){
|
||
function fill(id,rows,max){
|
||
var tb=document.getElementById(id); if(!tb)return;
|
||
rows.forEach(function(r){
|
||
var tr=document.createElement('tr');
|
||
var neg=r[1]<0;
|
||
tr.innerHTML='<td>'+r[0]+'</td><td class="r num" style="color:'+(neg?'var(--neg)':'var(--ink)')+'">'+(neg?'−':'')+Math.abs(r[1]).toLocaleString('en-US')+'</td>';
|
||
tb.appendChild(tr);
|
||
});
|
||
}
|
||
fill('act',[['Activos corrientes',3250],['Activos fijos',4140],['Depreciación acum.',-1136],['Otros activos',181],['Total activos',6435]]);
|
||
fill('pas',[['Pasivos corrientes',1420],['Préstamos largo plazo',902],['Total pasivos',2322],['Patrimonio',3894]]);
|
||
// bold totals
|
||
['act','pas'].forEach(function(id){var t=document.getElementById(id);var rs=t.querySelectorAll('tr');
|
||
rs.forEach(function(tr){if(/Total/.test(tr.textContent)){tr.style.fontWeight='700';tr.querySelectorAll('td').forEach(function(td){td.style.borderTop='1px solid var(--line)';});}});});
|
||
})();
|
||
})();
|
||
</script>
|