/* global React */
const { useState, useEffect } = React;

/*
  PlatformModulesSection — v3
  ─────────────────────────────
  Same UX/UI pattern as the rest of the Platform page:
    · pp-platform-section / pp-split / pp-tag / pp-section-title / pp-modules
    · device mock on one side, FeatureModule list on the other
    · alternating mist / white backgrounds, --flip alternates the side

  5 modules + AI custom section with 3 case studies (Litter live · Demand pilot · Pavement proposed).
  Cases 3 (PPE) and 4 (electrical) removed — out of scope for vehicle ops.
*/

// ── Local FeatureModule (mirrors the one in platform-page.jsx) ───────────────
function PMFeature({ num, title, body, chips }) {
  return (
    <div style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
      <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--accent)", background: "color-mix(in oklch, var(--accent) 10%, transparent)", border: "1px solid color-mix(in oklch, var(--accent) 22%, transparent)", borderRadius: 4, padding: "3px 7px", flexShrink: 0, marginTop: 2, letterSpacing: "0.08em" }}>{num}</div>
      <div>
        <div style={{ fontSize: 15, fontWeight: 500, marginBottom: 4 }}>{title}</div>
        <div style={{ fontSize: 13.5, color: "var(--fog)", lineHeight: 1.55, marginBottom: chips ? 8 : 0 }}>{body}</div>
        {chips && (
          <div style={{ display: "flex", flexWrap: "wrap", gap: 5 }}>
            {chips.map((c, i) => (
              <span key={i} style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "oklch(0.42 0.03 240)", background: "oklch(0.93 0.01 240)", border: "1px solid oklch(0.86 0.02 240)", borderRadius: 4, padding: "2px 7px", letterSpacing: "0.04em" }}>{c}</span>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ── Browser frame (mirrors PPBrowser styling) ───────────────────────────────
function PMBrowser({ url = "flow.gropp.tech", children }) {
  return (
    <div style={{
      width: 480, height: 340,
      background: "oklch(0.97 0.005 240)",
      borderRadius: 12,
      border: "1px solid oklch(0.82 0.02 240)",
      boxShadow: "0 4px 6px -1px oklch(0.50 0.06 240 / 0.07), 0 30px 80px -20px oklch(0.45 0.08 240 / 0.18)",
      overflow: "hidden", flexShrink: 0,
    }}>
      <div style={{ background: "oklch(0.93 0.006 240)", borderBottom: "1px solid oklch(0.86 0.01 240)", padding: "9px 14px", display: "flex", alignItems: "center", gap: 8 }}>
        <div style={{ display: "flex", gap: 5 }}>
          {["oklch(0.68 0.14 25)", "oklch(0.73 0.14 80)", "oklch(0.63 0.17 145)"].map((c, i) => (
            <div key={i} style={{ width: 11, height: 11, borderRadius: "50%", background: c }} />
          ))}
        </div>
        <div style={{ flex: 1, background: "oklch(0.97 0.005 240)", border: "1px solid oklch(0.86 0.01 240)", borderRadius: 5, padding: "3px 11px", fontFamily: "var(--font-mono)", fontSize: 9.5, color: "oklch(0.50 0.03 240)", letterSpacing: "0.04em" }}>
          {url}
        </div>
      </div>
      <div style={{ height: "calc(100% - 40px)", overflow: "hidden" }}>{children}</div>
    </div>
  );
}

// ── Mocks per module ────────────────────────────────────────────────────────

function ServicesMock({ isEs }) {
  const services = isEs ? [
    { code: "REC-DOM", name: "Recolección domiciliaria", freq: "Lun · Mié · Vie", crew: "1+2", forms: 2, active: true },
    { code: "BAR-CAL", name: "Barrido de calle", freq: "Diario", crew: "1+1", forms: 1, active: true },
    { code: "POD-VRD", name: "Recolección de poda", freq: "Quincenal", crew: "1+3", forms: 1, active: false },
    { code: "ESC-VOL", name: "Voluminosos", freq: "A demanda", crew: "1+2", forms: 2, active: true },
  ] : [
    { code: "COL-RES", name: "Residential collection", freq: "Mon · Wed · Fri", crew: "1+2", forms: 2, active: true },
    { code: "SWP-STR", name: "Street sweeping", freq: "Daily", crew: "1+1", forms: 1, active: true },
    { code: "PRN-COL", name: "Pruning collection", freq: "Bi-weekly", crew: "1+3", forms: 1, active: false },
    { code: "BLK-COL", name: "Bulk waste", freq: "On-demand", crew: "1+2", forms: 2, active: true },
  ];
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", background: "oklch(0.97 0.005 240)" }}>
      <div style={{ padding: "10px 14px", borderBottom: "1px solid oklch(0.88 0.01 240)", display: "flex", alignItems: "center", justifyContent: "space-between", background: "white" }}>
        <div style={{ fontSize: 12, fontWeight: 500 }}>{isEs ? "Catálogo de servicios" : "Service catalog"}</div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "var(--accent)", background: "color-mix(in oklch, var(--accent) 10%, transparent)", border: "1px solid color-mix(in oklch, var(--accent) 22%, transparent)", borderRadius: 4, padding: "3px 8px", letterSpacing: "0.06em" }}>+ {isEs ? "NUEVO" : "NEW"}</div>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "auto 1fr auto auto auto auto", padding: "8px 14px", gap: 12, fontFamily: "var(--font-mono)", fontSize: 8.5, color: "oklch(0.50 0.03 240)", letterSpacing: "0.08em", borderBottom: "1px solid oklch(0.92 0.01 240)" }}>
        <div>CÓDIGO</div><div>NOMBRE</div><div>FRECUENCIA</div><div>CUADRILLA</div><div>FORMS</div><div>EST.</div>
      </div>
      {services.map((s, i) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "auto 1fr auto auto auto auto", padding: "10px 14px", gap: 12, alignItems: "center", borderBottom: "1px solid oklch(0.94 0.01 240)" }}>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--accent)" }}>{s.code}</span>
          <span style={{ fontSize: 11.5, color: "oklch(0.25 0.04 250)" }}>{s.name}</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.45 0.03 240)" }}>{s.freq}</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.45 0.03 240)" }}>{s.crew}</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.45 0.03 240)" }}>{s.forms}</span>
          <span style={{ width: 8, height: 8, borderRadius: "50%", background: s.active ? "oklch(0.62 0.18 145)" : "oklch(0.78 0.02 240)", justifySelf: "end" }} />
        </div>
      ))}
    </div>
  );
}

