// ───────────────────────────────────────────────────────────
// LIBRETA LIBERTARIA · shell + calculadora ("lo que nos roban").
// Derivado de la app original "Menos Estado". Envuelto en IIFE para
// aislar su scope del tracker (que también declara useState, etc.).
// Expone las primitivas a window para que las usen las guías.
// ───────────────────────────────────────────────────────────
;(function () {
const { useState, useMemo, useEffect, useRef } = React;
const TC = window.TaxCalc;
const calculate = TC.calculate;
const calculateEffective = TC.calculateEffective;
const REGION_LIST = TC.REGIONS;
const fmtEur = TC.fmtEur;
const fmtEur2 = TC.fmtEur2;
const fmtPct = TC.fmtPct;

// ─── Animated number counter ────────────────────────────────
function AnimatedNumber({ value, formatter = fmtEur, duration = 500 }) {
  const [display, setDisplay] = useState(value);
  const fromRef = useRef(value);
  const startRef = useRef(0);
  const rafRef = useRef(0);

  useEffect(() => {
    cancelAnimationFrame(rafRef.current);
    const from = fromRef.current;
    const to = value;
    const start = performance.now();
    startRef.current = start;
    function step(now) {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      const v = from + (to - from) * eased;
      setDisplay(v);
      if (t < 1) rafRef.current = requestAnimationFrame(step);else
      fromRef.current = to;
    }
    rafRef.current = requestAnimationFrame(step);
    return () => cancelAnimationFrame(rafRef.current);
  }, [value, duration]);

  return <>{formatter(display)}</>;
}

// ─── Field primitives ───────────────────────────────────────
function NumberField({ label, value, onChange, suffix, hint, big = false, accent = false, min = 0, max = 9999999, step = 100 }) {
  const [raw, setRaw] = useState(String(value));
  const focused = useRef(false);

  useEffect(() => {
    if (!focused.current) setRaw(String(value));
  }, [value]);

  return (
    <div className="field">
      <label>{label}</label>
      <div className={`control${accent ? ' accent' : ''}`}>
        <input
          type="number"
          className={`numerals${big ? ' big' : ''}`}
          value={raw}
          min={min}
          max={max}
          step={step}
          onChange={(e) => setRaw(e.target.value)}
          onFocus={() => { focused.current = true; }}
          onBlur={(e) => {
            focused.current = false;
            const n = e.target.value === '' ? min : Math.max(min, Math.min(max, +e.target.value || min));
            onChange(n);
            setRaw(String(n));
          }} />
        {suffix && <span className="suffix">{suffix}</span>}
      </div>
      {hint && <div className="hint">{hint}</div>}
    </div>);

}

function SelectField({ label, value, onChange, options, hint }) {
  return (
    <div className="field">
      <label>{label}</label>
      <div className="control">
        <select value={value} onChange={(e) => onChange(e.target.value)}>
          {options.map((o) => <option key={o.id} value={o.id}>{o.label}</option>)}
        </select>
        <span className="chev">▾</span>
      </div>
      {hint && <div className="hint">{hint}</div>}
    </div>);

}

function Segmented({ value, onChange, options }) {
  return (
    <div className="seg" role="tablist">
      {options.map((o) =>
      <button
        key={o.id}
        role="tab"
        aria-selected={value === o.id}
        className={value === o.id ? 'on' : ''}
        onClick={() => onChange(o.id)}>
        {o.label}</button>
      )}
    </div>);

}

// ─── Slider ─────────────────────────────────────────────────
function SliderField({ label, value, onChange, min = 0, max = 100, step = 1, format, suggested }) {
  const fmt = format || ((v) => v);
  return (
    <div className="slider-field">
      <div className="head">
        <span className="label">{label}</span>
        <span className="val numerals">{fmt(value)}</span>
      </div>
      <input
        type="range"
        min={min} max={max} step={step}
        value={value}
        onChange={(e) => onChange(+e.target.value)} />
      
      {suggested != null && Math.abs(suggested - value) > 0.001 &&
      <div className="head" style={{ marginTop: -4 }}>
          <span className="suggested">Sugerido por tu nivel de ingresos: {fmt(suggested)}</span>
          <button className="btn ghost" style={{ padding: '2px 8px', fontSize: 11 }} onClick={() => onChange(suggested)}>Usar sugerido</button>
        </div>
      }
    </div>);

}

// ─── Toggle row ─────────────────────────────────────────────
function ToggleRow({ on, onChange, text, sub }) {
  return (
    <div className={`toggle-row${on ? ' on' : ''}`} onClick={() => onChange(!on)} role="switch" aria-checked={on}>
      <div>
        <div className="text">{text}</div>
        {sub && <div className="sub">{sub}</div>}
      </div>
      <div className="sw"></div>
    </div>);

}

// ─── Calculadora · "Lo que nos roban" ───────────────────────
// (Antes el bloque "comparativa" de la app original; ahora una sección
//  que monta la shell de Libreta Libertaria.)
const MEDIAN_TAX_PROFILE = Object.freeze({
  employmentType: 'asalariado',
  gross: 24500,
  payments: 14,
  region: 'andalucia',
  age: 45,
  contractType: 'indefinido',
  children: 0,
  childrenUnder3: 0,
  childShare: 0.5,
  pension: 0,
  disability: 'none',
  businessExpenses: 0,
  autonomoNetMonthly: 1500,
  autonomoBase: 0,
  monthsActive: 12,
  simplifiedEstimation: true
});

const MEDIAN_LIFESTYLE_PROFILE = Object.freeze({
  enabled: true,
  spendRate: null,
  ownsHome: true,
  homeValue: 150000
});

function CalculadoraSection() {
  const [input, setInput] = useState(() => ({ ...MEDIAN_TAX_PROFILE }));
  const [lifestyle, setLifestyle] = useState(() => ({ ...MEDIAN_LIFESTYLE_PROFILE }));

  const set = (k, v) => setInput((s) => ({ ...s, [k]: v }));
  const setL = (k, v) => setLifestyle((s) => ({ ...s, [k]: v }));
  const restoreMedianProfile = () => {
    setInput({ ...MEDIAN_TAX_PROFILE });
    setLifestyle({ ...MEDIAN_LIFESTYLE_PROFILE });
  };

  const result = useMemo(() => calculate(input), [input]);
  const effective = useMemo(() => {
    if (!lifestyle.enabled) {
      // "Pass-through": effective = net, no extra subtractions
      const net = result.net || 0;
      const gross = result.gross || 0;
      return {
        spendRate: 0, suggestedSpendRate: TC.suggestedSpendRate ? TC.suggestedSpendRate(net) : 0,
        spending: 0, vat: 0, ibi: 0, patrimonio: 0,
        consumption: 0, property: 0,
        totalExtra: 0, effective: net, effectiveMonthly: net / 12,
        totalTaxes: (result.irpf || 0) + (result.ss || 0),
        totalRate: result.totalRate || 0,
        totalWealth: 0, taxableWealth: 0, wealthBonif: 0
      };
    }
    const ls = { ...lifestyle };
    if (ls.spendRate == null) ls.spendRate = undefined;
    return calculateEffective(result, ls, input.region);
  }, [result, lifestyle, input.region]);

  // Currently-applied spend rate (numeric, after default substitution)
  const activeSpendRate = effective.spendRate || (TC.suggestedSpendRate ? TC.suggestedSpendRate(result.net) : 0.8);
  const suggestedSR = effective.suggestedSpendRate;

  // Percentages for the breakdown bar (guard against zero gross)
  const g = input.gross > 0 ? input.gross : 1;
  const pctEffective = Math.max(0, effective.effective / g * 100);
  const pctVat = Math.max(0, effective.vat / g * 100);
  const pctProp = Math.max(0, effective.property / g * 100);
  const pctIrpf = Math.max(0, result.irpf / g * 100);
  const pctSs = Math.max(0, result.ss / g * 100);

  const isAuto = input.employmentType === 'autonomo';
  const ssLabel = isAuto ? 'Cuota Autónomos' : 'Seguridad Social';
  const [showIrpfDetail, setShowIrpfDetail] = useState(false);

  return (
    <div id="comparativa" className="shell ll-tool-page">
        {/* HERO */}
        <section className="hero">
          <span className="eyebrow">herramienta · lo que nos roban · España · 2026</span>
          <h1>Lo que nos <mark>roban</mark>. Haz los números.</h1>
          <p>Tu salario bruto es una tarta de la que el Estado va cortando porciones hasta dejarte el neto —y sigue cortando cuando lo gastas o lo ahorras. Introduce tu situación y descubre cuánto pagas de verdad al año, a qué va cada gajo y cuánto te quedaría con un Estado mínimo.</p>
        </section>

        {/* CALCULATOR */}
        <section className="calc" id="calc">
          {/* LEFT — FORM */}
          <div>
            <div className="card">
              <div className="section-label"><span className="num">1</span>Situación base</div>
              <div className="defaults-note">
                <span>Valores iniciales: perfil mediano o más frecuente en España.</span>
                <button type="button" onClick={restoreMedianProfile}>Restaurar perfil</button>
              </div>
              <Segmented
                value={input.employmentType}
                onChange={(v) => set('employmentType', v)}
                options={[
                { id: 'asalariado', label: 'Asalariado' },
                { id: 'autonomo', label: 'Autónomo' }]
                } />
              

              <div style={{ height: 18 }}></div>

              <div className="grid-3-2">
                <NumberField
                  label={isAuto ? 'Ingresos brutos anuales' : 'Salario bruto anual'}
                  value={input.gross}
                  onChange={(v) => set('gross', v)}
                  suffix="€"
                  big accent
                  step={500}
                  hint={!isAuto ? 'Mediana salarial INE 2024, redondeada' : 'Sustitúyelo por tu facturación real'} />
                
                <SelectField
                  label="Nº de pagas"
                  value={String(input.payments)}
                  onChange={(v) => set('payments', +v)}
                  options={[
                  { id: '12', label: '12 pagas' },
                  { id: '14', label: '14 pagas' }]
                  }
                  hint={isAuto ? 'No aplica a autónomos' : null} />
                
              </div>

              <div style={{ height: 14 }}></div>

              <div className="grid-2">
                <SelectField
                  label="Comunidad autónoma"
                  value={input.region}
                  onChange={(v) => set('region', v)}
                  options={REGION_LIST}
                  hint="Andalucía es la comunidad más poblada de las incluidas" />
                
                <NumberField
                  label="Edad"
                  value={input.age}
                  onChange={(v) => set('age', v)}
                  min={18} max={100} step={1}
                  hint="Media nacional redondeada" />
                
              </div>

              <div style={{ height: 14 }}></div>

              <div className="grid-2">
                <NumberField
                  label="Descendientes con derecho a mínimo"
                  value={input.children}
                  onChange={(v) => set('children', v)}
                  min={0} max={10} step={1} />

                <SelectField
                  label="Parte del mínimo que te corresponde"
                  value={String(input.childShare)}
                  onChange={(v) => set('childShare', +v)}
                  options={[
                    { id: '0.5', label: '50% · compartido' },
                    { id: '1', label: '100% · exclusivo' }
                  ]} />
              </div>

              {input.children > 0 && <>
                <div style={{ height: 14 }}></div>
                <NumberField
                  label="De ellos, menores de 3 años"
                  value={input.childrenUnder3}
                  onChange={(v) => set('childrenUnder3', Math.min(v, input.children))}
                  min={0} max={input.children} step={1} />
              </>}

              <div style={{ height: 14 }}></div>
              {!isAuto ?
                <SelectField
                  label="Tipo de contrato"
                  value={input.contractType}
                  onChange={(v) => set('contractType', v)}
                  options={[
                    { id: 'indefinido', label: 'Indefinido' },
                    { id: 'temporal', label: 'Temporal' }
                  ]} /> :
                <div style={{ display: 'grid', gap: 14 }}>
                  <div className="grid-2">
                    <NumberField
                      label="Gastos deducibles anuales"
                      value={input.businessExpenses}
                      onChange={(v) => set('businessExpenses', v)}
                      suffix="€/año" step={500} />
                    <NumberField
                      label="Meses de alta"
                      value={input.monthsActive}
                      onChange={(v) => set('monthsActive', v)}
                      min={1} max={12} step={1} />
                  </div>
                  <div className="grid-2">
                    <NumberField
                      label="Rendimiento neto mensual RETA"
                      value={input.autonomoNetMonthly}
                      onChange={(v) => set('autonomoNetMonthly', v)}
                      suffix="€/mes" step={100}
                      hint="El comunicado a la Seguridad Social" />
                    <NumberField
                      label="Base de cotización elegida"
                      value={input.autonomoBase}
                      onChange={(v) => set('autonomoBase', v)}
                      suffix="€/mes" step={50}
                      hint="0 = base mínima de tu tramo" />
                  </div>
                  <ToggleRow
                    on={input.simplifiedEstimation}
                    onChange={(v) => set('simplifiedEstimation', v)}
                    text="Estimación directa simplificada"
                    sub="Aplica el 7% de gastos de difícil justificación, máximo 2.000 €" />
                </div>
              }
            </div>

            <div className="card">
              <details className="advanced" open>
                <summary>
                  <span><span className="section-label" style={{ margin: 0, display: 'inline-flex' }}><span className="num">2</span>Deducciones (opcional)</span></span>
                  <span className="caret">›</span>
                </summary>
                <div>
                  <div className="grid-2">
                    <NumberField
                      label="Aportación a plan de pensiones"
                      value={input.pension}
                      onChange={(v) => set('pension', v)}
                      suffix="€/año"
                      hint="Máx. deducible: 1.500 €/año"
                      step={100} max={1500} />
                    
                    <SelectField
                      label="Discapacidad"
                      value={input.disability}
                      onChange={(v) => set('disability', v)}
                      options={[
                      { id: 'none', label: 'Ninguna' },
                      { id: 'mild', label: '33 – 65%' },
                      { id: 'severe', label: 'Superior al 65%' }]
                      } />
                    
                  </div>
                </div>
              </details>
            </div>

            <div className="card">
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, marginBottom: lifestyle.enabled ? 18 : 0 }}>
                <div>
                  <div className="section-label" style={{ margin: 0 }}><span className="num">3</span>Estimaciones de consumo y vivienda</div>
                  <div style={{ fontSize: 12, color: 'var(--mute)', marginTop: 6, maxWidth: 420 }}>
                    {lifestyle.enabled ?
                    'IVA e IBI son aproximaciones separadas, no liquidaciones personales.' :
                    'Activa para estimar IVA e IBI. El Impuesto sobre el Patrimonio no se incluye porque requiere más datos.'}
                  </div>
                </div>
                <div
                  className={`mini-switch${lifestyle.enabled ? ' on' : ''}`}
                  onClick={() => setL('enabled', !lifestyle.enabled)}
                  role="switch" aria-checked={lifestyle.enabled}>
                  
                  <span className="dot"></span>
                </div>
              </div>

              {lifestyle.enabled &&
              <div style={{ display: 'grid', gap: 14 }}>
                  <SliderField
                  label="Porcentaje del neto que gastas al año"
                  value={Math.round(activeSpendRate * 100)}
                  onChange={(v) => setL('spendRate', v / 100)}
                  min={20} max={100} step={1}
                  format={(v) => `${v} %`}
                  suggested={Math.round(suggestedSR * 100)} />
                

                  <ToggleRow
                  on={lifestyle.ownsHome}
                  onChange={(v) => setL('ownsHome', v)}
                  text="Tengo vivienda en propiedad"
                  sub="El IBI se estima sobre el valor de mercado; el real depende del valor catastral y municipio" />
                

                  {lifestyle.ownsHome &&
                <div>
                      <NumberField
                    label="Valor de mercado vivienda"
                    value={lifestyle.homeValue}
                    onChange={(v) => setL('homeValue', v)}
                    suffix="€" step={5000}
                    hint="Mediana entre hogares propietarios (EFF 2022)" />
                    </div>
                }
                </div>
              }
            </div>

            <div className="disclaimer">
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5">
                <circle cx="8" cy="8" r="6.5" />
                <path d="M8 5v3.5M8 11h.01" strokeLinecap="round" />
              </svg>
              <span>IRPF con las últimas escalas completas publicadas (Renta 2025) y cotizaciones 2026. Declaración individual, territorio común y sin deducciones autonómicas. IVA e IBI son estimaciones. No sustituye a Renta WEB.</span>
            </div>
          </div>

          {/* RIGHT — RESULT */}
          <div>
            <div className="result-card">
              <div className="stamp">
                <span>{lifestyle.enabled ? 'efectivo anual' : 'neto anual'} · {2026}</span>
                <span>{REGION_LIST.find((r) => r.id === input.region)?.label}</span>
              </div>
              <div className="big">
                <span className="numerals"><AnimatedNumber value={lifestyle.enabled ? effective.effective : result.net} formatter={fmtEur} /></span>
                <span className="cur">/ año</span>
              </div>
              <div className="sub">
                <span><strong className="numerals">{fmtEur(lifestyle.enabled ? effective.effectiveMonthly : result.monthly)}</strong> al mes</span>
                {!isAuto &&
                <span><strong className="numerals">{fmtEur(result.perPayment)}</strong> por paga {input.payments === 14 && '(×14)'}</span>
                }
                <span>Tipo efectivo: <strong className="numerals">{fmtPct(input.gross > 0 ? (result.irpf + result.ss) / input.gross : 0)}</strong></span>
                {lifestyle.enabled &&
                <span>Con estilo de vida: <strong className="numerals">{fmtPct(effective.totalRate)}</strong></span>
                }
              </div>
              {lifestyle.enabled &&
              <div className="secondary">
                  <div className="row">
                    <span>Neto</span>
                    <span className="v"><AnimatedNumber value={result.net} formatter={fmtEur} /> <span style={{ color: 'oklch(0.7 0.04 88)' }}>/ {fmtEur(result.monthly)} mes</span></span>
                  </div>
                  <div className="row">
                    <span>− IVA</span>
                    <span className="v">−<AnimatedNumber value={effective.vat} formatter={fmtEur} /></span>
                  </div>
                  <div className="row">
                    <span>− IBI estimado</span>
                    <span className="v">−<AnimatedNumber value={effective.property} formatter={fmtEur} /></span>
                  </div>
                </div>
              }
            </div>

            <div className="card">
              <div className="section-label">
                <span className="num">4</span>Desglose{lifestyle.enabled ? ' completo' : ''}
              </div>

              <div className="bar" aria-hidden>
                {lifestyle.enabled ?
                <>
                    <div className="seg-bar effective" style={{ width: `${pctEffective}%` }}>{pctEffective >= 10 ? `${pctEffective.toFixed(0)}%` : ''}</div>
                    <div className="seg-bar vat" style={{ width: `${pctVat}%` }}>{pctVat >= 6 ? `${pctVat.toFixed(0)}%` : ''}</div>
                    <div className="seg-bar property" style={{ width: `${pctProp}%` }}>{pctProp >= 4 ? `${pctProp.toFixed(0)}%` : ''}</div>
                    <div className="seg-bar irpf" style={{ width: `${pctIrpf}%` }}>{pctIrpf >= 6 ? `${pctIrpf.toFixed(0)}%` : ''}</div>
                    <div className="seg-bar ss" style={{ width: `${pctSs}%` }}>{pctSs >= 5 ? `${pctSs.toFixed(0)}%` : ''}</div>
                  </> :

                <>
                    <div className="seg-bar net" style={{ width: `${100 - pctIrpf - pctSs}%` }}>{100 - pctIrpf - pctSs >= 10 ? `${(100 - pctIrpf - pctSs).toFixed(0)}%` : ''}</div>
                    <div className="seg-bar irpf" style={{ width: `${pctIrpf}%` }}>{pctIrpf >= 6 ? `${pctIrpf.toFixed(0)}%` : ''}</div>
                    <div className="seg-bar ss" style={{ width: `${pctSs}%` }}>{pctSs >= 5 ? `${pctSs.toFixed(0)}%` : ''}</div>
                  </>
                }
              </div>

              <div className="legend">
                {lifestyle.enabled ?
                <>
                    <div className="item"><span className="sw" style={{ background: 'var(--hi)' }}></span>Efectivo</div>
                    <div className="item"><span className="sw" style={{ background: 'oklch(0.78 0.10 75)' }}></span>IVA</div>
                    <div className="item"><span className="sw" style={{ background: 'oklch(0.55 0.08 50)' }}></span>IBI estimado</div>
                    <div className="item"><span className="sw" style={{ background: 'var(--ink)' }}></span>IRPF</div>
                    <div className="item"><span className="sw" style={{ background: 'var(--mute)' }}></span>{ssLabel}</div>
                  </> :

                <>
                    <div className="item"><span className="sw" style={{ background: 'var(--hi)' }}></span>Neto</div>
                    <div className="item"><span className="sw" style={{ background: 'var(--ink)' }}></span>IRPF</div>
                    <div className="item"><span className="sw" style={{ background: 'var(--mute)' }}></span>{ssLabel}</div>
                  </>
                }
              </div>

              <div className="detail-table">
                <div className="row">
                  <span className="label">Bruto Anual</span>
                  <span><AnimatedNumber value={input.gross} formatter={fmtEur} /></span>
                </div>
                <div className="row">
                  <span className="label">– {ssLabel}</span>
                  <span>−<AnimatedNumber value={result.ss} formatter={fmtEur} /></span>
                </div>
                <div className="row">
                  <span className="label">– IRPF</span>
                  <span>−<AnimatedNumber value={result.irpf} formatter={fmtEur} /></span>
                </div>
                <div className={`row${lifestyle.enabled ? ' subtotal' : ' total'}`}>
                  <span className="label">= Neto Anual</span>
                  <span><AnimatedNumber value={result.net} formatter={fmtEur} /></span>
                </div>
                {lifestyle.enabled &&
                <>
                    <div className="row">
                      <span className="label">– IVA (sobre <AnimatedNumber value={effective.spending} formatter={fmtEur} /> gastados)</span>
                      <span>−<AnimatedNumber value={effective.vat} formatter={fmtEur} /></span>
                    </div>
                    <div className="row">
                      <span className="label">– IBI</span>
                      <span>−<AnimatedNumber value={effective.ibi} formatter={fmtEur} /></span>
                    </div>
                    <div className="row total">
                      <span className="label">= Efectivo anual</span>
                      <span><AnimatedNumber value={effective.effective} formatter={fmtEur} /></span>
                    </div>
                  </>
                }
              </div>

              <button
                className={`irpf-toggle${showIrpfDetail ? ' open' : ''}`}
                onClick={() => setShowIrpfDetail((s) => !s)}>
                Detalle del cálculo del IRPF
                <svg className="irpf-caret" width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
                  <path d="M2.5 1.5L7.5 5L2.5 8.5" />
                </svg>
              </button>

              {showIrpfDetail &&
              <div className="irpf-detail">
                  <div className="irpf-profile">
                    <span className="tag">{input.age} años</span>
                    <span className="tag">{REGION_LIST.find((r) => r.id === input.region)?.label}</span>
                    {input.children > 0 && <span className="tag">{input.children} {input.children === 1 ? 'descendiente' : 'descendientes'} · {Math.round(input.childShare * 100)}%</span>}
                    {input.pension > 0 && <span className="tag">Pensión: {fmtEur(isAuto ? result.pensionDed : result.pensionCap)}</span>}
                    {input.disability !== 'none' && <span className="tag">{input.disability === 'mild' ? 'Discap. ≥33%' : 'Discap. ≥65%'}</span>}
                  </div>

                  <div className="irpf-calc">
                    {isAuto ?
                    <>
                        <div className="c-row">
                          <span className="l">Ingresos brutos</span>
                          <span><AnimatedNumber value={result.gross} /></span>
                        </div>
                        <div className="c-row">
                          <span className="l">– Gastos deducibles declarados</span>
                          <span>−<AnimatedNumber value={result.businessExpenses} /></span>
                        </div>
                        <div className="c-row">
                          <span className="l">– Cuota autónomos ({fmtEur(result.contributionBase)} base · {result.monthsActive} meses)</span>
                          <span>−<AnimatedNumber value={result.ss} /></span>
                        </div>
                        {result.forfait > 0 && <div className="c-row">
                          <span className="l">– Deducción forfait (7%, máx. 2.000 €)</span>
                          <span>−<AnimatedNumber value={result.forfait} /></span>
                        </div>}
                        {result.pensionDed > 0 &&
                        <div className="c-row">
                            <span className="l">– Planes de pensión</span>
                            <span>−<AnimatedNumber value={result.pensionDed} /></span>
                          </div>
                        }
                      </> :

                    <>
                        <div className="c-row">
                          <span className="l">Rendimiento íntegro</span>
                          <span><AnimatedNumber value={result.gross} /></span>
                        </div>
                        <div className="c-row">
                          <span className="l">– {ssLabel} 2026{input.contractType === 'temporal' ? ' · temporal' : ''}</span>
                          <span>−<AnimatedNumber value={result.ss} /></span>
                        </div>
                        <div className="c-row">
                          <span className="l">– Gastos deducibles (art. 19 LIRPF)</span>
                          <span>−<AnimatedNumber value={result.workExpense} /></span>
                        </div>
                        {result.reduction > 0 &&
                        <div className="c-row">
                            <span className="l">– Reducción por rendimientos del trabajo</span>
                            <span>−<AnimatedNumber value={result.reduction} /></span>
                          </div>
                        }
                        {result.pensionCap > 0 &&
                        <div className="c-row">
                            <span className="l">– Planes de pensión</span>
                            <span>−<AnimatedNumber value={result.pensionCap} /></span>
                          </div>
                        }
                      </>
                    }

                    <div className="c-row c-sub">
                      <span className="l">= Base liquidable</span>
                      <span><AnimatedNumber value={result.base} /></span>
                    </div>
                    <div className="c-row c-mini">
                      <span className="l">Mínimo personal y familiar estatal / autonómico</span>
                      <span className="numerals">{fmtEur(result.minimoEstatal)} / {fmtEur(result.minimoAutonomico)}</span>
                    </div>

                    <div className="c-sep">Parte estatal</div>
                    <div className="c-row">
                      <span className="l">Cuota íntegra estatal</span>
                      <span><AnimatedNumber value={result.cuotaEstatal} /></span>
                    </div>
                    <div className="c-row">
                      <span className="l">– Cuota correspondiente al mínimo estatal</span>
                      <span>−<AnimatedNumber value={result.cuotaMinimoEst} /></span>
                    </div>
                    <div className="c-row c-sub">
                      <span className="l">= Cuota líquida estatal</span>
                      <span><AnimatedNumber value={Math.max(0, result.cuotaEstatal - result.cuotaMinimoEst)} /></span>
                    </div>

                    <div className="c-sep">Parte autonómica · {REGION_LIST.find((r) => r.id === input.region)?.label}</div>
                    <div className="c-row">
                      <span className="l">Cuota íntegra autonómica</span>
                      <span><AnimatedNumber value={result.cuotaAuton} /></span>
                    </div>
                    <div className="c-row">
                      <span className="l">– Cuota correspondiente al mínimo autonómico</span>
                      <span>−<AnimatedNumber value={result.cuotaMinimoAut} /></span>
                    </div>
                    <div className="c-row c-sub">
                      <span className="l">= Cuota líquida autonómica</span>
                      <span><AnimatedNumber value={Math.max(0, result.cuotaAuton - result.cuotaMinimoAut)} /></span>
                    </div>

                    <div className="c-row c-total">
                      <span className="l">= IRPF total</span>
                      <span><AnimatedNumber value={result.irpf} /></span>
                    </div>
                  </div>
                </div>
              }

              <div className="actions">
                <div className="tags">
                  {!isAuto && <span className="tag">Retención ≈ {fmtPct(result.withholding)}</span>}
                  {lifestyle.enabled && <span className="tag">IVA estimado · cesta media 8,5%</span>}
                  {lifestyle.enabled && lifestyle.ownsHome && <span className="tag">IBI ≈ 0,18% s/mercado</span>}
                </div>
                <div className="spacer"></div>
                <button className="btn ghost" title="Compartir" onClick={share}>
                  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5">
                    <path d="M4 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4ZM12 5l-6 2M12 11l-6-2M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z" strokeLinejoin="round" />
                  </svg>
                  Compartir
                </button>
                <button className="btn" onClick={() => window.print()}>
                  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5">
                    <path d="M4 6V2h8v4M4 12H2V6h12v6h-2M5 10h6v4H5z" strokeLinejoin="round" />
                  </svg>
                  PDF
                </button>
              </div>
            </div>
          </div>
        </section>

        {/* UN ESTADO MÍNIMO — RALLO COMPARISON */}
        <RalloComparison
          gross={input.gross}
          personal={lifestyle.enabled ? effective.effective : result.net}
          lifestyleEnabled={lifestyle.enabled}
          isAuto={isAuto} />


        {/* EXPLAINER */}
        <section id="como" className="card" style={{ marginBottom: 64 }}>
          <div className="section-label"><span className="num">i</span>Cómo se calcula</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 24 }}>
            <Step n="1" title="Seguridad Social" body={isAuto ? 'RETA 2026: base elegida dentro del tramo de rendimiento neto y tipo total del 31,5%.' : 'Cotizaciones 2026: contingencias, desempleo, formación, MEI y, cuando procede, cuota de solidaridad.'} />
            <Step n="2" title="IRPF" body="Últimas escalas completas publicadas (Renta 2025): tramo estatal y autonómico, mínimos personal y familiar y reducción por trabajo del artículo 20." />
            {lifestyle.enabled && <Step n="3" title="IVA al consumir" body={`Estimamos que gastas ~${Math.round(activeSpendRate * 100)}% de tu neto. Aplicamos un IVA efectivo medio del 8,5% (mezcla ponderada de 21% / 10% / 4% según cesta de consumo española).`} />}
            {lifestyle.enabled && <Step n="4" title="IBI estimado" body="Se aproxima como un 0,18% del valor de mercado. El recibo real depende del valor catastral y del tipo aprobado por el municipio." />}
          </div>
        </section>
    </div>
  );
}

