// app-ui.jsx — Reusable components that mirror the real AFianco app's visual language.
// Designed to be loaded as a shared <script type="text/babel" src="app-ui.jsx"> on any page.
// All components attach to window for cross-script availability.

(function() {
  const { useState, useEffect } = React;

  // ── Palette mirroring the real app ─────────────────────────────────────
  const APP_PALETTE = {
    cardMint: "oklch(0.97 0.022 160)",       // soft green tint for positive KPIs
    cardMintBorder: "oklch(0.92 0.04 160)",
    cardNeutral: "var(--bg)",
    cardCritical: "oklch(0.96 0.04 25)",     // pink/coral for Health Score critical
    cardCriticalBorder: "oklch(0.86 0.1 25)",
    deltaPos: "oklch(0.55 0.16 150)",
    deltaNeg: "oklch(0.6 0.2 25)",
    gaugeGood: "oklch(0.8 0.16 85)",         // yellow when "Buono"
    gaugeExcellent: "oklch(0.62 0.15 145)",  // green when "Eccellente"
    gaugeWarning: "oklch(0.7 0.15 50)",      // orange when "Attenzione"
    gaugeCritical: "oklch(0.6 0.2 25)",      // red when "Critico"
    barBlue: "oklch(0.55 0.19 260)",         // ricavi
    barRed: "oklch(0.65 0.21 25)",           // spese
    areaTeal: "oklch(0.65 0.13 175)",
    areaBlue: "oklch(0.62 0.17 240)",
    waterfallGreen: "oklch(0.62 0.16 150)",
    waterfallPurple: "oklch(0.58 0.15 285)",
    waterfallRed: "oklch(0.65 0.2 25)",
    waterfallOrange: "oklch(0.7 0.16 50)",
    paretoOrange: "oklch(0.7 0.17 50)",
    callout: "oklch(0.96 0.025 245)",        // light blue callout
    calloutBorder: "oklch(0.85 0.08 245)",
    calloutText: "oklch(0.45 0.15 250)",
    sidebarBg: "oklch(0.16 0.025 250)",
    sidebarBgHover: "oklch(0.22 0.028 250)",
    sidebarText: "oklch(0.7 0.012 250)",
    sidebarTextActive: "white",
    sidebarBorder: "oklch(0.24 0.028 250)",
  };

  // ── Atoms ──────────────────────────────────────────────────────────────

  function InfoIcon() {
    return (
      <svg width="13" height="13" viewBox="0 0 16 16" fill="none" style={{ display: "inline-block", verticalAlign: "middle", marginLeft: 4, opacity: 0.45 }}>
        <circle cx="8" cy="8" r="6.5" stroke="currentColor" strokeWidth="1.2" />
        <circle cx="8" cy="5" r="0.9" fill="currentColor" />
        <path d="M 8 7.5 V 11.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
      </svg>
    );
  }

  function PinIcon({ filled }) {
    return (
      <svg width="13" height="13" viewBox="0 0 16 16" fill="none" style={{ opacity: filled ? 0.85 : 0.35 }}>
        <path d="M 6.5 1.5 L 11 6 L 9.5 7.5 L 11 9 L 7 13 L 5.5 11.5 L 4 13 L 2 11 L 3.5 9.5 L 5 11 L 9 7" stroke="currentColor" strokeWidth="1.1" strokeLinejoin="round" fill={filled ? "currentColor" : "none"} transform="rotate(45 7 7)" />
      </svg>
    );
  }

  function DeltaArrow({ positive }) {
    return positive ? (
      <svg width="11" height="11" viewBox="0 0 12 12" fill="none" style={{ display: "inline-block", marginRight: 3 }}>
        <path d="M 3 9 L 9 3 M 4 3 H 9 V 8" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
      </svg>
    ) : (
      <svg width="11" height="11" viewBox="0 0 12 12" fill="none" style={{ display: "inline-block", marginRight: 3 }}>
        <path d="M 3 3 L 9 9 M 9 4 V 9 H 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
      </svg>
    );
  }

  // ── SemiCircleGauge ────────────────────────────────────────────────────
  // Half-arc score gauge. value 0-100. Returns the gauge + score number below.

  function SemiCircleGauge({ value = 75, max = 100, label, size = 200, animate = false, showScore = true }) {
    const [v, setV] = useState(animate ? 0 : value);
    useEffect(() => {
      if (!animate) { setV(value); return; }
      let cancelled = false;
      const start = Date.now();
      const tick = () => {
        if (cancelled) return;
        const p = Math.min(1, (Date.now() - start) / 1200);
        setV(value * (1 - Math.pow(1 - p, 3)));
        if (p < 1) setTimeout(tick, 16);
      };
      tick();
      return () => { cancelled = true; };
    }, [value, animate]);

    const pct = v / max;
    const color = pct >= 0.8 ? APP_PALETTE.gaugeExcellent
                : pct >= 0.6 ? APP_PALETTE.gaugeGood
                : pct >= 0.4 ? APP_PALETTE.gaugeWarning
                              : APP_PALETTE.gaugeCritical;

    // Semi-circle path
    const cx = 100, cy = 100, r = 80;
    const startAngle = Math.PI;
    const endAngle = startAngle + Math.PI * pct;
    const x2 = cx + Math.cos(endAngle) * r;
    const y2 = cy + Math.sin(endAngle) * r;
    const arcPath = `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${x2} ${y2}`;
    const fullPath = `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx + r} ${cy}`;

    return (
      <div style={{ position: "relative", width: size, height: size * 0.62 }}>
        <svg viewBox="0 0 200 130" style={{ width: size, height: size * 0.65, display: "block" }}>
          <path d={fullPath} fill="none" stroke="oklch(0.92 0.012 260)" strokeWidth="16" strokeLinecap="round" />
          {pct > 0.001 && (
            <path d={arcPath} fill="none" stroke={color} strokeWidth="16" strokeLinecap="round" />
          )}
          {/* Needle */}
          <line
            x1={cx} y1={cy}
            x2={cx + Math.cos(endAngle) * (r - 6)}
            y2={cy + Math.sin(endAngle) * (r - 6)}
            stroke="oklch(0.25 0.02 260)"
            strokeWidth="1.8"
            strokeLinecap="round"
          />
          <circle cx={cx} cy={cy} r="4" fill="oklch(0.25 0.02 260)" />
          {/* Score number rendered as SVG text so it sits exactly inside the arc */}
          {showScore && (
            <text
              x={cx}
              y={cy - 12}
              textAnchor="middle"
              style={{
                fontFamily: "var(--font-sans)",
                fontSize: 30,
                fontWeight: 700,
                letterSpacing: "-0.025em",
                fill: "var(--ink)",
              }}
            >{Math.round(v)}</text>
          )}
        </svg>
      </div>
    );
  }

  // ── MintKpiCard ────────────────────────────────────────────────────────
  // Soft green tint when positive, white when neutral, soft pink when critical

  function MintKpiCard({ label, value, delta, deltaPositive, tone = "neutral", pinned = true, info = true, compact = false, labelKey, deltaKey }) {
    const bg = tone === "positive" ? APP_PALETTE.cardMint
            : tone === "critical" ? APP_PALETTE.cardCritical
            : APP_PALETTE.cardNeutral;
    const border = tone === "positive" ? APP_PALETTE.cardMintBorder
                : tone === "critical" ? APP_PALETTE.cardCriticalBorder
                : "var(--line)";
    const valueColor = tone === "critical" ? "oklch(0.5 0.18 25)" : "var(--ink)";
    return (
      <div style={{
        background: bg,
        border: `1px solid ${border}`,
        borderRadius: 16,
        padding: compact ? "14px 16px" : "18px 22px",
        position: "relative",
      }}>
        {pinned && (
          <span style={{ position: "absolute", top: 12, right: 12, color: "var(--ink-4)" }}>
            <PinIcon />
          </span>
        )}
        <div style={{ display: "flex", alignItems: "center", color: tone === "critical" ? "oklch(0.55 0.18 25)" : "var(--ink-3)", fontSize: compact ? 12 : 13, fontWeight: 500, letterSpacing: "-0.005em" }}>
          <span data-i18n={labelKey}>{label}</span>
          {info && <span style={{ color: tone === "critical" ? "oklch(0.55 0.18 25)" : "var(--ink-4)" }}><InfoIcon /></span>}
        </div>
        <div className="kpi-value" style={{
          fontSize: compact ? 22 : 30,
          fontWeight: 700,
          letterSpacing: "-0.025em",
          color: valueColor,
          marginTop: 6,
          lineHeight: 1.1,
          whiteSpace: "nowrap",
        }}>
          {value}
        </div>
        {delta && (
          <div style={{
            marginTop: 8,
            fontSize: 12,
            color: deltaPositive ? APP_PALETTE.deltaPos : APP_PALETTE.deltaNeg,
            display: "inline-flex",
            alignItems: "center",
          }}>
            <DeltaArrow positive={deltaPositive} />
            {delta}{deltaKey ? <span> </span> : null}{deltaKey ? <span data-i18n={deltaKey}>vs anno prec.</span> : null}
          </div>
        )}
      </div>
    );
  }

  // ── DimensionBar ───────────────────────────────────────────────────────
  // "Margine Netto · ████████ · 25/25" row

  function DimensionBar({ name, value, max = 25, nameKey }) {
    const pct = value / max;
    const color = pct >= 0.8 ? APP_PALETTE.gaugeExcellent
                : pct >= 0.6 ? APP_PALETTE.gaugeGood
                : pct >= 0.4 ? APP_PALETTE.gaugeWarning
                              : APP_PALETTE.gaugeCritical;
    return (
      <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1fr) minmax(60px, 90px) 44px", gap: 10, alignItems: "center", fontSize: 12.5, minWidth: 0 }}>
        <span style={{ color: "var(--ink-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }} data-i18n={nameKey}>{name}</span>
        <div style={{ height: 7, background: "oklch(0.92 0.012 260)", borderRadius: 999, overflow: "hidden", minWidth: 0 }}>
          <div style={{ width: `${pct * 100}%`, height: "100%", background: color, borderRadius: 999, transition: "width .8s ease" }} />
        </div>
        <span className="mono" style={{ fontSize: 11.5, color: "var(--ink-3)", textAlign: "right", whiteSpace: "nowrap" }}>{value}/{max}</span>
      </div>
    );
  }

  // ── SidebarMock ────────────────────────────────────────────────────────
  // Mini sidebar like the real app — dark background, white logo, nav items

  function SidebarMock({ active = "cashflow", compact = false }) {
    const items = [
      { id: "dashboard", labelKey: "sb.dashboard", label: "Dashboard", icon: "▦" },
      { id: "cashflow",  labelKey: "sb.cashflow",  label: "Cashflow Monitor", icon: "↗" },
      { id: "ordini",    labelKey: "sb.orders",    label: "Ordini", icon: "🛒" },
      { id: "affitti",   labelKey: "sb.rentals",   label: "Affitti", icon: "▭" },
      { id: "calendar",  labelKey: "sb.calendar",  label: "Calendario", icon: "▤" },
      { id: "stores",    labelKey: "sb.stores",    label: "I miei Store", icon: "⊕" },
    ];
    const dataItems = [
      { id: "prodotti",  labelKey: "sb.products",  label: "Prodotti", icon: "▣" },
      { id: "corsi",     labelKey: "sb.courses",   label: "Corsi", icon: "▥" },
      { id: "clienti",   labelKey: "sb.customers", label: "Clienti", icon: "◉" },
      { id: "fornitori", labelKey: "sb.suppliers", label: "Fornitori", icon: "▼" },
    ];
    const aiItems = [
      { id: "moduli",    labelKey: "sb.modules",   label: "Moduli", icon: "▦" },
      { id: "anomalie",  labelKey: "sb.anomalies", label: "Anomalie", icon: "◐" },
      { id: "ai",        labelKey: "sb.ai",        label: "Analisi AI", icon: "✦" },
      { id: "qualita",   labelKey: "sb.dataquality", label: "Qualità dati", icon: "✓" },
    ];

    return (
      <aside style={{
        background: APP_PALETTE.sidebarBg,
        color: APP_PALETTE.sidebarText,
        padding: compact ? "16px 10px" : "20px 14px",
        display: "flex",
        flexDirection: "column",
        gap: 4,
        height: "100%",
      }}>
        {/* Logo */}
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 8px 18px" }}>
          <img src="/logo.svg" alt="" width="28" height="28" style={{ display: "block" }} />
          <img src="/wordmark-light.svg" alt="AFianco" style={{ height: 20, width: "auto", display: "block" }} />
        </div>

        <SideGroup items={items} active={active} />

        <div style={{
          marginTop: 16,
          padding: "8px 10px 6px",
          fontFamily: "var(--font-mono)",
          fontSize: 10,
          color: "oklch(0.5 0.012 250)",
          letterSpacing: "0.08em",
          textTransform: "uppercase",
        }} data-i18n="sb.data">Dati base</div>
        <SideGroup items={dataItems} active={active} />

        <div style={{ marginTop: 12 }}>
          <SideGroup items={aiItems} active={active} />
        </div>

        {/* User card */}
        <div style={{ marginTop: "auto", paddingTop: 16, borderTop: `1px solid ${APP_PALETTE.sidebarBorder}`, display: "flex", alignItems: "center", gap: 10, padding: "12px 8px" }}>
          <span style={{ width: 32, height: 32, borderRadius: 8, background: "oklch(0.22 0.03 260)", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "white", fontSize: 12, fontWeight: 600 }}>M</span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 12, color: "white", fontWeight: 500 }}>Marco Conti</div>
            <div className="mono" style={{ fontSize: 10, color: APP_PALETTE.sidebarText, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>demo.afianco@gmail…</div>
          </div>
          <span style={{ color: APP_PALETTE.sidebarText, fontSize: 14 }}>⤓</span>
        </div>
      </aside>
    );
  }

  function SideGroup({ items, active }) {
    return (
      <div style={{ display: "flex", flexDirection: "column", gap: 1 }}>
        {items.map(it => (
          <a key={it.id} href="#" style={{
            display: "flex", alignItems: "center", gap: 10,
            padding: "8px 10px",
            borderRadius: 6,
            background: active === it.id ? APP_PALETTE.sidebarBgHover : "transparent",
            color: active === it.id ? APP_PALETTE.sidebarTextActive : APP_PALETTE.sidebarText,
            fontSize: 13,
            fontWeight: active === it.id ? 500 : 400,
          }}>
            <span style={{ fontSize: 13, opacity: 0.7, width: 14, textAlign: "center" }}>{it.icon}</span>
            <span data-i18n={it.labelKey}>{it.label}</span>
          </a>
        ))}
      </div>
    );
  }

  // ── Charts ─────────────────────────────────────────────────────────────

  // Real-style bar chart: blue ricavi + red spese, daily, with subtle hover
  function RicaviSpeseChart({ days = 24 }) {
    // Generate semi-realistic spiky data like the real app
    const data = React.useMemo(() => {
      const arr = [];
      for (let i = 0; i < days; i++) {
        const spike = Math.random() > 0.85;
        arr.push({
          ricavi: spike ? 1800 + Math.random() * 1400 : 200 + Math.random() * 400,
          spese:  Math.random() > 0.5 ? Math.random() * 200 : 0,
        });
      }
      return arr;
    }, [days]);
    const max = Math.max(...data.map(d => Math.max(d.ricavi, d.spese))) || 1;
    return (
      <svg viewBox="0 0 600 200" style={{ width: "100%", height: 200 }} preserveAspectRatio="none">
        {/* y-axis labels */}
        {[0, 1, 2, 3].map(i => (
          <g key={i}>
            <line x1="0" y1={40 + i * 45} x2="600" y2={40 + i * 45} stroke="oklch(0.94 0.012 260)" strokeDasharray="2 3" />
          </g>
        ))}
        {data.map((d, i) => {
          const slotW = 600 / data.length;
          const x = i * slotW + slotW * 0.3;
          const w = slotW * 0.4;
          const ricaviH = (d.ricavi / max) * 175;
          const speseH = (d.spese / max) * 175;
          return (
            <g key={i}>
              <rect x={x} y={185 - ricaviH} width={w} height={ricaviH} fill={APP_PALETTE.barBlue} rx="1.5" />
              {d.spese > 0 && <rect x={x + w + 1.5} y={185 - speseH} width={w * 0.55} height={speseH} fill={APP_PALETTE.barRed} rx="1.5" />}
            </g>
          );
        })}
      </svg>
    );
  }

  // Cashflow Cumulativo area chart (light blue gradient)
  function CashflowCumulativoChart({ points }) {
    const data = points || React.useMemo(() => {
      const arr = [];
      let v = 0;
      for (let i = 0; i < 60; i++) {
        v += (Math.random() - 0.3) * 800;
        if (i > 20 && i < 25) v += 1500; // jump like real
        if (i > 40 && i < 46) v += 1800;
        arr.push(v);
      }
      return arr;
    }, []);
    const max = Math.max(...data);
    const min = Math.min(0, ...data);
    const range = max - min;
    const sx = (i) => (i / (data.length - 1)) * 600;
    const sy = (v) => 180 - ((v - min) / range) * 160;
    const linePath = data.map((v, i) => `${i === 0 ? "M" : "L"} ${sx(i)} ${sy(v)}`).join(" ");
    const areaPath = `${linePath} L ${sx(data.length - 1)} 180 L 0 180 Z`;
    return (
      <svg viewBox="0 0 600 200" style={{ width: "100%", height: 220 }} preserveAspectRatio="none">
        <defs>
          <linearGradient id="cflowGrad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={APP_PALETTE.areaBlue} stopOpacity="0.35" />
            <stop offset="100%" stopColor={APP_PALETTE.areaBlue} stopOpacity="0" />
          </linearGradient>
        </defs>
        {[0,1,2,3,4].map(i => (
          <line key={i} x1="0" y1={20 + i * 40} x2="600" y2={20 + i * 40} stroke="oklch(0.94 0.012 260)" strokeDasharray="2 3" />
        ))}
        <path d={areaPath} fill="url(#cflowGrad)" />
        <path d={linePath} fill="none" stroke={APP_PALETTE.areaBlue} strokeWidth="2" />
      </svg>
    );
  }

  // Risultato Giornaliero teal line chart
  function RisultatoChart() {
    const data = React.useMemo(() => {
      const arr = [];
      for (let i = 0; i < 60; i++) {
        const base = 200 + Math.sin(i / 4) * 150 + (Math.random() - 0.5) * 400;
        arr.push(base + (Math.random() > 0.9 ? 1500 : 0));
      }
      return arr;
    }, []);
    const max = Math.max(...data);
    const min = Math.min(0, ...data);
    const range = max - min;
    const sx = (i) => (i / (data.length - 1)) * 600;
    const sy = (v) => 180 - ((v - min) / range) * 160;
    const linePath = data.map((v, i) => `${i === 0 ? "M" : "L"} ${sx(i)} ${sy(v)}`).join(" ");
    return (
      <svg viewBox="0 0 600 200" style={{ width: "100%", height: 200 }} preserveAspectRatio="none">
        {[0,1,2,3,4].map(i => (
          <line key={i} x1="0" y1={20 + i * 40} x2="600" y2={20 + i * 40} stroke="oklch(0.94 0.012 260)" strokeDasharray="2 3" />
        ))}
        <line x1="0" y1={sy(0)} x2="600" y2={sy(0)} stroke="oklch(0.85 0.012 260)" strokeWidth="0.8" />
        <path d={linePath} fill="none" stroke={APP_PALETTE.areaTeal} strokeWidth="2" />
      </svg>
    );
  }

  // ── Waterfall: Fatturato → Risultato Netto ─────────────────────────────
  function WaterfallChart({ steps }) {
    const items = steps || [
      { label: "Fatturato",         value: 41055,  pct: 100, color: APP_PALETTE.waterfallGreen },
      { label: "Costi Fissi",       value: -10317, pct: 25,  color: APP_PALETTE.waterfallPurple },
      { label: "Spese Operative",   value: -7763,  pct: 19,  color: APP_PALETTE.waterfallRed },
      { label: "Acquisti Fornitori",value: -6286,  pct: 15,  color: APP_PALETTE.waterfallOrange },
      { label: "Risultato Netto",   value: 16690,  pct: 41,  color: APP_PALETTE.waterfallGreen, divider: true },
    ];
    const fmt = (v) => (v > 0 ? "+" : "") + v.toLocaleString("it-IT") + " €";
    return (
      <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        {items.map((it, i) => (
          <React.Fragment key={i}>
            {it.divider && <div style={{ height: 1, background: "var(--line)", margin: "4px 0" }} />}
            <div style={{ display: "grid", gridTemplateColumns: "minmax(110px, 0.5fr) 1.5fr minmax(90px, auto)", gap: 16, alignItems: "center" }}>
              <div style={{ fontSize: 13.5, color: "var(--ink-2)", fontWeight: 500, textAlign: "right" }}>{it.label}</div>
              <div style={{ height: 26, background: `color-mix(in oklab, ${it.color} 14%, transparent)`, borderRadius: 6, position: "relative", overflow: "hidden" }}>
                <div style={{ position: "absolute", left: 0, top: 0, height: "100%", width: `${it.pct}%`, background: it.color, borderRadius: 6 }} />
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="mono" style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>{fmt(it.value)}</div>
                <div className="mono" style={{ fontSize: 11, color: "var(--ink-4)" }}>{it.pct}%</div>
              </div>
            </div>
          </React.Fragment>
        ))}
      </div>
    );
  }

  // ── Pareto Fornitori: orange bars + blue cumulative line ───────────────
  function ParetoChart() {
    const data = [
      { name: "Apple Store",     v: 5200, cum: 75 },
      { name: "Logitech Store",  v: 450, cum: 82 },
      { name: "Amazon Business", v: 380, cum: 88 },
      { name: "Hoepli",          v: 320, cum: 93 },
      { name: "Vistaprint",      v: 280, cum: 97 },
      { name: "Rode IT",         v: 220, cum: 100 },
    ];
    const max = Math.max(...data.map(d => d.v));
    const w = 500, h = 200;
    return (
      <svg viewBox={`0 0 ${w} ${h + 40}`} style={{ width: "100%", height: 240 }}>
        {[0,1,2,3,4].map(i => (
          <line key={i} x1="0" y1={40 + i * 40} x2={w} y2={40 + i * 40} stroke="oklch(0.94 0.012 260)" strokeDasharray="2 3" />
        ))}
        {data.map((d, i) => {
          const slot = w / data.length;
          const barW = slot * 0.5;
          const x = i * slot + slot * 0.25;
          const barH = (d.v / max) * 160;
          return (
            <g key={i}>
              <rect x={x} y={200 - barH} width={barW} height={barH} fill={APP_PALETTE.paretoOrange} rx="2" />
              <text x={x + barW / 2} y={h + 20} textAnchor="middle" fontSize="9" fill="var(--ink-4)" fontFamily="var(--font-mono)">{d.name.length > 12 ? d.name.slice(0, 10) + "…" : d.name}</text>
            </g>
          );
        })}
        {/* cumulative line */}
        <polyline
          points={data.map((d, i) => {
            const slot = w / data.length;
            const x = i * slot + slot * 0.5;
            const y = 40 + (1 - d.cum / 100) * 160;
            return `${x},${y}`;
          }).join(" ")}
          fill="none"
          stroke={APP_PALETTE.barBlue}
          strokeWidth="2"
        />
        {data.map((d, i) => {
          const slot = w / data.length;
          const x = i * slot + slot * 0.5;
          const y = 40 + (1 - d.cum / 100) * 160;
          return <circle key={i} cx={x} cy={y} r="3" fill={APP_PALETTE.barBlue} />;
        })}
      </svg>
    );
  }

  // ── Digest section label ────────────────────────────────────────────────
  function DigestSection({ icon, children }) {
    return (
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 24, marginBottom: 12 }}>
        <span style={{
          width: 24, height: 24,
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          color: APP_PALETTE.calloutText,
          fontSize: 14,
        }}>{icon}</span>
        <span className="mono" style={{ fontSize: 12, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-2)" }}>{children}</span>
      </div>
    );
  }

  // Soft blue callout (used for "EMERGENZA LIQUIDITÀ" etc.)
  function DigestCallout({ children, tone = "info" }) {
    const bg = tone === "warning" ? "oklch(0.97 0.04 70)" : APP_PALETTE.callout;
    const border = tone === "warning" ? "oklch(0.82 0.1 70)" : APP_PALETTE.calloutBorder;
    const color = tone === "warning" ? "oklch(0.45 0.12 70)" : APP_PALETTE.calloutText;
    return (
      <div style={{
        padding: "12px 14px",
        background: bg,
        border: `1px solid ${border}`,
        borderRadius: 8,
        fontSize: 13.5,
        color,
        display: "flex",
        gap: 10,
        margin: "12px 0",
      }}>
        <span style={{ fontSize: 16, lineHeight: 1 }}>ⓘ</span>
        <span style={{ lineHeight: 1.5 }}>{children}</span>
      </div>
    );
  }

  // Helpers: highlight bold + color spans in digest text
  // bold and color helpers
  function HL({ children, tone }) {
    const color = tone === "neg" ? APP_PALETTE.deltaNeg
                : tone === "pos" ? APP_PALETTE.deltaPos
                : "var(--ink)";
    return <strong style={{ color }}>{children}</strong>;
  }

  Object.assign(window, {
    APP_PALETTE,
    InfoIcon, PinIcon, DeltaArrow,
    SemiCircleGauge, MintKpiCard, DimensionBar,
    SidebarMock,
    RicaviSpeseChart, CashflowCumulativoChart, RisultatoChart,
    WaterfallChart, ParetoChart,
    DigestSection, DigestCallout, HL,
  });
})();