function PlansMock({ isEs }) {
  const days = isEs ? ["L", "M", "X", "J", "V", "S", "D"] : ["M", "T", "W", "T", "F", "S", "S"];
  const turns = isEs ? ["Mañana", "Tarde", "Noche"] : ["Morning", "Afternoon", "Night"];
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", background: "oklch(0.97 0.005 240)" }}>
      <div style={{ padding: "10px 14px", borderBottom: "1px solid oklch(0.88 0.01 240)", display: "flex", alignItems: "center", justifyContent: "space-between", background: "white" }}>
        <div style={{ fontSize: 12, fontWeight: 500 }}>{isEs ? "Plan recurrente · Semana tipo" : "Recurring plan · Template week"}</div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.55 0.03 240)" }}>SEM 17 · 2026</div>
      </div>
      <div style={{ padding: "12px 14px", flex: 1, display: "grid", gridTemplateColumns: "70px repeat(7, 1fr)", gap: 4 }}>
        <div />
        {days.map((d, i) => (
          <div key={i} style={{ textAlign: "center", fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.45 0.03 240)", letterSpacing: "0.1em" }}>{d}</div>
        ))}
        {turns.map((t, ti) => (
          <React.Fragment key={ti}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.50 0.03 240)", display: "flex", alignItems: "center" }}>{t}</div>
            {[0, 1, 2, 3, 4, 5, 6].map(di => {
              // weekend off for night/afternoon mostly
              const has = !(di > 4 && ti > 0) && !(ti === 2 && di > 3);
              const isToday = di === 2 && ti === 0;
              return (
                <div key={di} style={{
                  background: has ? (isToday ? "var(--accent)" : "oklch(0.93 0.01 240)") : "transparent",
                  border: has ? "1px solid " + (isToday ? "var(--accent)" : "oklch(0.86 0.02 240)") : "1px dashed oklch(0.88 0.01 240)",
                  borderRadius: 4,
                  padding: "8px 4px",
                  fontFamily: "var(--font-mono)",
                  fontSize: 8.5,
                  color: has ? (isToday ? "white" : "oklch(0.35 0.04 250)") : "oklch(0.75 0.02 240)",
                  textAlign: "center",
                  lineHeight: 1.3,
                }}>
                  {has ? <>R-{12 + ti}<br />{ti === 0 ? "06:00" : ti === 1 ? "14:00" : "22:00"}</> : "—"}
                </div>
              );
            })}
          </React.Fragment>
        ))}
      </div>
      <div style={{ padding: "10px 14px", borderTop: "1px solid oklch(0.92 0.01 240)", display: "flex", justifyContent: "space-between", fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.50 0.03 240)" }}>
        <span>{isEs ? "PRONÓSTICO FIN" : "FORECAST END"} · 18:42</span>
        <span style={{ color: "oklch(0.62 0.18 145)" }}>±8 min · {isEs ? "histórico" : "vs. history"}</span>
      </div>
    </div>
  );
}

function RoutesMock({ isEs }) {
  const stops = [[40, 200], [80, 160], [130, 140], [180, 100], [220, 80], [280, 60], [320, 50]];
  const [t, setT] = useState(0);
  useEffect(() => { const id = setInterval(() => setT(x => (x + 1) % 100), 80); return () => clearInterval(id); }, []);
  const idx = Math.floor((t / 100) * (stops.length - 1));
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", background: "oklch(0.97 0.005 240)" }}>
      <div style={{ padding: "10px 14px", borderBottom: "1px solid oklch(0.88 0.01 240)", display: "flex", alignItems: "center", justifyContent: "space-between", background: "white" }}>
        <div style={{ fontSize: 12, fontWeight: 500 }}>R-14 · {isEs ? "Centro · Mañana" : "Downtown · AM"}</div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.62 0.18 145)" }}>{isEs ? "CONFIRMADA" : "CONFIRMED"}</div>
      </div>
      <div style={{ flex: 1, position: "relative", background: "oklch(0.94 0.01 240)" }}>
        <svg viewBox="0 0 380 240" style={{ width: "100%", height: "100%" }}>
          {[40, 80, 120, 160, 200].map(y => <line key={y} x1={0} y1={y} x2={380} y2={y} stroke="oklch(0.86 0.02 240)" strokeWidth={0.6} />)}
          {[60, 120, 180, 240, 300, 360].map(x => <line key={x} x1={x} y1={0} x2={x} y2={240} stroke="oklch(0.86 0.02 240)" strokeWidth={0.6} />)}
          {/* zone polygon */}
          <polygon points="20,180 90,120 240,90 340,40 360,210 60,230" fill="color-mix(in oklch, var(--accent) 12%, transparent)" stroke="var(--accent)" strokeWidth={1} strokeDasharray="4 3" />
          <polyline points={stops.map(p => p.join(",")).join(" ")} fill="none" stroke="oklch(0.30 0.04 250)" strokeWidth={2} />
          {stops.map(([x, y], i) => (
            <g key={i}>
              <circle cx={x} cy={y} r={i <= idx ? 6 : 4.5} fill={i <= idx ? "var(--accent)" : "oklch(0.94 0.01 240)"} stroke="var(--accent)" strokeWidth={1.5} />
              <text x={x + 8} y={y + 3} fontSize={8} fontFamily="var(--font-mono)" fill="oklch(0.40 0.03 240)">#{i + 1}</text>
            </g>
          ))}
        </svg>
      </div>
      <div style={{ padding: "8px 14px", borderTop: "1px solid oklch(0.92 0.01 240)", display: "flex", justifyContent: "space-between", fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.50 0.03 240)" }}>
        <span>{stops.length} {isEs ? "paradas" : "stops"} · 8.4 km</span>
        <span>{idx + 1} / {stops.length} {isEs ? "completadas" : "done"}</span>
      </div>
    </div>
  );
}