// ─── Un Estado Mínimo — Rallo comparison ─────────────────
const RALLO_FLAT = 0.05; // 5% flat tax on gross
const RALLO_FEES = 0.0055; // 0.55% fees on gross
const RALLO_TOTAL = RALLO_FLAT + RALLO_FEES;

const ALL_CATEGORIES = [
  {
    currentLabel: 'Servicios Públicos Generales',
    currentDesc:  'Administración, deuda pública y servicios de apoyo.',
    currentPct:   12.8,
    ralloLabel:   'Servicios Públicos Generales',
    ralloDesc:    'Burocracia central mínima; la deuda se amortiza durante la transición.',
    ralloPct:     10,
  },
  {
    currentLabel: 'Defensa',
    currentDesc:  'Operaciones militares y equipamiento.',
    currentPct:   2.00,
    ralloLabel:   'Defensa',
    ralloDesc:    'Ejército y equipamiento defensivo.',
    ralloPct:     21,
  },
  {
    currentLabel: 'Orden Público y Seguridad',
    currentDesc:  'Policia, justicia y prisiones.',
    currentPct:   3.90,
    ralloLabel:   'Orden Público y Seguridad',
    ralloDesc:    'Policía nacional, justicia y sistema penitenciario.',
    ralloPct:     23,
  },
  {
    currentLabel: 'Asuntos Económicos',
    currentDesc:  'Transporte, energía, agricultura e infraestructuras.',
    currentPct:   11.20,
    ralloLabel:   'Asuntos Económicos',
    ralloDesc:    'Infraestructura e I+D básicas.',
    ralloPct:     6,
  },
  {
    currentLabel: 'Protección del Medio Ambiente',
    currentDesc:  'Gestión de residuos y conservación.',
    currentPct:   2.10,
    ralloLabel:   'Protección del Medio Ambiente',
    ralloDesc:    'Financiación privada y filantrópica.',
    ralloPct:     0,
  },
  {
    currentLabel: 'Vivienda y Servicios Comunitarios',
    currentDesc:  'Vivienda pública y urbanismo.',
    currentPct:   1.1,
    ralloLabel:   'Vivienda y Servicios Comunitarios',
    ralloDesc:    'Comunidades privadas autogestionadas.',
    ralloPct:     0,
  },
  {
    currentLabel: 'Salud',
    currentDesc:  'Sanidad pública, hospitales y medicamentos.',
    currentPct:   14.20,
    ralloLabel:   'Salud',
    ralloDesc:    'Seguros y hospitales privados.',
    ralloPct:     0,
  },
  {
    currentLabel: 'Ocio, Cultura y Religión',
    currentDesc:  'Actividades culturales y recreativas.',
    currentPct:   2.60,
    ralloLabel:   'Ocio, Cultura y Religión',
    ralloDesc:    'Financiación privada y filantrópica.',
    ralloPct:     0,
  },
  {
    currentLabel: 'Educación',
    currentDesc:  'Docencia, investigación universitaria y becas.',
    currentPct:   9.10,
    ralloLabel:   'Educación',
    ralloDesc:    'Universidades y colegios privados.',
    ralloPct:     0,
  },
  {
    currentLabel: 'Protección Social',
    currentDesc:  'Pensiones, desempleo, familia y dependencia.',
    currentPct:   41.00,
    ralloLabel:   'Protección Social',
    ralloDesc:    'Red de seguridad de última instancia. Pensiones privatizadas.',
    ralloPct:     40,
  },
];