function EmergentMock({ isEs }) {
  const items = isEs ? [
    { id: "#312", t: "Reclamo", txt: "Contenedor desbordado · Av. 8 de Octubre 3421", state: "→ ruta R-14", color: "var(--accent)" },
    { id: "#308", t: "Reclamo", txt: "Microbasural · Bv. España y Sarmiento", state: "agendado · jueves", color: "oklch(0.68 0.16 75)" },
    { id: "WO-89", t: "Orden", txt: "Limpieza extra evento · Plaza Independencia", state: "asignada · cuadrilla B", color: "oklch(0.62 0.18 145)" },
    { id: "EV-45", t: "Imprevisto", txt: "Corte por accidente · Bv. Artigas", state: "+12 min ETA", color: "oklch(0.65 0.18 35)" },
  ] : [
    { id: "#312", t: "Complaint", txt: "Overflowing bin · 8 de Octubre Ave 3421", state: "→ route R-14", color: "var(--accent)" },
    { id: "#308", t: "Complaint", txt: "Illegal dump · Bv. España & Sarmiento", state: "scheduled · Thu", color: "oklch(0.68 0.16 75)" },
    { id: "WO-89", t: "Order", txt: "Extra cleaning event · Independencia Sq.", state: "assigned · crew B", color: "oklch(0.62 0.18 145)" },
    { id: "EV-45", t: "Unplanned", txt: "Closure due to accident · Artigas Blvd", state: "+12 min ETA", color: "oklch(0.65 0.18 35)" },
  ];
  return (
    <div style={{ height: "100%", display: "flex", flexDirection: "column", background: "oklch(0.97 0.005 240)" }}>
      <div style={{ padding: "10px 14px", borderBottom: "1px solid oklch(0.88 0.01 240)", display: "flex", alignItems: "center", justifyContent: "space-between", background: "white" }}>
        <div style={{ fontSize: 12, fontWeight: 500 }}>{isEs ? "Bandeja de trabajo emergente" : "Emergent work inbox"}</div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, color: "oklch(0.50 0.03 240)" }}>4 / 12</div>
      </div>
      <div style={{ flex: 1, padding: "10px 12px", display: "flex", flexDirection: "column", gap: 8 }}>
        {items.map((it, i) => (
          <div key={i} style={{ display: "flex", alignItems: "center", gap: 12, background: "white", border: "1px solid oklch(0.92 0.01 240)", borderLeft: `3px solid ${it.color}`, borderRadius: 5, padding: "9px 11px" }}>
            <div style={{ minWidth: 42 }}>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, fontWeight: 600, color: it.color }}>{it.id}</div>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 7.5, color: "oklch(0.55 0.03 240)", letterSpacing: "0.06em", marginTop: 1 }}>{it.t.toUpperCase()}</div>
            </div>
            <div style={{ flex: 1, fontSize: 11, color: "oklch(0.30 0.04 250)" }}>{it.txt}</div>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 8.5, color: it.color, background: "color-mix(in oklch, " + it.color + " 10%, transparent)", border: "1px solid color-mix(in oklch, " + it.color + " 24%, transparent)", borderRadius: 4, padding: "3px 7px", whiteSpace: "nowrap" }}>{it.state}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

function RulesMock({ isEs }) {
  return (
    <div style={{ height:"100%", background:"white", overflow:"hidden", display:"flex", alignItems:"flex-start", justifyContent:"center" }}>
      <img
        src={(window.__resources&&window.__resources.rulesReal)||"assets/rules-real.png"}
        alt={isEs ? "Builder de reglas · Agregar Regla Lógica" : "Rule builder · Add Logic Rule"}
        style={{ width:"100%", height:"auto", objectFit:"contain", display:"block" }}
      />
    </div>
  );
}

// ── AI case visuals (kept compact, browser-framed) ───────────────────────────

function LitterMock() {
  return (
    <div style={{ width:"100%", height:"100%", position:"relative", overflow:"hidden", background:"oklch(0.15 0.04 250)" }}>
      <img
        src={(window.__resources&&window.__resources.detectionLitter)||"assets/detection-litter.png"}
        alt="AI litter detection"
        style={{ width:"100%", height:"100%", objectFit:"cover", display:"block" }}
      />
      <div style={{ position:"absolute", top:10, left:10, background:"oklch(0.20 0.04 250 / 0.85)", backdropFilter:"blur(4px)", borderRadius:4, padding:"4px 9px", fontSize:10, fontFamily:"var(--font-mono)", color:"white", letterSpacing:"0.08em", display:"flex", alignItems:"center", gap:6 }}>
        <span style={{ width:6, height:6, borderRadius:"50%", background:"oklch(0.65 0.20 25)", boxShadow:"0 0 8px oklch(0.65 0.20 25)" }}/>
        AI-DETECTED · 100.0%
      </div>
      <div style={{ position:"absolute", bottom:0, left:0, right:0, padding:"6px 12px", background:"oklch(0.13 0.03 250 / 0.92)", display:"flex", justifyContent:"space-between", fontSize:10, fontFamily:"var(--font-mono)" }}>
        <span style={{ color:"var(--accent)" }}>VEH 2285·TAB · POINT Z23D-138</span>
        <span style={{ color:"oklch(0.55 0.04 240)" }}>REC ●</span>
      </div>
    </div>
  );
}