function RalloComparison({ gross, personal, lifestyleEnabled, isAuto }) {
  const [showBreakdown, setShowBreakdown] = useState(false);

  const currentState = Math.max(0, gross - personal);
  const ralloFlat = gross * RALLO_FLAT;
  const ralloFees = gross * RALLO_FEES;
  const ralloState = ralloFlat + ralloFees;
  const ralloPersonal = gross - ralloState;
  const wealthGained = Math.max(0, ralloPersonal - personal);
  const pctGain = personal > 0 ? wealthGained / personal * 100 : 0;

  const g = gross > 0 ? gross : 1;
  const pctCP = Math.max(0, personal / g * 100);
  const pctCS = Math.max(0, currentState / g * 100);
  const pctRP = Math.max(0, ralloPersonal / g * 100);
  const pctRS = Math.max(0, ralloState / g * 100);

  const currentTaxesLabel = lifestyleEnabled ?
  `IRPF + ${isAuto ? 'Cuota Aut.' : 'SS'} + IVA + IBI estimados` :
  `IRPF + ${isAuto ? 'Cuota Autónomos' : 'Seguridad Social'}`;
  const currentRate = gross > 0 ? (currentState / gross * 100).toFixed(1) : '0';

  return (
    <section className="rallo-card" id="estado-minimo">
      <div className="rallo-head">
        <div className="eyebrow">una alternativa · juan ramón rallo</div>
        <h2>¿Y si pagáramos un <span className="mark-g">Estado Mínimo</span>?</h2>
        <p>
          En lugar del laberinto fiscal actual, el economista Juan Ramón Rallo propone financiar un Estado
          mínimo con un único impuesto proporcional del <strong>5% sobre la renta</strong>, más tasas por el
          uso de servicios públicos que rondarían el <strong>0,5% del PIB</strong> —aquí aproximadas como un
          0,55% adicional sobre tu bruto—. El Estado pasaría de absorber cerca del <b>45,5% del PIB</b> a en
          torno al <b>5%</b>: un <b>90% más pequeño</b>.
        </p>
      </div>

      <div className="rallo-grid">
        <div className="rallo-panel current">
          <div className="panel-tag">
            <span>Sistema actual</span>
            <span className="rate numerals">{currentRate}%</span>
          </div>
          <div className="panel-bar">
            <div className="seg-bar personal" style={{ width: `${pctCP}%` }}>
              {pctCP >= 14 ? `${pctCP.toFixed(0)}%` : ''}
            </div>
            <div className="seg-bar state" style={{ width: `${pctCS}%` }}>
              {pctCS >= 14 ? `${pctCS.toFixed(0)}%` : ''}
            </div>
          </div>
          <div className="panel-rows">
            <div className="row">
              <span className="dot personal"></span>
              <span className="lbl">
                Personal
                <span className="hint">Lo que de verdad te llega</span>
              </span>
              <span className="v"><AnimatedNumber value={personal} formatter={fmtEur} /></span>
            </div>
            <div className="row">
              <span className="dot state"></span>
              <span className="lbl">
                Estado
                <span className="hint">{currentTaxesLabel}</span>
              </span>
              <span className="v"><AnimatedNumber value={currentState} formatter={fmtEur} /></span>
            </div>
          </div>
          <button
            className={`breakdown-toggle${showBreakdown ? ' open' : ''}`}
            onClick={() => setShowBreakdown((s) => !s)}>
            ¿A qué va cada euro que pagas?
            <svg className="breakdown-caret" width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
              <path d="M2.5 1.5L7.5 5L2.5 8.5" />
            </svg>
          </button>
          {showBreakdown &&
          <div className="breakdown-list">
              {ALL_CATEGORIES.map((cat) =>
              <div className="breakdown-row" key={cat.currentLabel}>
                  <span className="cat-label">
                    {cat.currentLabel}
                    <span className="cat-desc">{cat.currentDesc}</span>
                  </span>
                  {cat.currentPct === 0 ?
                  <span className="cat-privatized" style={{ gridColumn: '2 / 4' }}>PRIVATIZADO</span> :
                  <>
                      <span className="cat-pct numerals">{cat.currentPct}%</span>
                      <span className="cat-amt numerals">{fmtEur(currentState * cat.currentPct / 100)}</span>
                    </>
                  }
                </div>
              )}
            </div>
          }
        </div>

        <div className="rallo-panel rallo">
          <div className="panel-tag">
            <span>Estado Mínimo · Rallo</span>
            <span className="rate numerals">5,55%</span>
          </div>
          <div className="panel-bar">
            <div className="seg-bar personal" style={{ width: `${pctRP}%` }}>
              {pctRP >= 14 ? `${pctRP.toFixed(0)}%` : ''}
            </div>
            <div className="seg-bar state" style={{ width: `${pctRS}%` }}>
              {pctRS >= 6 ? `${pctRS.toFixed(1)}%` : ''}
            </div>
          </div>
          <div className="panel-rows">
            <div className="row">
              <span className="dot personal"></span>
              <span className="lbl">
                Personal
                <span className="hint">Lo que te llegaría</span>
              </span>
              <span className="v"><AnimatedNumber value={ralloPersonal} formatter={fmtEur} /></span>
            </div>
            <div className="row">
              <span className="dot state"></span>
              <span className="lbl">
                Estado
                <span className="hint">5% impuesto fijo + tasas (aproximadas)</span>
              </span>
              <span className="v"><AnimatedNumber value={ralloState} formatter={fmtEur} /></span>
            </div>
          </div>
          <button
            className={`breakdown-toggle${showBreakdown ? ' open' : ''}`}
            onClick={() => setShowBreakdown((s) => !s)}>
            ¿A qué va cada euro que pagas?
            <svg className="breakdown-caret" width="10" height="10" viewBox="0 0 10 10" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
              <path d="M2.5 1.5L7.5 5L2.5 8.5" />
            </svg>
          </button>
          {showBreakdown &&
          <div className="breakdown-list">
              {ALL_CATEGORIES.map((cat) =>
              <div className="breakdown-row" key={cat.ralloLabel}>
                  <span className="cat-label">
                    {cat.ralloLabel}
                    <span className="cat-desc">{cat.ralloDesc}</span>
                  </span>
                  {cat.ralloPct === 0 ?
                  <span className="cat-privatized" style={{ gridColumn: '2 / 4' }}>PRIVATIZADO</span> :
                  <>
                      <span className="cat-pct numerals">{cat.ralloPct}%</span>
                      <span className="cat-amt numerals">{fmtEur(ralloState * cat.ralloPct / 100)}</span>
                    </>
                  }
                </div>
              )}
            </div>
          }
        </div>
      </div>

      <div className="rallo-gain">
        <div className="lbl">
          <span className="eyebrow">Riqueza ganada</span>
          <span className="desc">Lo que tendrías de más en tu bolsillo cada año</span>
        </div>
        <div className="amt">
          <span className="plus">+</span>
          <span className="numerals"><AnimatedNumber value={wealthGained} formatter={fmtEur} /></span>
          <span className="pct">+{pctGain.toFixed(0)}%</span>
        </div>
      </div>
    </section>);

}