function DemandMock({ isEs }) {
  const grid = [
    [3, 5, 4, 2, 1, 3], [4, 7, 8, 5, 2, 2], [3, 6, 9, 7, 3, 1], [2, 4, 7, 6, 4, 2], [1, 2, 3, 4, 3, 2],
  ];
  const colorFor = v => `oklch(${0.95 - (v / 9) * 0.45} ${0.04 + (v / 9) * 0.18} ${250 - (v / 9) * 100})`;
  return (
    <svg viewBox="0 0 480 300" style={{ width: "100%", height: "100%", display: "block" }}>
      <rect width={480} height={300} fill="oklch(0.97 0.005 240)" />
      <text x={20} y={28} fontSize={11} fontFamily="var(--font-mono)" fill="oklch(0.40 0.03 240)" letterSpacing="0.08em">{isEs ? "DEMANDA PREVISTA · MIÉRCOLES" : "FORECAST DEMAND · WED"}</text>
      {grid.map((row, ri) => row.map((v, ci) => (
        <g key={`${ri}-${ci}`}>
          <rect x={20 + ci * 50} y={48 + ri * 40} width={46} height={36} fill={colorFor(v)} stroke="white" strokeWidth={1.5} />
          <text x={43 + ci * 50} y={72 + ri * 40} textAnchor="middle" fontSize={13} fontFamily="var(--font-mono)" fill={v > 5 ? "white" : "oklch(0.40 0.03 240)"}>{v}</text>
        </g>
      )))}
      <rect x={340} y={48} width={120} height={120} fill="oklch(0.94 0.008 240)" stroke="var(--accent)" strokeWidth={1.5} />
      <text x={350} y={70} fontSize={10} fontFamily="var(--font-mono)" fill="var(--accent)" letterSpacing="0.06em">{isEs ? "SUGERENCIA" : "SUGGESTION"}</text>
      <text x={350} y={94} fontSize={13} fontFamily="var(--font-mono)" fill="oklch(0.30 0.04 250)">+1 {isEs ? "cuadrilla" : "crew"}</text>
      <text x={350} y={114} fontSize={13} fontFamily="var(--font-mono)" fill="oklch(0.30 0.04 250)">{isEs ? "Zona" : "Zone"} C-3</text>
      <text x={350} y={138} fontSize={11} fontFamily="var(--font-mono)" fill="oklch(0.50 0.03 240)">conf. 0.89</text>
      <rect x={345} y={148} width={108} height={14} fill="var(--accent)" />
      <text x={399} y={159} textAnchor="middle" fontSize={10} fontFamily="var(--font-mono)" fill="white">{isEs ? "ACEPTAR" : "APPROVE"}</text>
      <text x={350} y={188} fontSize={10} fontFamily="var(--font-mono)" fill="oklch(0.40 0.03 240)" letterSpacing="0.08em">RECLAMOS / ZONA</text>
      {[0, 3, 6, 9].map((v, i) => (
        <g key={i}>
          <rect x={350 + i * 24} y={196} width={20} height={12} fill={colorFor(v)} />
          <text x={360 + i * 24} y={222} fontSize={10} fontFamily="var(--font-mono)" textAnchor="middle" fill="oklch(0.50 0.03 240)">{v}</text>
        </g>
      ))}
    </svg>
  );
}

function PavementMock({ isEs }) {
  return (
    <svg viewBox="0 0 480 300" style={{ width: "100%", height: "100%", display: "block" }}>
      <rect width={480} height={300} fill="oklch(0.18 0.03 245)" />
      <polygon points="0,300 480,300 340,140 140,140" fill="oklch(0.28 0.02 245)" />
      <polygon points="232,140 248,140 274,300 206,300" fill="oklch(0.34 0.02 245)" />
      <line x1={240} y1={150} x2={240} y2={166} stroke="white" strokeWidth={2} />
      <line x1={240} y1={180} x2={240} y2={196} stroke="white" strokeWidth={2} />
      <line x1={240} y1={216} x2={240} y2={236} stroke="white" strokeWidth={2} />
      <line x1={240} y1={258} x2={240} y2={282} stroke="white" strokeWidth={2} />
      <ellipse cx={155} cy={245} rx={22} ry={9} fill="oklch(0.16 0.02 245)" />
      <rect x={120} y={228} width={70} height={36} fill="none" stroke="oklch(0.65 0.18 35)" strokeWidth={2} strokeDasharray="4 3" />
      <text x={120} y={222} fontSize={11} fontFamily="var(--font-mono)" fill="oklch(0.65 0.18 35)">pothole · S3 · 0.91</text>
      <ellipse cx={355} cy={195} rx={14} ry={6} fill="oklch(0.16 0.02 245)" />
      <rect x={332} y={184} width={48} height={24} fill="none" stroke="oklch(0.68 0.16 75)" strokeWidth={2} strokeDasharray="4 3" />
      <text x={332} y={178} fontSize={11} fontFamily="var(--font-mono)" fill="oklch(0.68 0.16 75)">crack · S2 · 0.83</text>
      <rect x={0} y={0} width={480} height={32} fill="oklch(0.13 0.03 250)" />
      <text x={20} y={20} fontSize={11} fontFamily="var(--font-mono)" fill="var(--accent)">{isEs ? "RUTA 1 · KM 187.3 · 2 deterioros" : "ROUTE 1 · KM 187.3 · 2 damages"}</text>
      <text x={400} y={20} fontSize={11} fontFamily="var(--font-mono)" fill="oklch(0.65 0.18 145)">42 km/h</text>
    </svg>
  );
}