function Step({ n, title, body }) {
  return (
    <div>
      <div style={{ fontFamily: 'var(--font-num)', fontSize: 12, color: 'var(--mute)', marginBottom: 6 }}>{`0${n}`}</div>
      <div style={{ fontWeight: 600, marginBottom: 4 }}>{title}</div>
      <div style={{ fontSize: 14, color: 'var(--ink-2)' }}>{body}</div>
    </div>);

}

function share() {
  const url = window.location.href;
  if (navigator.share) {
    navigator.share({ title: 'Libreta Libertaria · haz los números', url }).catch(() => {});
  } else if (navigator.clipboard) {
    navigator.clipboard.writeText(url);
  }
}

// Expone los primitivos reutilizables a window para que los archivos
// guide-*.jsx (cargados antes) los usen al renderizar.
Object.assign(window, {
  AnimatedNumber, NumberField, SelectField, Segmented, SliderField, ToggleRow, Step,
  fmtEur, fmtEur2, fmtPct });

// ════════════════════════════════════════════════════════════
//  LIBRETA LIBERTARIA · shell unificada
//  Une las dos herramientas ("lo que nos roban" = calculadora ·
//  "lo que nos mienten" = corrupción) con la guía de la propuesta
//  minarquista de Rallo (principios · gobierno · bases · transición).
// ════════════════════════════════════════════════════════════

// tono: rojo = lo que hace el Estado (las dos herramientas) ·
//       oro  = la alternativa (la guía de Rallo).
const SECTIONS = [
  { id: 'inicio',      label: 'Inicio',       group: null,  tone: null },
  { id: 'ideas',       label: 'El Liberalismo',    group: null,  tone: 'oro' },
  { id: 'modelo',      label: 'Transición Liberal',    group: null,  tone: 'oro' },
  { id: 'herramientas',label: 'Herramientas', group: null,  tone: 'rojo' },
  { id: 'amigos',      label: 'Amigos',       group: null,  tone: 'oro' },
];

function LibretaNav({ view, onNav }) {
  const [open, setOpen] = useState(false);
  const go = (id) => (e) => { e.preventDefault(); onNav(id); setOpen(false); };
  return (
    <header className="ll-nav">
      <div className="ll-nav-inner">
        <a className="ll-brand" href="#inicio" onClick={go('inicio')} aria-label="Libreta Libertaria · inicio">
          <span className="ll-brand-mark" aria-hidden="true">
            <span className="ll-brand-rule" /><span className="ll-brand-rule" /><span className="ll-brand-rule" />
          </span>
          <span className="ll-brand-name">Libreta<span className="ll-brand-name-2">Libertaria</span></span>
        </a>

        <button className={`ll-burger${open ? ' open' : ''}`} onClick={() => setOpen((o) => !o)} aria-expanded={open} aria-label="Menú">
          <span /><span /><span />
        </button>

        <nav className={`ll-links${open ? ' open' : ''}`}>
          {SECTIONS.map((s) => (
            <a
              key={s.id}
              href={'#' + s.id}
              onClick={go(s.id)}
              className={`ll-link${view === s.id ? ' on' : ''}${s.tone ? ' tone-' + s.tone : ''}`}
            >
              {s.kicker && <span className="ll-link-kicker">{s.kicker}</span>}
              {s.label}
            </a>
          ))}
        </nav>
      </div>
    </header>
  );
}