// ── Sección principal ────────────────────────────────────────────────────────
function PlatformModulesSection({ isEs }) {

  // 5 módulos, alineados al patrón pp-split del resto de la página
  const modules = isEs ? [
    {
      tag: "CATÁLOGO",
      title_a: "Definí los ", title_b: "servicios", title_c: " que ofrecés.",
      sub: "Cada servicio es la unidad mínima de oferta. Tipo de operación, frecuencia, ventana, recursos asignados y formularios — todo configurable por cliente, sin tocar código.",
      mock: <PMBrowser url="flow.gropp.tech/services"><ServicesMock isEs={isEs} /></PMBrowser>,
      flip: false, mist: false,
      modules: [
        { num: "01", title: "Tipo de servicio", body: "Recolección, barrido, riego, mantenimiento, pedidos B2B. Con frecuencia, ventana horaria y SLA propios.", chips: ["frecuencia", "SLA", "ventana"] },
        { num: "02", title: "Recursos por servicio", body: "Cantidad de asistentes, tipo de vehículo y equipamiento requerido. El sistema bloquea asignaciones inválidas en planificación.", chips: ["validación", "equipos", "cuadrilla"] },
        { num: "03", title: "Cámaras con IA y métricas", body: "Cámaras a bordo con inteligencia artificial detectan anomalías y servicios a realizar en tiempo real. Alimentan métricas multi-industria: kg recolectados, m² barridos, m³ regados, tiempo de servicio, km productivos.", chips: ["cámaras IA", "anomalías", "multi-industria"] },
        { num: "04", title: "Formularios configurables", body: "Adjuntás un formulario al servicio. El chofer lo completa en cabina al cierre — firmado, georreferenciado, exportable a PDF.", chips: ["en cabina", "firma", "PDF"] },
      ],
    },
    {
      tag: "PLANIFICACIÓN",
      title_a: "Planes operativos ", title_b: "recurrentes", title_c: ".",
      sub: "El despachador no arma el día desde cero. Definís plantillas semanales o mensuales y el sistema instancia el plan diario automáticamente, con choferes, vehículos y rutas reales.",
      mock: <PMBrowser url="flow.gropp.tech/operative-plans"><PlansMock isEs={isEs} /></PMBrowser>,
      flip: true, mist: true,
      modules: [
        { num: "01", title: "Plantilla recurrente", body: "Definís el patrón una vez ('Lun a Vie, 06:00, R-12, cuadrilla A'). El sistema genera el plan diario y lo deja editable.", chips: ["semanal", "mensual", "editable"] },
        { num: "02", title: "Plan diario en ejecución", body: "Turnos, conductores, asistentes, vehículos, rutas. Drag-and-drop entre filas; el sistema re-balancea en vivo.", chips: ["drag & drop", "live", "validación"] },
        { num: "03", title: "Pronóstico de fin de turno", body: "El motor predice cuándo termina cada ruta del plan, comparando con el histórico. Desviaciones detectadas antes de que afecten al cliente.", chips: ["IA", "ETA", "histórico"] },
        { num: "04", title: "Historial confiable", body: "Cada plan ejecutado se firma al cierre de turno. Fundamento para reclamos, facturación y disputas con el cliente.", chips: ["firmado", "auditoría", "facturación"] },
      ],
    },
    {
      tag: "GEOGRAFÍA",
      title_a: "Cargá, configurá y manejá tu ", title_b: "mapa operativo", title_c: ".",
      sub: "Rutas, secciones de calle, zonas y geocercas — todo dado de alta y editado desde el sistema, sin depender de planos en Excel ni KMLs sueltos. El cliente carga su geografía una vez y opera sobre ella.",
      mock: <PMBrowser url="flow.gropp.tech/routes/R-14"><RoutesMock isEs={isEs} /></PMBrowser>,
      flip: false, mist: false,
      modules: [
        { num: "01", title: "Rutas con paradas", body: "Secuencia ordenada de paradas o secciones, asociada a turno, periodicidad, total de paradas y próxima ejecución. Visible para chofer en cabina.", chips: ["paradas", "turno", "cabina"] },
        { num: "02", title: "Secciones de calle", body: "Tramos configurables — cuadras, manzanas, segmentos de avenida. Ideal para barrido, riego o limpieza, donde la unidad de trabajo es geográfica y no un punto.", chips: ["cuadras", "manzanas", "avenidas"] },
        { num: "03", title: "Zonas y geocercas", body: "Zonas agrupan paradas; geocercas disparan reglas (entrada, salida, tiempo dentro). Base para alertas, cobertura y municipios.", chips: ["polígonos", "reglas", "alertas"] },
      ],
    },
    {
      tag: "EMERGENTE",
      title_a: "Lo que ", title_b: "no estaba en el plan", title_c: ".",
      sub: "Reclamos del ciudadano, órdenes variables del cliente, eventos no programados. El sistema los absorbe en la operación del día sin romper la planificación.",
      mock: <PMBrowser url="flow.gropp.tech/emergent"><EmergentMock isEs={isEs} /></PMBrowser>,
      flip: true, mist: true,
      modules: [
        { num: "01", title: "Reclamos en pipeline", body: "Cuatro estados: gestión activa, agenda futura, pre-autorización y cierre. Cada reclamo se cierra con evento georreferenciado y opcionalmente foto.", chips: ["pipeline", "georef", "foto"] },
        { num: "02", title: "Reclamo → parada en ruta", body: "El despachador inserta un reclamo como parada en la ruta más cercana con un clic. El sistema recalcula ETA y notifica al chofer.", chips: ["1-clic", "re-ETA", "notificación"] },
        { num: "03", title: "Órdenes de trabajo variables", body: "Pedidos puntuales que no encajan en un servicio recurrente. Asignables a cuadrilla, con SLA propio y facturación independiente.", chips: ["B2B", "SLA propio", "facturación"] },
        { num: "04", title: "Eventos no planificados", body: "Retrasos, desvíos, paradas no agendadas, pérdida de tiempo justificada. Catalogados por tipo, fundamentan el análisis post-turno.", chips: ["pérdida tiempo", "justificación", "post-turno"] },
      ],
    },
    {
      tag: "REGLAS",
      title_a: "Reglas ", title_b: "customizables", title_c: " sin código.",
      sub: "El motor de eventos complejos empaquetado como recetario configurable por el cliente. Disparador, condiciones, ventana y acción — sin tocar Esper crudo.",
      mock: <PMBrowser url="flow.gropp.tech/rules"><RulesMock isEs={isEs} /></PMBrowser>,
      flip: false, mist: false,
      modules: [
        { num: "01", title: "Catálogo de recetas", body: "Recetas pre-armadas: frenada brusca, exceso de velocidad, salida de geocerca, sin descarga, parada prolongada. Toggle por cliente.", chips: ["pre-armadas", "toggle", "rápido"] },
        { num: "02", title: "Builder visual", body: "Constructor tipo Zapier para reglas custom. Disparador (telemetría, evento, geocerca) + condiciones + ventana temporal + acción.", chips: ["zapier-style", "no-code", "ventana"] },
        { num: "03", title: "Bandeja de alarmas", body: "Cada regla disparada genera alarma con vehículo, tipo, condición y motivo legible. Estados: nueva, vista, resuelta. Asignable a usuario.", chips: ["alarmas", "asignable", "estados"] },
        { num: "04", title: "Scope granular", body: "Reglas aplicables por vehículo, por tipo de servicio, por turno o por geocerca. Una regla con scope correcto reemplaza decenas duplicadas.", chips: ["por vehículo", "por turno", "por geocerca"] },
      ],
    },
  ] : [
    {
      tag: "CATALOG",
      title_a: "Define the ", title_b: "services", title_c: " you offer.",
      sub: "Every service is the minimum unit of offer. Operation type, frequency, time window, assigned resources and forms — all configurable per customer, no code.",
      mock: <PMBrowser url="flow.gropp.tech/services"><ServicesMock isEs={isEs} /></PMBrowser>,
      flip: false, mist: false,
      modules: [
        { num: "01", title: "Service type", body: "Collection, sweeping, irrigation, maintenance, B2B orders. With own frequency, time window and SLA.", chips: ["frequency", "SLA", "window"] },
        { num: "02", title: "Resources per service", body: "Number of assistants, vehicle type and required equipment. The system blocks invalid assignments at plan time.", chips: ["validation", "equipment", "crew"] },
        { num: "03", title: "AI cameras and metrics", body: "On-board AI cameras detect anomalies and services to perform in real time. They feed multi-industry metrics: kg collected, m² swept, m³ irrigated, service time, productive km.", chips: ["AI cameras", "anomalies", "multi-industry"] },
        { num: "04", title: "Configurable forms", body: "Attach a form to the service. Driver fills in-cabin at close — signed, georeferenced, exportable to PDF.", chips: ["in-cabin", "signature", "PDF"] },
      ],
    },
    {
      tag: "PLANNING",
      title_a: "Recurring ", title_b: "operative plans", title_c: ".",
      sub: "Dispatchers don't build the day from scratch. Define weekly or monthly templates and the system instantiates the daily plan with real drivers, vehicles and routes.",
      mock: <PMBrowser url="flow.gropp.tech/operative-plans"><PlansMock isEs={isEs} /></PMBrowser>,
      flip: true, mist: true,
      modules: [
        { num: "01", title: "Recurring template", body: "Define the pattern once ('Mon–Fri, 06:00, R-12, crew A'). The system generates the daily plan and leaves it editable.", chips: ["weekly", "monthly", "editable"] },
        { num: "02", title: "Live daily plan", body: "Shifts, drivers, assistants, vehicles, routes. Drag-and-drop between rows; the system re-balances live.", chips: ["drag & drop", "live", "validation"] },
        { num: "03", title: "Shift-end forecast", body: "The engine predicts each route's finish time, benchmarked against history. Catch deviations before they hit the customer.", chips: ["AI", "ETA", "history"] },
        { num: "04", title: "Reliable history", body: "Every executed plan is signed at shift close. Foundation for complaints, billing and customer disputes.", chips: ["signed", "audit", "billing"] },
      ],
    },
    {
      tag: "GEOGRAPHY",
      title_a: "Load, configure and manage your ", title_b: "operational map", title_c: ".",
      sub: "Routes, street sections, zones and geofences — all defined and edited from the system, no Excel maps or loose KMLs. The customer loads their geography once and operates on top of it.",
      mock: <PMBrowser url="flow.gropp.tech/routes/R-14"><RoutesMock isEs={isEs} /></PMBrowser>,
      flip: false, mist: false,
      modules: [
        { num: "01", title: "Routes with stops", body: "Ordered sequence of stops or sections, tied to shift, periodicity, total stops and next execution. Visible to driver in-cabin.", chips: ["stops", "shift", "in-cabin"] },
        { num: "02", title: "Street sections", body: "Configurable segments — city blocks, lots, avenue sub-stretches. Ideal for sweeping, irrigation or cleaning, where the unit of work is geographic, not a single point.", chips: ["blocks", "lots", "avenues"] },
        { num: "03", title: "Zones & geofences", body: "Zones group stops; geofences trigger rules (enter, exit, dwell). Foundation for alerts, coverage and municipalities.", chips: ["polygons", "rules", "alerts"] },
      ],
    },
    {
      tag: "EMERGENT",
      title_a: "What ", title_b: "wasn't in the plan", title_c: ".",
      sub: "Citizen complaints, variable customer orders, unscheduled events. The system absorbs them into the day's operation without breaking planning.",
      mock: <PMBrowser url="flow.gropp.tech/emergent"><EmergentMock isEs={isEs} /></PMBrowser>,
      flip: true, mist: true,
      modules: [
        { num: "01", title: "Complaint pipeline", body: "Four states: active management, future agenda, pre-authorization and close. Each closes with a georeferenced event and optional photo.", chips: ["pipeline", "geo", "photo"] },
        { num: "02", title: "Complaint → route stop", body: "Dispatcher inserts a complaint as a stop in the nearest route with one click. The system recalculates ETA and notifies the driver.", chips: ["1-click", "re-ETA", "notify"] },
        { num: "03", title: "Variable work orders", body: "One-off orders that don't fit a recurring service. Assignable to crew, with own SLA and independent billing.", chips: ["B2B", "own SLA", "billing"] },
        { num: "04", title: "Unplanned events", body: "Delays, deviations, off-agenda stops, justified loss-time. Cataloged by type, foundation for post-shift analysis.", chips: ["loss-time", "justify", "post-shift"] },
      ],
    },
    {
      tag: "RULES",
      title_a: "Customizable ", title_b: "rules", title_c: ", no code.",
      sub: "The complex-event engine packaged as a customer-configurable recipe book. Trigger, conditions, time window and action — no raw Esper.",
      mock: <PMBrowser url="flow.gropp.tech/rules"><RulesMock isEs={isEs} /></PMBrowser>,
      flip: false, mist: false,
      modules: [
        { num: "01", title: "Recipe catalog", body: "Pre-built recipes: hard braking, speeding, geofence breach, no dump, prolonged idle. Per-customer toggle.", chips: ["pre-built", "toggle", "fast"] },
        { num: "02", title: "Visual builder", body: "Zapier-style builder for custom rules. Trigger (telemetry, event, geofence) + conditions + time window + action.", chips: ["zapier-style", "no-code", "window"] },
        { num: "03", title: "Alarm inbox", body: "Each fired rule generates an alarm with vehicle, type, condition and human-readable reason. States: new, seen, resolved. Assignable.", chips: ["alarms", "assignable", "states"] },
        { num: "04", title: "Granular scope", body: "Rules per vehicle, per service type, per shift or per geofence. One rule with the right scope replaces dozens of duplicates.", chips: ["per vehicle", "per shift", "per geofence"] },
      ],
    },
  ];

  // ── 3 AI cases (live + pilot + proposed, all vehicle-mounted)
  const aiCases = isEs ? [
    {
      caseNum: "01", industry: "RESIDUOS · MUNICIPAL",
      title: "Detección automática de basura en vía pública",
      problem: "El supervisor dependía de denuncias y rondas manuales para detectar acumulación de basura, restos de poda, escombros o microbasurales. Cobertura espacial baja, latencia alta, evidencia frágil.",
      solution: "Modelo de visión sobre la cámara frontal del camión de recolección. Clasifica y localiza basura por tipo (orgánica, voluminosa, escombros, microbasural). Bounding boxes con score, asociados a ruta y kilómetro.",
      metrics: [{ num: "0.91", label: "PRECISIÓN MEDIA" }, { num: "+340 km", label: "MONITOREADOS / DÍA" }, { num: "−47%", label: "TIEMPO RESPUESTA" }],
      status: "live", mock: <LitterMock />, flip: false, mist: false,
    },
    {
      caseNum: "02", industry: "RESIDUOS · MUNICIPAL",
      title: "Predicción de demanda de servicios",
      problem: "Picos de reclamos en zonas y días específicos generaban sobrecarga puntual y rutas sub-dimensionadas. El plan operativo se ajustaba reactivamente, no anticipadamente.",
      solution: "Modelo de series temporales que combina histórico de reclamos, calendario (feriados, lluvia, recolección retrasada) y características de zona. Predice volumen por zona/día y sugiere refuerzo de cuadrilla en el plan.",
      metrics: [{ num: "0.89", label: "CONF. MEDIA" }, { num: "−31%", label: "RECLAMOS NO ATENDIDOS" }, { num: "+22%", label: "USO DE FLOTA" }],
      status: "pilot", mock: <DemandMock isEs={isEs} />, flip: true, mist: true,
    },
    {
      caseNum: "03", industry: "VIALIDAD · INFRAESTRUCTURA",
      title: "Detección de daño en pavimento",
      problem: "Inventario de daños (baches, fisuras, hundimientos) hecho con relevamientos manuales semestrales. Inversión de mantenimiento mal asignada por datos desactualizados.",
      solution: "Modelo de visión sobre cámaras de vehículos institucionales (basura, transporte, control). Cada paso registra y clasifica daños por severidad (S1–S3). El mapa de pavimento se actualiza solo, sin recorridos dedicados.",
      metrics: [{ num: "0.88", label: "F1 SCORE" }, { num: "12×", label: "FRECUENCIA RELEVAMIENTO" }, { num: "−54%", label: "COSTO INVENTARIO" }],
      status: "proposed", mock: <PavementMock isEs={isEs} />, flip: false, mist: false,
    },
  ] : [
    {
      caseNum: "01", industry: "WASTE · MUNICIPAL",
      title: "Automatic litter detection on public roads",
      problem: "Supervisors relied on citizen reports and manual patrols to detect litter, pruning waste, debris or illegal dumps. Low spatial coverage, high latency, fragile evidence.",
      solution: "Vision model on collection-truck dashcam. Classifies and localizes litter by type (organic, bulk, debris, dump). Bounding boxes with confidence score, tied to route and kilometer.",
      metrics: [{ num: "0.91", label: "MEAN PRECISION" }, { num: "+340 km", label: "MONITORED / DAY" }, { num: "−47%", label: "RESPONSE TIME" }],
      status: "live", mock: <LitterMock />, flip: false, mist: false,
    },
    {
      caseNum: "02", industry: "WASTE · MUNICIPAL",
      title: "Service demand forecasting",
      problem: "Complaint spikes in specific zones and days created localized overload and under-sized routes. The plan was adjusted reactively, never anticipated.",
      solution: "Time-series model combining complaint history, calendar features (holidays, rain, delayed collection) and zone characteristics. Predicts volume per zone/day and suggests crew reinforcement in the plan.",
      metrics: [{ num: "0.89", label: "MEAN CONF" }, { num: "−31%", label: "UNRESOLVED" }, { num: "+22%", label: "FLEET USE" }],
      status: "pilot", mock: <DemandMock isEs={isEs} />, flip: true, mist: true,
    },
    {
      caseNum: "03", industry: "ROADS · INFRASTRUCTURE",
      title: "Pavement damage detection",
      problem: "Damage inventory (potholes, cracks, sinkholes) built from semi-annual manual surveys. Maintenance investment misallocated by outdated data.",
      solution: "Vision model on cameras of institutional vehicles (waste, transit, monitoring). Every pass logs and classifies damage by severity (S1–S3). The pavement map updates itself, no dedicated surveys.",
      metrics: [{ num: "0.88", label: "F1 SCORE" }, { num: "12×", label: "SURVEY FREQ" }, { num: "−54%", label: "INVENTORY COST" }],
      status: "proposed", mock: <PavementMock isEs={isEs} />, flip: false, mist: false,
    },
  ];

  const aiHead = isEs ? {
    eyebrow: "// 05 · IA CUSTOMIZADA",
    title_a: "Modelos entrenados ", title_b: "para tu industria", title_c: ".",
    sub: "Gropp Flow es la plataforma; los modelos de IA son verticales. Cada cliente entrena modelos sobre sus propios datos — cámaras de su flota, telemetría, geometría — y los conecta a sus rutas, planes y reglas. Tres casos en operación de vehículos.",
  } : {
    eyebrow: "// 05 · CUSTOM AI",
    title_a: "Models trained ", title_b: "for your industry", title_c: ".",
    sub: "Gropp Flow is the platform; AI models are vertical. Each customer trains models on their own data — fleet cameras, telemetry, geometry — and wires them to routes, plans and rules. Three cases in vehicle operations.",
  };

  const statusLabel = (s, isEs) => s === "live" ? (isEs ? "EN PRODUCCIÓN" : "LIVE") : s === "pilot" ? (isEs ? "PILOTO" : "PILOT") : (isEs ? "PROPUESTO" : "PROPOSED");
  const statusColor = s => s === "live" ? "oklch(0.55 0.14 145)" : s === "pilot" ? "var(--accent)" : "oklch(0.65 0.18 35)";

  return (
    <>
      <style>{`
        .pmv-head { margin-bottom: 56px; max-width: 720px; padding: 100px 0 0; }
        .pmv-head h2 { font-size: clamp(32px, 4vw, 58px); letter-spacing: -0.025em; font-weight: 500; line-height: 1.04; margin: 12px 0 16px; }
        .pmv-head h2 .accent { color: var(--accent); }
        .pmv-head p { font-size: 16px; color: var(--fog); line-height: 1.65; }
        .pmv-section--ai .pmv-head h2 { color: var(--ink-2); }
        .pmv-section--ai .pmv-head p { color: oklch(0.72 0.03 240); }

        .pmv-section--ai { background: var(--ink); }

        .pmv-status { display: inline-block; font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.14em; border: 1px solid; border-radius: 3px; padding: 3px 8px; margin-left: 10px; vertical-align: middle; }
      `}</style>

      {/* SECCIÓN 04 — Módulos (sin head, arrancan directo) */}
      {modules.map((m, i) => (
        <section key={i} className={"pp-platform-section" + (m.mist ? " pp-platform-section--mist" : "")}>
          <div className="container">
            <div className={"pp-split" + (m.flip ? " pp-split--flip" : "")}>
              {m.flip ? (
                <>
                  <div className="pp-device">
                    <div className="pp-device-glow" />
                    {m.mock}
                  </div>
                  <div className="pp-modules">
                    <div>
                      <span className="pp-tag">{m.tag}</span>
                      <h2 className="pp-section-title">
                        {m.title_a}<span className="accent">{m.title_b}</span>{m.title_c}
                      </h2>
                      <p className="pp-section-sub" style={{ color: "var(--fog)" }}>{m.sub}</p>
                    </div>
                    {m.modules.map((mod, j) => <PMFeature key={j} {...mod} />)}
                  </div>
                </>
              ) : (
                <>
                  <div className="pp-modules">
                    <div>
                      <span className="pp-tag">{m.tag}</span>
                      <h2 className="pp-section-title">
                        {m.title_a}<span className="accent">{m.title_b}</span>{m.title_c}
                      </h2>
                      <p className="pp-section-sub" style={{ color: "var(--fog)" }}>{m.sub}</p>
                    </div>
                    {m.modules.map((mod, j) => <PMFeature key={j} {...mod} />)}
                  </div>
                  <div className="pp-device">
                    <div className="pp-device-glow" />
                    {m.mock}
                  </div>
                </>
              )}
            </div>
          </div>
        </section>
      ))}

      {/* SECCIÓN 05 — IA Customizada */}
      <div className="pmv-section--ai">
        <div className="container">
          <div className="pmv-head">
            <div className="eyebrow" style={{ color: "oklch(0.55 0.03 240)" }}>{aiHead.eyebrow}</div>
            <h2>{aiHead.title_a}<span className="accent">{aiHead.title_b}</span>{aiHead.title_c}</h2>
            <p>{aiHead.sub}</p>
          </div>
        </div>

        {aiCases.map((c, i) => (
          <section key={i} className="pp-platform-section pp-platform-section--dark" style={{ background: i % 2 === 1 ? "oklch(0.16 0.035 250)" : "var(--ink)" }}>
            <div className="container">
              <div className={"pp-split" + (c.flip ? " pp-split--flip" : "")}>
                {c.flip ? (
                  <>
                    <div className="pp-device">
                      <div className="pp-device-glow" />
                      <div style={{ width: 480, height: 300, borderRadius: 10, overflow: "hidden", border: "1px solid oklch(0.24 0.04 250)", boxShadow: "0 30px 80px -20px oklch(0.05 0.04 250 / 0.6)" }}>{c.mock}</div>
                    </div>
                    <AICaseText c={c} isEs={isEs} statusLabel={statusLabel} statusColor={statusColor} />
                  </>
                ) : (
                  <>
                    <AICaseText c={c} isEs={isEs} statusLabel={statusLabel} statusColor={statusColor} />
                    <div className="pp-device">
                      <div className="pp-device-glow" />
                      <div style={{ width: 480, height: 300, borderRadius: 10, overflow: "hidden", border: "1px solid oklch(0.24 0.04 250)", boxShadow: "0 30px 80px -20px oklch(0.05 0.04 250 / 0.6)" }}>{c.mock}</div>
                    </div>
                  </>
                )}
              </div>
            </div>
          </section>
        ))}
      </div>
    </>
  );
}