function Landing({ go, onNav }) {
  return (
    <div className="ll-landing">
      <section className="ll-hero shell">
        <div className="ll-hero-eyebrow">ideas para reducir el Estado · y por qué · España · 2026</div>
        <h1 className="ll-hero-h1">
          Menos Estado,<br /><mark className="ll-mark-oro">más libertad</mark>.
        </h1>
        <p className="ll-hero-lede">
          Una guía de la idea liberal-libertaria: reducir el Estado a sus funciones esenciales
          —proteger los derechos de cada cual y poco más— y, en el horizonte, aprender a prescindir
          de él. Reúne los principios que la fundamentan, los pensadores que la formularon, un modelo
          concreto para España y tres herramientas para medir impuestos, corrupción y legislación.
        </p>
        <div className="ll-hero-cta">
          <button className="ll-btn ll-btn-oro" onClick={() => go('ideas', 'principios')}>Empieza por las ideas →</button>
          <button className="ll-btn ll-btn-ghost" onClick={() => go('herramientas', 'calculadora')}>Ver lo que cuesta el Estado</button>
        </div>
      </section>

      <section className="shell ll-pillars-wrap">
        <div className="ll-section-rule tone-oro"><span>Por dónde empezar</span></div>
        <div className="ll-pillars">
          <button className="ll-pillar tone-oro" onClick={() => go('ideas', 'principios')}>
            <span className="ll-pillar-k">El Liberalismo</span>
            <span className="ll-pillar-t">Por qué menos Estado</span>
            <span className="ll-pillar-d">Los diez principios del liberalismo y los pensadores que lo formularon, de la minarquía a la anarquía.</span>
            <span className="ll-pillar-go">Explorar →</span>
          </button>
          <button className="ll-pillar tone-oro" onClick={() => go('modelo', 'gobierno')}>
            <span className="ll-pillar-k">Transición Liberal</span>
            <span className="ll-pillar-t">Un plan para España</span>
            <span className="ll-pillar-d">Del 45,5 % al 5 % como penúltimo paso, y de ahí a una sociedad sin Estado: 14 bases y una hoja de ruta.</span>
            <span className="ll-pillar-go">Ver el plan →</span>
          </button>
          <button className="ll-pillar tone-rojo" onClick={() => go('herramientas', 'calculadora')}>
            <span className="ll-pillar-k">Las Herramientas</span>
            <span className="ll-pillar-t">Lo que cuesta hoy</span>
            <span className="ll-pillar-d">Impuestos, corrupción y leyes: herramientas para ver lo que nos roban, lo que nos mienten y lo que nos imponen.</span>
            <span className="ll-pillar-go">Abrir →</span>
          </button>
        </div>
      </section>

      <section className="shell ll-thesis">
        <div className="ll-thesis-inner">
          <div className="ll-thesis-k">El horizonte · menos Estado, siempre</div>
          <p className="ll-thesis-p">
            El Estado mínimo no es la meta, sino la penúltima etapa. Incluso quienes lo proponen como
            modelo para España, como el economista <em>Juan Ramón Rallo</em>, lo describen como un
            «mal necesario», y admiten que, externalizando justicia y seguridad, podría caer del 5 % al
            1,5 % del PIB. El horizonte que persigue la tradición anarcocapitalista —Molinari, Rothbard,
            Hoppe— es una sociedad capaz de sostener el orden <strong>sin Estado en absoluto</strong>. La
            minarquía es el último modelo estatal de ese camino: después queda sustituir sus funciones residuales.
          </p>
          <button className="ll-btn ll-btn-oro ll-thesis-cta" onClick={() => go('ideas', 'pensadores')}>Conoce a los pensadores →</button>
        </div>
      </section>

      <section className="shell ll-amigos-teaser">
        <div className="ll-amigos-teaser-inner">
          <div>
            <div className="ll-amigos-teaser-k">Amigos de la Libertad</div>
            <p className="ll-amigos-teaser-p">Voces e instituciones que defienden, cada cual a su manera, más sociedad y menos Estado.</p>
          </div>
          <button className="ll-btn ll-btn-ghost" onClick={() => onNav('amigos')}>Ver los enlaces →</button>
        </div>
      </section>
    </div>
  );
}

// Barra de navegación secundaria, compartida por las pestañas que
// agrupan varias secciones (Las ideas · El modelo · Herramientas).
function SubNav({ items, active, onPick, kicker, tone = 'oro' }) {
  return (
    <div className={`ll-subnav tone-${tone}`}>
      <div className="shell ll-subnav-inner">
        {kicker && <span className="ll-subnav-kicker">{kicker}</span>}
        <div className="ll-subnav-tabs" role="tablist" aria-label={kicker}>
          {items.map((it) => (
            <button
              key={it.id} role="tab" aria-selected={active === it.id}
              className={`ll-subnav-tab${active === it.id ? ' on' : ''}`}
              onClick={() => onPick(it.id)}
            >
              {it.label}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

// Las ideas: el liberalismo en sí (principios + tradición). Sin Rallo.
function IdeasSection({ sub, setSub }) {
  const PrincipiosSection = window.PrincipiosSection;
  return (
    <div className="ll-sub-page">
      <SubNav kicker="Las ideas" active={sub} onPick={setSub} items={[
        { id: 'principios', label: 'Principios' },
        { id: 'pensadores', label: 'Pensadores' },
      ]} />
      {sub === 'principios' && PrincipiosSection && <PrincipiosSection />}
      {sub === 'pensadores' && <PensadoresSection />}
    </div>
  );
}

// El modelo: el plan concreto para España. Aquí sí se acredita a Rallo.
function ModeloSection({ sub, setSub }) {
  const GobiernoSection = window.GobiernoSection;
  const BasesSection = window.BasesSection;
  const TransicionSection = window.TransicionSection;
  return (
    <div className="ll-sub-page">
      <SubNav kicker="Transición Liberal" active={sub} onPick={setSub} items={[
        { id: 'gobierno', label: 'El Objetivo' },
        { id: 'bases', label: 'Las Bases' },
        { id: 'transicion', label: 'El Proceso' },
      ]} />
      <div className="shell ll-modelo-note">
        <span className="ll-modelo-note-k">Sobre este modelo</span>
        El plan concreto para España, con sus cifras, sectores y calendario, está desarrollado por el
        economista <strong>Juan Ramón Rallo</strong> a partir de fuentes públicas. Es una vía
        posible hacia el Estado mínimo, no la única. En esta guía, ese mínimo es explícitamente el
        <strong> penúltimo paso</strong>: el horizonte final es una sociedad capaz de organizarse sin Estado.
      </div>
      {sub === 'gobierno' && GobiernoSection && <GobiernoSection />}
      {sub === 'bases' && BasesSection && <BasesSection />}
      {sub === 'transicion' && TransicionSection && <TransicionSection />}
    </div>
  );
}

// Herramientas: las dos calculadoras del coste del Estado.
function HerramientasSection({ tool, setTool }) {
  const CorrupcionSection = window.CorrupcionSection;
  const LibertasTrackerPage = window.LibertasTrackerPage;
  return (
    <div className="ll-sub-page">
      <SubNav kicker="Herramientas" tone="rojo" active={tool} onPick={setTool} items={[
        { id: 'calculadora', label: 'Lo que nos roban' },
        { id: 'corrupcion', label: 'Lo que nos mienten' },
        { id: 'libertas', label: 'Lo que nos imponen' },
      ]} />
      <div className="ll-tools-body">
        {tool === 'calculadora' && <CalculadoraSection />}
        {tool === 'corrupcion' && CorrupcionSection && <CorrupcionSection />}
        {tool === 'libertas' && LibertasTrackerPage && <LibertasTrackerPage />}
      </div>
    </div>
  );
}

// ── AMIGOS DE LA LIBERTAD ─────────────────────────────────────
// Enlaces externos verificados (jul. 2026). Para añadir uno nuevo,
// basta con sumar un objeto a la lista de su categoría.
const AMIGOS = [
  {
    cat: 'Divulgación',
    items: [
      { name: 'Juan Ramón Rallo', kind: 'YouTube', desc: 'Economía, política y liberalismo. La fuente intelectual de esta guía.', url: 'https://www.youtube.com/@juanrallo' },
      { name: 'Juan Soto Ivars', kind: 'YouTube', desc: 'Periodismo a contracorriente: libertad de expresión y crítica al poder.', url: 'https://www.youtube.com/@JuanSotoIvarsYtb' },
      { name: 'Axel Kaiser', kind: 'YouTube', desc: 'Liberalismo clásico desde Chile; uno de los grandes divulgadores en español.', url: 'https://www.youtube.com/channel/UCvBCqaycE-OTmzLeK586UDg' },
      { name: 'Daniel Lacalle', kind: 'YouTube', desc: 'Economía y mercados sin anestesia: energía, deuda pública y crítica al intervencionismo.', url: 'https://www.youtube.com/@DanielLacalleOfficial' },
    ],
  },
  {
    cat: 'Instituciones y formación',
    items: [
      { name: 'Instituto Juan de Mariana', kind: 'Think tank', desc: 'El centro de referencia del liberalismo clásico en España.', url: 'https://juandemariana.org/' },
      { name: 'Universidad Francisco Marroquín', kind: 'Universidad', desc: 'La universidad libertaria por excelencia; con sede también en Madrid.', url: 'https://www.ufm.edu/' },
      { name: 'Mises Institute', kind: 'Investigación', desc: 'El gran archivo mundial de la escuela austriaca y el anarcocapitalismo.', url: 'https://mises.org/' },
      { name: 'elCato.org', kind: 'En español', desc: 'La ventana hispana del Cato Institute: análisis liberal de políticas públicas.', url: 'https://www.elcato.org/' },
    ],
  },
  {
    cat: 'Redes y activismo',
    items: [
      { name: 'Fundación para el Avance de la Libertad', kind: 'Think tank', desc: 'Estudios e índices que miden la libertad en España —fiscal, económica, sanitaria— y campañas para ampliarla.', url: 'https://fundalib.org/' },
      { name: 'Estudiantes por la Libertad', kind: 'Red estudiantil', desc: 'La mayor red mundial de jóvenes pro-libertad, con presencia y formación en español.', url: 'https://www.studentsforliberty.org/es/' },
    ],
  },
  {
    cat: 'Política',
    items: [
      { name: 'Partido Libertario (P-LIB)', kind: 'Partido', desc: 'El único partido español que rechaza por estatutos las subvenciones públicas.', url: 'https://www.p-lib.es/' },
      { name: 'Escaños en Blanco', kind: 'Partido', desc: 'Se compromete a dejar vacíos los escaños que obtiene: el voto en blanco convertido en menos sillones —y menos gasto— político.', url: 'https://escanos.org/' },
    ],
  },
];

function AmigosSection() {
  return (
    <div className="ll-amigos">
      <section className="shell ll-amigos-hd">
        <div className="ll-hero-eyebrow tone-oro">la causa de la libertad · enlaces externos</div>
        <h1 className="ll-amigos-h1">Amigos de la Libertad</h1>
        <p className="ll-amigos-lede">
          Quien quiera seguir tirando del hilo encontrará aquí a algunas de las voces e instituciones
          que defienden, cada cual a su manera, más sociedad y menos Estado. Son enlaces externos: se
          abren en una pestaña nueva.
        </p>
      </section>
      {AMIGOS.map((g) => (
        <section className="shell ll-amigos-group" key={g.cat}>
          <div className="ll-section-rule tone-oro"><span>{g.cat}</span></div>
          <div className="ll-amigos-grid">
            {g.items.map((a) => (
              <a className="ll-amigo" key={a.name} href={a.url} target="_blank" rel="noopener noreferrer">
                <span className="ll-amigo-kind">{a.kind}</span>
                <span className="ll-amigo-name">{a.name}</span>
                <span className="ll-amigo-desc">{a.desc}</span>
                <span className="ll-amigo-go">Visitar <span aria-hidden="true">↗</span></span>
              </a>
            ))}
          </div>
        </section>
      ))}
    </div>
  );
}

function LibretaFooter({ onNav }) {
  return (
    <footer className="ll-footer">
      <div className="shell ll-footer-inner">
        <div className="ll-footer-brand">
          <span className="ll-brand-name">Libreta<span className="ll-brand-name-2">Libertaria</span></span>
          <p>Una guía de las ideas del liberalismo libertario: del Estado mínimo a una sociedad sin Estado. El modelo concreto para España y sus cifras provienen de la obra del economista Juan Ramón Rallo y de fuentes públicas (IGAE, INE, BEPSAP, Eurostat).</p>
        </div>
        <nav className="ll-footer-links">
          <a href="#ideas" onClick={(e) => { e.preventDefault(); onNav('ideas'); }}>El Liberalismo</a>
          <a href="#modelo" onClick={(e) => { e.preventDefault(); onNav('modelo'); }}>Transición Liberal</a>
          <a href="#herramientas" onClick={(e) => { e.preventDefault(); onNav('herramientas'); }}>Herramientas</a>
          <a href="#amigos" onClick={(e) => { e.preventDefault(); onNav('amigos'); }}>Amigos de la Libertad</a>
        </nav>
      </div>
      <div className="shell ll-footer-legal">
        <span>© 2026 Libreta Libertaria · contenido divulgativo, no asesoramiento fiscal ni jurídico.</span>
        <span>Sobre los casos judiciales rige la presunción de inocencia de todos los implicados.</span>
      </div>
    </footer>
  );
}

// ── PENSADORES LIBERTARIOS ────────────────────────────────────
// Ordenados como una genealogía: del liberalismo clásico al Estado
// mínimo (donde se sitúa Rallo) y, más allá, al anarcocapitalismo.
// Citas breves y atribuidas; las de Bastiat, Molinari y el lema de
// Mises (Virgilio) son de dominio público.
const PENSADORES = [
  {
    cat: 'Liberalismo clásico',
    note: 'Por qué el Estado debe limitarse',
    items: [
      {
        name: 'Adam Smith', life: '1723–1790',
        vision: 'El padre de la economía moderna. Mostró que la cooperación entre desconocidos no necesita un director: el interés propio, bajo reglas de justicia, se convierte en prosperidad general, con un Estado limitado a defensa, justicia y unas pocas obras públicas.',
        works: 'La riqueza de las naciones · Teoría de los sentimientos morales',
        quote: 'No es de la benevolencia del carnicero, del cervecero o del panadero de donde esperamos nuestra cena, sino del cuidado que ponen en su propio interés.',
        quoteSrc: 'La riqueza de las naciones (1776)',
      },
      {
        name: 'Frédéric Bastiat', life: '1801–1850',
        vision: 'Denunció el «expolio legal»: el Estado vive de redistribuir por la fuerza lo que produce la sociedad. Y enseñó a mirar siempre lo que no se ve, no solo lo visible.',
        works: 'La ley · Lo que se ve y lo que no se ve',
        quote: 'El Estado: la gran ficción por la que todos viven a costa de todos.',
      },
      {
        name: 'Ludwig von Mises', life: '1881–1973',
        vision: 'Mostró que sin propiedad privada ni precios el socialismo no puede calcular, y que el mercado es la forma más pacífica de cooperación humana.',
        works: 'La acción humana · Socialismo · Liberalismo',
        quote: 'No te dejes vencer por el mal; enfréntate a él con más audacia.',
        quoteSrc: 'su lema, tomado de Virgilio',
      },
      {
        name: 'Friedrich A. Hayek', life: '1899–1992',
        vision: 'El conocimiento está disperso entre millones de personas: ninguna mente central puede planificar la economía sin destruir el orden espontáneo que la hace funcionar.',
        works: 'Camino de servidumbre · Los fundamentos de la libertad',
        quote: 'Cuanto más planifica el Estado, más difícil le resulta planificar al individuo.',
      },
      {
        name: 'Milton Friedman', life: '1912–2006',
        vision: 'Sin libertad económica no hay libertad política: el mercado coordina por consentimiento lo que el Estado solo consigue por coacción.',
        works: 'Capitalismo y libertad · Libertad de elegir',
        quote: 'Nada hay tan permanente como un programa temporal del gobierno.',
      },
    ],
  },
  {
    cat: 'El Estado mínimo',
    note: 'Donde se sitúa esta guía',
    items: [
      {
        name: 'Robert Nozick', life: '1938–2002',
        vision: 'Solo el Estado mínimo —limitado a protegernos de la fuerza, el robo y el fraude— es legítimo; cualquier Estado más amplio viola los derechos de alguien.',
        works: 'Anarquía, Estado y utopía',
        quote: 'El Estado mínimo es el Estado más amplio que puede justificarse.',
      },
      {
        name: 'Juan Ramón Rallo', life: '1984– ',
        vision: 'Economista español y fuente intelectual de esta guía. Ha traducido la minarquía a cifras para España: un Estado del 5% del PIB, financiado con un impuesto único y tasas, como etapa realista —y revisable a la baja— hacia una sociedad plenamente libre.',
        works: 'Una revolución liberal para España · Liberalismo: los diez principios',
        quote: 'El liberalismo es una ideología cuyo principio básico es tratar de minimizar la coacción dentro de las relaciones sociales.',
        quoteSrc: 'sobre Una revolución liberal para España',
      },
    ],
  },
  {
    cat: 'Hacia la abolición del Estado',
    note: 'El horizonte: orden sin Estado',
    items: [
      {
        name: 'Gustave de Molinari', life: '1819–1912',
        vision: 'El primero en llevar la lógica del mercado hasta el final: si la competencia mejora todos los servicios, tampoco la seguridad tendría por qué ser monopolio del Estado.',
        works: 'La producción de seguridad',
        quote: 'Ningún gobierno debería impedir que otro gobierno compita con él.',
      },
      {
        name: 'Murray N. Rothbard', life: '1926–1995',
        vision: 'Padre del anarcocapitalismo: el Estado es expolio institucionalizado, y todo servicio —justicia y seguridad incluidas— puede proveerlo mejor el mercado libre.',
        works: 'La ética de la libertad · Hacia una nueva libertad',
        quote: 'El Estado no es más que una banda de ladrones a gran escala.',
      },
      {
        name: 'David D. Friedman', life: '1945– ',
        vision: 'Economista, hijo de Milton Friedman. Detalló cómo el mercado podría producir también ley, policía y tribunales: el anarcocapitalismo como ingeniería institucional concreta, no como utopía.',
        works: 'La maquinaria de la libertad',
        quote: 'El uso directo de la fuerza es tan mala solución para cualquier problema que, por lo general, solo la emplean los niños pequeños y las grandes naciones.',
        quoteSrc: 'La maquinaria de la libertad',
      },
      {
        name: 'Hans-Hermann Hoppe', life: '1949– ',
        vision: 'Discípulo de Rothbard. Sostiene que ningún gobierno se mantiene limitado y que la democracia, al volver el Estado «propiedad pública», acelera su expansión. Defiende un orden privado basado en la propiedad.',
        works: 'Monarquía, democracia y orden natural',
        quote: 'No puede existir algo así como un gobierno limitado.',
      },
      {
        name: 'Jesús Huerta de Soto', life: '1956– ',
        vision: 'Catedrático español de la escuela austriaca, en activo. Une cálculo económico y función empresarial: ningún planificador puede reunir el conocimiento que necesitaría para dirigir la sociedad, por lo que toda intervención coactiva la desorganiza.',
        works: 'Socialismo, cálculo económico y función empresarial · Dinero, crédito bancario y ciclos económicos',
        quote: 'El socialismo es todo sistema de agresión institucional contra el libre ejercicio de la función empresarial.',
        quoteSrc: 'su definición de socialismo',
      },
    ],
  },
];

function PensadoresSection() {
  return (
    <div className="ll-think">
      <section className="shell ll-think-hd">
        <div className="ll-hero-eyebrow tone-oro">la genealogía de la libertad · de la minarquía a la anarquía</div>
        <h1 className="ll-think-h1">Pensadores Libertarios</h1>
        <p className="ll-think-lede">
          Estos autores trazan el recorrido de quienes argumentaron por qué el Estado debe limitarse, al Estado mínimo
          donde se sitúa esta guía, hasta quienes sostienen que el orden podría mantenerse sin Estado
          alguno. La dirección, en todos, es la misma: más sociedad, menos coacción.
        </p>
      </section>
      {PENSADORES.map((g) => (
        <section className="shell ll-think-group" key={g.cat}>
          <div className="ll-section-rule tone-oro"><span>{g.cat}</span><em>{g.note}</em></div>
          <div className={`ll-think-grid${g.items.length === 1 ? ' is-solo' : ''}`}>
            {g.items.map((p) => (
              <article className="ll-thinker" key={p.name}>
                <div className="ll-thinker-top">
                  <span className="ll-thinker-name">{p.name}</span>
                  <span className="ll-thinker-life numerals">{p.life}</span>
                </div>
                <p className="ll-thinker-vision">{p.vision}</p>
                <blockquote className="ll-thinker-quote">
                  <span className="ll-thinker-q">«{p.quote}»</span>
                  {p.quoteSrc && <cite className="ll-thinker-cite">{p.quoteSrc}</cite>}
                </blockquote>
                <div className="ll-thinker-works"><span className="ll-thinker-works-k">Obras</span>{p.works}</div>
              </article>
            ))}
          </div>
        </section>
      ))}
    </div>
  );
}

// ── Routing por hash (#seccion o #seccion/subseccion) ─────────
// Hace las vistas enlazables y compartibles sin servidor. Los hashes
// que no correspondan a una vista (p.ej. anclas internas como #g-coste)
// se ignoran y siguen funcionando como anclas de scroll.
const VALID_VIEWS = new Set(SECTIONS.map((s) => s.id));
const VALID_SUBS = {
  ideas: ['principios', 'pensadores'],
  modelo: ['gobierno', 'bases', 'transicion'],
  herramientas: ['calculadora', 'corrupcion', 'libertas'],
};
function readHash() {
  if (window.location.pathname.replace(/\/$/, '') === '/libertas-tracker') {
    return { v: 'herramientas', sub: 'libertas' };
  }
  const [v, sub] = window.location.hash.replace(/^#/, '').split('/');
  if (!VALID_VIEWS.has(v)) return null;
  return { v, sub: (VALID_SUBS[v] || []).includes(sub) ? sub : null };
}

function Shell() {
  const initial = readHash();
  const [view, setView] = useState(initial ? initial.v : 'inicio');
  const [tool, setTool] = useState(initial && initial.v === 'herramientas' && initial.sub ? initial.sub : 'calculadora');
  const [ideaSub, setIdeaSub] = useState(initial && initial.v === 'ideas' && initial.sub ? initial.sub : 'principios');
  const [modeloSub, setModeloSub] = useState(initial && initial.v === 'modelo' && initial.sub ? initial.sub : 'gobierno');
  const onNav = (id) => setView(id);
  // Navega a una pestaña y, opcionalmente, a una de sus subsecciones.
  const go = (v, sub) => {
    if (sub) {
      if (v === 'herramientas') setTool(sub);
      else if (v === 'ideas') setIdeaSub(sub);
      else if (v === 'modelo') setModeloSub(sub);
    }
    setView(v);
  };
  useEffect(() => { window.scrollTo(0, 0); }, [view]);

  // Estado → URL: mantiene el hash sincronizado con la vista actual.
  useEffect(() => {
    const sub =
      view === 'herramientas' ? tool :
      view === 'ideas' ? ideaSub :
      view === 'modelo' ? modeloSub : null;
    if (view === 'herramientas' && tool === 'libertas') {
      if (window.location.pathname.replace(/\/$/, '') !== '/libertas-tracker' || window.location.hash) {
        history.replaceState(null, '', '/libertas-tracker');
      }
      return;
    }
    const h = '#' + view + (sub ? '/' + sub : '');
    if (window.location.pathname !== '/' || window.location.hash !== h) history.replaceState(null, '', '/' + h);
  }, [view, tool, ideaSub, modeloSub]);

  // URL → estado: soporta atrás/adelante del navegador y enlaces entrantes.
  useEffect(() => {
    const onHash = () => {
      const p = readHash();
      if (!p) return;
      if (p.sub) {
        if (p.v === 'herramientas') setTool(p.sub);
        else if (p.v === 'ideas') setIdeaSub(p.sub);
        else if (p.v === 'modelo') setModeloSub(p.sub);
      }
      setView(p.v);
    };
    window.addEventListener('hashchange', onHash);
    window.addEventListener('popstate', onHash);
    return () => { window.removeEventListener('hashchange', onHash); window.removeEventListener('popstate', onHash); };
  }, []);

  return (
    <>
      <LibretaNav view={view} onNav={onNav} />
      <main className="ll-main">
        {view === 'inicio' && <Landing go={go} onNav={onNav} />}
        {view === 'ideas' && <IdeasSection sub={ideaSub} setSub={setIdeaSub} />}
        {view === 'modelo' && <ModeloSection sub={modeloSub} setSub={setModeloSub} />}
        {view === 'herramientas' && <HerramientasSection tool={tool} setTool={setTool} />}
        {view === 'amigos' && <AmigosSection />}
      </main>
      <LibretaFooter onNav={onNav} />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<Shell />);
})();