function AICaseText({ c, isEs, statusLabel, statusColor }) {
  return (
    <div className="pp-modules">
      <div>
        <span className="pp-tag" style={{ color: "var(--accent)" }}>{isEs ? "CASO" : "CASE"} {c.caseNum} · {c.industry}</span>
        <h2 className="pp-section-title" style={{ color: "var(--ink-2)" }}>
          {c.title}
          <span className="pmv-status" style={{ color: statusColor(c.status), borderColor: statusColor(c.status), background: "oklch(0.13 0.03 250)" }}>{statusLabel(c.status, isEs)}</span>
        </h2>
      </div>
      <PMFeatureDark num={isEs ? "PROBLEMA" : "PROBLEM"} body={c.problem} />
      <PMFeatureDark num={isEs ? "MODELO" : "MODEL"} body={c.solution} />
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12, paddingTop: 14, borderTop: "1px solid oklch(0.25 0.04 250)" }}>
        {c.metrics.map((m, i) => (
          <div key={i}>
            <div style={{ fontFamily: "var(--font-display)", fontSize: 26, fontWeight: 500, letterSpacing: "-0.025em", color: "var(--accent)", lineHeight: 1 }}>{m.num}</div>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 9, letterSpacing: "0.1em", color: "oklch(0.55 0.04 240)", marginTop: 6 }}>{m.label}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

function PMFeatureDark({ num, body }) {
  return (
    <div style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
      <div style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "var(--accent)", background: "color-mix(in oklch, var(--accent) 14%, transparent)", border: "1px solid color-mix(in oklch, var(--accent) 30%, transparent)", borderRadius: 4, padding: "3px 7px", flexShrink: 0, marginTop: 2, letterSpacing: "0.1em", whiteSpace: "nowrap" }}>{num}</div>
      <div style={{ fontSize: 13.5, color: "oklch(0.78 0.02 240)", lineHeight: 1.55 }}>{body}</div>
    </div>
  );
}

window.PlatformModulesSection = PlatformModulesSection;
