// kitel-screens.jsx — Kitel Estel · Peixateries (iOS app)
// Identidad fiel al logo: cian #009FE3 + tinta casi negra. Copy en catalán.
// Fotos reales del catálogo (assets/p/). Display hecho a mano (Shantell Sans) + sans limpia.

const K = {
  cyan: '#009FE3',
  cyanDeep: '#007BB5',
  cyanSoft: '#E2F4FC',
  cyanWash: '#F0FAFE',
  ink: '#14181B',
  inkSoft: '#2A3338',
  muted: '#5C6A72',
  faint: '#9AA7AE',
  line: '#E6ECEF',
  field: '#F2F6F8',
  white: '#FFFFFF',
  ok: '#1E9E6A',
};

const KB = '"Plus Jakarta Sans", -apple-system, system-ui, sans-serif';
const KD = '"Shantell Sans", "Plus Jakarta Sans", system-ui, sans-serif';

// ── White-label: deriva la paleta del color corporatiu de la botiga ───
function _hex(h) { h = String(h).replace('#', ''); return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16)); }
function _rgb(a) { return '#' + a.map((x) => Math.max(0, Math.min(255, Math.round(x))).toString(16).padStart(2, '0')).join(''); }
function _mix(c1, c2, t) { const a = _hex(c1), b = _hex(c2); return _rgb(a.map((x, i) => x + (b[i] - x) * t)); }
function _shade(c, t) { return t < 0 ? _mix(c, '#000000', -t) : _mix(c, '#ffffff', t); }

// Aplica el color de marca a la paleta (muta K, que es el que llegeixen les pantalles).
function applyBrand(brand) {
  const raw = brand && brand.primary_color;
  const primary = (typeof raw === 'string' && /^#[0-9a-fA-F]{6}$/.test(raw)) ? raw : '#009FE3';
  K.cyan = primary;
  K.cyanDeep = _shade(primary, -0.18);
  K.cyanSoft = _mix(primary, '#ffffff', 0.86);
  K.cyanWash = _mix(primary, '#ffffff', 0.94);
}
Object.assign(window, { applyBrand });

const LOGO_W = 'assets/kitel-estel-logo-white.png';
const FISH = 'assets/kitel-fish.png';
const FISH_W = 'assets/kitel-fish-white.png';
const PH = 'assets/p/';

// ── Foto de producte (cutout sobre fons clar) ─────────────────────────
function ProdImg({ p, style = {}, fit = 'contain', bg = K.cyanWash, pos = 'center' }) {
  return (
    <div style={{ overflow: 'hidden', background: bg, display: 'flex', alignItems: 'center', justifyContent: 'center', ...style }}>
      {p
        ? <img src={PH + p} alt="" style={{ width: '100%', height: '100%', objectFit: fit, objectPosition: pos, display: 'block' }} />
        : <span style={{ fontFamily: 'ui-monospace, monospace', fontSize: 10, color: K.faint }}>foto</span>}
    </div>
  );
}

function FishMark({ h = 34, white = false }) {
  const logo = window.STORE && window.STORE.brand && window.STORE.brand.logo_url;
  if (logo) {
    return <img src={logo} alt="" style={{ height: h, width: 'auto', display: 'block', objectFit: 'contain', ...(white ? { filter: 'brightness(0) invert(1)' } : {}) }} />;
  }
  return <img src={white ? FISH_W : FISH} alt="" style={{ height: h, width: 'auto', display: 'block' }} />;
}

function KBtn({ children, kind = 'primary', onClick }) {
  const base = { height: 56, borderRadius: 16, width: '100%', border: 'none', fontFamily: KB, fontSize: 17, fontWeight: 700, letterSpacing: -0.2, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, cursor: 'pointer' };
  const skin = {
    primary: { background: K.cyan, color: '#fff', boxShadow: '0 10px 24px rgba(0,159,227,0.32)' },
    dark: { background: K.ink, color: '#fff', boxShadow: '0 10px 24px rgba(20,24,27,0.25)' },
    ghost: { background: 'transparent', color: K.cyan },
    light: { background: '#fff', color: K.cyan, boxShadow: '0 10px 24px rgba(0,0,0,0.16)' },
  }[kind];
  return <button onClick={onClick} style={{ ...base, ...skin }}>{children}</button>;
}

function CartIcon({ count = 0, onClick }) {
  return (
    <div onClick={onClick} style={{ position: 'relative', width: 44, height: 44, borderRadius: 13, background: K.field, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
      <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
        <path d="M3 4h2l2.4 12.2a1.5 1.5 0 001.5 1.2h8.5a1.5 1.5 0 001.5-1.2L21 8H6" stroke={K.ink} strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round" />
        <circle cx="9.5" cy="20" r="1.3" fill={K.ink} /><circle cx="17.5" cy="20" r="1.3" fill={K.ink} />
      </svg>
      {count > 0 && (
        <div style={{ position: 'absolute', top: -4, right: -4, minWidth: 20, height: 20, padding: '0 5px', borderRadius: 10, background: K.cyan, color: '#fff', fontSize: 11, fontWeight: 800, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: KB, border: '2px solid #fff' }}>{count}</div>
      )}
    </div>
  );
}

function Stepper({ value, onDec, onInc }) {
  const btn = { width: 34, height: 34, borderRadius: 10, background: '#fff', border: `1.5px solid ${K.line}`, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', fontSize: 18, fontWeight: 700, color: K.cyan, userSelect: 'none' };
  const stop = (fn) => (e) => { e.stopPropagation(); if (fn) fn(); };
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
      <div className="tap" style={btn} onClick={stop(onDec)}>–</div>
      <span style={{ minWidth: 56, textAlign: 'center', fontSize: 16, fontWeight: 700, color: K.ink, fontFamily: KB }}>{value}</span>
      <div className="tap" style={{ ...btn, background: K.cyan, color: '#fff', border: 'none' }} onClick={stop(onInc)}>+</div>
    </div>
  );
}

function Screen({ children, bg = K.white }) {
  return <div style={{ height: '100%', background: bg, fontFamily: KB, color: K.ink, display: 'flex', flexDirection: 'column' }}>{children}</div>;
}
function Footer({ children, bg = '#fff', border = true }) {
  return <div style={{ padding: '14px 24px 38px', background: bg, borderTop: border ? `1px solid ${K.line}` : 'none', display: 'flex', flexDirection: 'column', gap: 10 }}>{children}</div>;
}
function H1({ children, color = K.ink }) {
  return <div style={{ fontFamily: KD, fontSize: 30, fontWeight: 600, letterSpacing: 0.2, lineHeight: 1.12, color, textWrap: 'pretty' }}>{children}</div>;
}
function BackBtn({ light = false, onClick }) {
  return (
    <div onClick={onClick} style={{ width: 40, height: 40, borderRadius: 12, background: light ? '#fff' : K.field, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, boxShadow: light ? '0 4px 12px rgba(0,0,0,0.10)' : 'none', cursor: 'pointer' }}>
      <svg width="11" height="18" viewBox="0 0 11 18" fill="none"><path d="M9 2L2 9l7 7" stroke={K.ink} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" /></svg>
    </div>
  );
}
function VacuumTag({ small = false }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, background: K.field, color: K.muted, fontSize: small ? 11 : 12, fontWeight: 700, padding: small ? '4px 9px' : '5px 11px', borderRadius: 8 }}>
      <svg width="12" height="12" viewBox="0 0 24 24" fill="none"><rect x="4" y="3" width="16" height="18" rx="3" stroke={K.cyanDeep} strokeWidth="2" /><path d="M8 9h8M8 13h8" stroke={K.cyanDeep} strokeWidth="2" strokeLinecap="round" /></svg>
      Envasat al buit
    </span>
  );
}
const eur = (n) => n.toFixed(2).replace('.', ',') + ' €';

// 14 al·lèrgens de declaració obligatòria (Reglament UE 1169/2011).
const ALLERGENS = {
  gluten: ['🌾', 'Gluten'], crustacis: ['🦐', 'Crustacis'], ous: ['🥚', 'Ous'], peix: ['🐟', 'Peix'],
  cacauets: ['🥜', 'Cacauets'], soja: ['🫘', 'Soja'], lactics: ['🥛', 'Lactis'], fruitsclosca: ['🌰', 'Fruits de closca'],
  api: ['🌿', 'Api'], mostassa: ['🟡', 'Mostassa'], sesam: ['🫓', 'Sèsam'], sulfits: ['🍷', 'Sulfits'],
  tramussos: ['🌱', 'Tramussos'], mollucs: ['🐚', 'Mol·luscs'],
};
// Enllaç a la fitxa pública de trazabilitat EtiQali a partir de la referència del lot.
function etiqaliLotUrl(ref) {
  var base = (window.KE_CONFIG && window.KE_CONFIG.etiqaliLotUrl) || 'https://etiqali.com/lot.html';
  var q = [];
  if (ref.lot) q.push('lot=' + encodeURIComponent(ref.lot));
  if (ref.cod) q.push('cod=' + encodeURIComponent(ref.cod));
  if (ref.emp) q.push('emp=' + encodeURIComponent(ref.emp));
  return base + '?' + q.join('&');
}
function fmtD(d) {
  if (!d) return '';
  var dt = new Date(String(d).length <= 10 ? d + 'T12:00:00' : d);
  if (isNaN(dt)) return String(d);
  return String(dt.getDate()).padStart(2, '0') + '/' + String(dt.getMonth() + 1).padStart(2, '0') + '/' + dt.getFullYear();
}
function TField({ label, value }) {
  if (!value) return null;
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, padding: '8px 0', borderBottom: '1px solid rgba(255,255,255,0.12)' }}>
      <span style={{ fontSize: 11.5, color: '#7ec8f7', fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4 }}>{label}</span>
      <span style={{ fontSize: 13.5, color: '#fff', fontWeight: 600, textAlign: 'right' }}>{value}</span>
    </div>
  );
}
// Bloc de trazabilitat EtiQali: carrega les dades reals del lot i les mostra.
function EtiqaliBlock({ refx }) {
  if (!refx || !refx.lot) return null;
  const [data, setData] = React.useState(null);
  const [open, setOpen] = React.useState(false);
  React.useEffect(() => {
    let alive = true;
    window.KEApi.etiqaliLot(refx).then((d) => { if (alive) setData(d); });
    return () => { alive = false; };
  }, [refx.lot]);

  const url = etiqaliLotUrl(refx);
  const qr = 'https://api.qrserver.com/v1/create-qr-code/?size=150x150&margin=0&data=' + encodeURIComponent(url);
  const p = data && data.p;
  const emp = data && data.emp;
  const chain = (data && data.chain) || [];
  const sector = (p && p.sector) || 'pesca';
  const l1 = sector === 'carn' ? 'Espècie' : sector === 'fruta' ? 'Varietat' : sector === 'xarcuteria' ? 'Tipus' : 'Zona FAO';
  const l2 = sector === 'carn' ? 'Nascut a' : sector === 'fruta' ? 'País origen' : sector === 'xarcuteria' ? 'Ingredient' : 'Art de pesca';
  const chainIcons = { origen: '🌊', intermediari: '🏭', majorista: '🏭', venedor: '🏪', comercio: '🏪' };

  return (
    <div style={{ marginTop: 18, background: '#073152', borderRadius: 16, padding: 16, color: '#fff' }}>
      <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
        <img src={qr} alt="QR" style={{ width: 66, height: 66, borderRadius: 10, background: '#fff', padding: 4, flexShrink: 0 }} />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: 1, color: '#7ec8f7' }}>🔗 TRAÇABILITAT ETIQALI</div>
          <div style={{ fontSize: 14, fontWeight: 700, marginTop: 3 }}>{(p && (p.nom_legal || p.nom_producte)) || ('Lot ' + refx.lot)}</div>
          {p && p.nom_cientific && <div style={{ fontSize: 12, fontStyle: 'italic', color: 'rgba(255,255,255,0.6)' }}>{p.nom_cientific}</div>}
        </div>
      </div>

      {p && (
        <div style={{ marginTop: 12 }}>
          <TField label="Nº Lot" value={p.num_lot || refx.lot} />
          {open && (<React.Fragment>
            <TField label={l1} value={p.zona} />
            <TField label={l2} value={p.art_pesca} />
            <TField label="Calibre" value={p.calibre} />
            <TField label="Barco" value={p.barco_nom} />
            <TField label="Matrícula" value={p.barco_matricula} />
            <TField label="Port" value={p.port} />
            <TField label="Data captura" value={fmtD(p.data_captura)} />
            <TField label="Data subasta" value={fmtD(p.data_desembarcament)} />
            <TField label="Cons. preferent" value={fmtD(p.data_caducitat)} />
            <TField label="Conservació" value={p.conservacio} />
            {chain.length > 1 && (
              <div style={{ marginTop: 12 }}>
                <div style={{ fontSize: 11.5, color: '#7ec8f7', fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 8 }}>Recorregut del producte</div>
                {chain.map((c, i) => (
                  <div key={i} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', padding: '4px 0' }}>
                    <span style={{ fontSize: 15 }}>{chainIcons[c.tipus] || '📦'}</span>
                    <div>
                      <div style={{ fontSize: 13, fontWeight: 700 }}>{c.etiqueta || (c.tipus === 'origen' ? 'Captura' : 'Distribució')}</div>
                      <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,0.6)' }}>{[c.zona, c.art_pesca, c.estat, fmtD(c.data_pas)].filter(Boolean).join(' · ')}</div>
                    </div>
                  </div>
                ))}
              </div>
            )}
            {emp && (
              <div style={{ marginTop: 10, fontSize: 12, color: 'rgba(255,255,255,0.75)' }}>
                {emp.nom}{emp.cif ? ' · CIF ' + emp.cif : ''}{emp.rgseaa ? ' · RGSEAA ES ' + emp.rgseaa : ''}
              </div>
            )}
          </React.Fragment>)}
        </div>
      )}

      <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
        {p && <button className="tap" onClick={() => setOpen((o) => !o)} style={{ flex: 1, border: 'none', background: 'rgba(46,134,206,0.4)', color: '#fff', fontSize: 13, fontWeight: 700, padding: '8px 10px', borderRadius: 9, cursor: 'pointer', fontFamily: KB }}>{open ? 'Amagar detalls' : 'Veure trazabilitat'}</button>}
        <a href={url} target="_blank" rel="noreferrer" style={{ flex: 1, textAlign: 'center', fontSize: 13, fontWeight: 700, color: '#fff', background: 'rgba(255,255,255,0.14)', padding: '8px 10px', borderRadius: 9, textDecoration: 'none' }}>Obrir fitxa / QR →</a>
      </div>
      <div style={{ marginTop: 10, fontSize: 10.5, lineHeight: 1.4, color: 'rgba(255,255,255,0.55)' }}>
        Dades de traçabilitat declarades pel comerç i registrades a EtiQali. EtiQali és una eina de registre de la cadena; no en verifica el contingut ni en garanteix la veracitat.
      </div>
    </div>
  );
}
function AllergenList({ items }) {
  if (!items || !items.length) return null;
  return (
    <div style={{ marginTop: 16 }}>
      <div style={{ fontSize: 13, fontWeight: 800, color: K.muted, marginBottom: 8, letterSpacing: 0.2 }}>{t('allergens')}</div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7 }}>
        {items.map((k) => { const a = ALLERGENS[k] || ['•', k]; return (
          <span key={k} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: K.field, color: K.inkSoft, fontSize: 12.5, fontWeight: 700, padding: '5px 10px', borderRadius: 8 }}>{a[0]} {a[1]}</span>
        ); })}
      </div>
    </div>
  );
}

// =====================================================================
// 1 · INICI
// =====================================================================
function ScreenHome({ nav = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();
  const quickAdd = (id) => cart.add((window.PROD_BY_ID && window.PROD_BY_ID[id]) || { id, n: id, price: 0, unit: 'kg' });
  const daily = window.DAILY || {};
  const items = (window.FEATURED && window.FEATURED.length)
    ? window.FEATURED
    : (window.CATALOG || []).flatMap((c) => c.products).slice(0, 4);
  return (
    <Screen>
      <div style={{ padding: '64px 24px 0' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <FishMark h={32} />
          <div style={{ flex: 1, lineHeight: 1 }}>
            <div style={{ fontFamily: KD, fontSize: 18, fontWeight: 600, letterSpacing: 0.4, color: K.ink }}>{((window.STORE && window.STORE.name) || 'Kitel Estel').toUpperCase()}</div>
            {(window.STORE && window.STORE.brand && window.STORE.brand.tagline) && (
              <div style={{ fontSize: 10, fontWeight: 800, letterSpacing: 3, color: K.cyan, marginTop: 2 }}>{String(window.STORE.brand.tagline).toUpperCase()}</div>
            )}
          </div>
          <CartIcon count={cart.count} onClick={() => go('cart')} />
        </div>
        <div style={{ marginTop: 18, height: 50, borderRadius: 14, background: K.field, display: 'flex', alignItems: 'center', padding: '0 16px', gap: 10 }}>
          <svg width="18" height="18" viewBox="0 0 20 20" fill="none"><circle cx="9" cy="9" r="6.5" stroke={K.faint} strokeWidth="2" /><path d="M14 14l4 4" stroke={K.faint} strokeWidth="2" strokeLinecap="round" /></svg>
          <span style={{ color: K.faint, fontSize: 15.5, fontWeight: 500 }}>{t('search')}</span>
        </div>
      </div>

      <div style={{ flex: 1, overflowY: nav.tab ? 'auto' : 'hidden', WebkitOverflowScrolling: 'touch', padding: nav.tab ? '18px 24px 96px' : '18px 24px 0' }}>
        {/* peix del dia · banner clar amb foto real */}
        <div onClick={() => go('daily')} style={{ borderRadius: 22, overflow: 'hidden', position: 'relative', height: 158, background: `linear-gradient(135deg, ${K.cyan}, ${K.cyanDeep})`, display: 'flex', cursor: 'pointer' }}>
          <div style={{ flex: 1, padding: '18px 0 18px 18px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
            <div style={{ display: 'inline-flex', alignSelf: 'flex-start', background: '#fff', color: K.cyanDeep, fontSize: 11, fontWeight: 800, padding: '4px 9px', borderRadius: 8, letterSpacing: 0.3, fontFamily: KD }}>{t('dayProduct')}</div>
            <div style={{ fontFamily: KD, fontSize: 23, fontWeight: 600, color: '#fff', letterSpacing: 0.2, marginTop: 8, lineHeight: 1.05 }}>{daily.n || 'Peix del dia'}</div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginTop: 6 }}>
              <span style={{ fontSize: 18, fontWeight: 800, color: '#fff' }}>{eur(daily.price || 0)}</span>
              <span style={{ fontSize: 12.5, color: 'rgba(255,255,255,0.75)', fontWeight: 600 }}>/{daily.unit || 'kg'}</span>
            </div>
          </div>
          <div style={{ width: 132, flexShrink: 0, padding: 12 }}>
            <ProdImg p={daily.p || 'sardina.jpeg'} fit="cover" bg="rgba(255,255,255,0.14)" style={{ width: '100%', height: '100%', borderRadius: 16 }} />
          </div>
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 18 }}>
          {[['Peix blanc', 'blanc', true], ['Peix blau', 'blau', false], ['Marisc', 'marisc', false], ['Cefalòpodes', 'cefal', false]].map(([t, id, on]) => (
            <div key={t} onClick={() => go('category', { cat: id })} style={{ padding: '9px 14px', borderRadius: 11, fontSize: 13, fontWeight: 700, background: on ? K.ink : K.field, color: on ? '#fff' : K.muted, whiteSpace: 'nowrap', cursor: 'pointer' }}>{t}</div>
          ))}
        </div>

        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginTop: 22, marginBottom: 12 }}>
          <div style={{ fontFamily: KD, fontSize: 20, fontWeight: 600, letterSpacing: 0.2 }}>{t('freshToday')}</div>
          <span onClick={() => go('categories')} style={{ fontSize: 13.5, fontWeight: 700, color: K.cyan, cursor: 'pointer' }}>{t('seeAll')}</span>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 13 }}>
          {items.map((it) => (
            <div key={it.n} onClick={() => go('product', { prod: it.id })} style={{ display: 'flex', alignItems: 'center', gap: 14, cursor: 'pointer' }}>
              <ProdImg p={it.p} style={{ width: 60, height: 60, borderRadius: 14, flexShrink: 0 }} />
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 16, fontWeight: 700, color: K.ink }}>{it.n}</div>
                <div style={{ fontSize: 13, color: K.muted, fontWeight: 600, marginTop: 1 }}>{it.o}</div>
                <div style={{ fontSize: 15, fontWeight: 800, color: K.cyanDeep, marginTop: 3 }}>{eur(it.price)}<span style={{ fontSize: 12, color: K.faint, fontWeight: 600 }}> /{it.unit || 'kg'}</span></div>
              </div>
              <div onClick={(e) => { e.stopPropagation(); quickAdd(it.id); }} style={{ width: 38, height: 38, borderRadius: 12, background: K.cyanSoft, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 22, fontWeight: 700, color: K.cyanDeep, flexShrink: 0, cursor: 'pointer' }}>+</div>
            </div>
          ))}
        </div>
      </div>
    </Screen>
  );
}

// =====================================================================
// 2 · PEIX DEL DIA (destacat)
// =====================================================================
function ScreenDaily({ nav = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();
  const daily = window.DAILY || (window.PROD_BY_ID && window.PROD_BY_ID['sardina']) || { id: 'sardina', n: 'Peix del dia', price: 9.9, unit: 'kg', cuts: ['Sencera', 'Oberta en llom'] };
  const addDaily = () => { cart.add(daily, { qty: 0.5, cut: (daily.cuts && daily.cuts[0]) || '' }); go('cart'); };
  return (
    <Screen>
      <div style={{ position: 'relative', height: 392, flexShrink: 0, background: `linear-gradient(165deg, ${K.cyanSoft}, ${K.cyanWash})` }}>
        <ProdImg p={daily.p || 'sardina.jpeg'} fit="cover" bg="transparent" style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'absolute', top: 64, left: 24, right: 24, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <BackBtn light onClick={() => (nav.back || go).call(null, 'home')} />
          <div style={{ background: 'rgba(255,255,255,0.94)', color: K.ink, fontSize: 12.5, fontWeight: 700, padding: '7px 13px', borderRadius: 11, boxShadow: '0 4px 12px rgba(0,0,0,0.08)' }}>Dimecres · 29 maig</div>
        </div>
      </div>

      <div style={{ flex: 1, background: '#fff', borderRadius: '26px 26px 0 0', marginTop: -26, padding: '20px 24px 0', position: 'relative', overflow: 'hidden' }}>
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: K.cyan, color: '#fff', fontSize: 12, fontWeight: 800, padding: '6px 12px', borderRadius: 10, letterSpacing: 0.4, fontFamily: KD, marginBottom: 12 }}>
          <FishMark h={15} white /> {t('dayProduct')}
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
          <H1>{daily.n || 'Peix del dia'}</H1>
          <div style={{ textAlign: 'right', flexShrink: 0 }}>
            <div style={{ fontSize: 24, fontWeight: 800, color: K.cyanDeep, lineHeight: 1 }}>{eur(daily.price || 0)}</div>
            <div style={{ fontSize: 12.5, color: K.faint, fontWeight: 600 }}>/{daily.unit || 'kg'}</div>
          </div>
        </div>
        <div style={{ fontSize: 14.5, color: K.muted, lineHeight: 1.5, fontWeight: 500, marginTop: 10 }}>
          {daily.desc || 'Peix fresc arribat avui de la llotja.'}
        </div>

        <div style={{ display: 'flex', gap: 10, marginTop: 18 }}>
          {[['Llotja', 'Palamós'], ['Arribada', '07:40 avui'], ['Mida', 'Mitjana']].map(([l, v]) => (
            <div key={l} style={{ flex: 1, background: K.field, borderRadius: 13, padding: '11px 12px' }}>
              <div style={{ fontSize: 11, color: K.muted, fontWeight: 700, letterSpacing: 0.2 }}>{l}</div>
              <div style={{ fontSize: 14, color: K.ink, fontWeight: 800, marginTop: 3 }}>{v}</div>
            </div>
          ))}
        </div>

        <div style={{ marginTop: 16, display: 'flex', gap: 12, alignItems: 'flex-start', background: K.cyanSoft, borderRadius: 14, padding: '14px 15px' }}>
          <FishMark h={24} />
          <div>
            <div style={{ fontSize: 13, fontWeight: 800, color: K.cyanDeep }}>Suggeriment del peixater</div>
            <div style={{ fontSize: 13, color: K.cyanDeep, fontWeight: 600, lineHeight: 1.4, marginTop: 2, opacity: 0.92 }}>Les netegem sense cap cost. Demana-les obertes en llom per a la planxa.</div>
          </div>
        </div>
      </div>

      <Footer>
        <KBtn onClick={addDaily}><span style={{ display: 'flex', alignItems: 'center', gap: 10 }}>{t('addToCart')}<span style={{ opacity: 0.55 }}>·</span>0,5 kg · {eur(daily.price * 0.5)}</span></KBtn>
      </Footer>
    </Screen>
  );
}

// =====================================================================
// 3 · CATEGORIES (graella)
// =====================================================================
function ScreenCategories({ nav = {} }) {
  const go = nav.go || (() => {});
  const cats = (window.CATALOG || []).map((c) => ({ id: c.id, n: c.n, c: c.products.length, p: c.cover, note: c.note }));
  return (
    <Screen>
      <div style={{ padding: '64px 24px 0' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <BackBtn onClick={() => (nav.back || go).call(null, 'home')} />
          <H1>{t('categories')}</H1>
        </div>
        <div style={{ marginTop: 16, height: 50, borderRadius: 14, background: K.field, display: 'flex', alignItems: 'center', padding: '0 16px', gap: 10 }}>
          <svg width="18" height="18" viewBox="0 0 20 20" fill="none"><circle cx="9" cy="9" r="6.5" stroke={K.faint} strokeWidth="2" /><path d="M14 14l4 4" stroke={K.faint} strokeWidth="2" strokeLinecap="round" /></svg>
          <span style={{ color: K.faint, fontSize: 15.5, fontWeight: 500 }}>{t('search')}</span>
        </div>
      </div>

      <div style={{ flex: 1, overflowY: nav.tab ? 'auto' : 'hidden', WebkitOverflowScrolling: 'touch', padding: nav.tab ? '18px 24px 96px' : '18px 24px 0' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          {cats.map((cat) => (
            <div key={cat.id} onClick={() => go('category', { cat: cat.id })} style={{ borderRadius: 18, overflow: 'hidden', border: `1.5px solid ${K.line}`, background: '#fff', cursor: 'pointer' }}>
              <ProdImg p={cat.p} style={{ height: 78 }} />
              <div style={{ padding: '10px 12px 12px' }}>
                <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 6 }}>
                  <div style={{ fontFamily: KD, fontSize: 15.5, fontWeight: 600, color: K.ink, lineHeight: 1.05, letterSpacing: 0.2 }}>{cat.n}</div>
                  <div style={{ fontSize: 11.5, fontWeight: 800, color: K.cyan, flexShrink: 0 }}>{cat.c}</div>
                </div>
                <div style={{ fontSize: 10.5, color: K.muted, fontWeight: 600, marginTop: 4, lineHeight: 1.2 }}>{cat.note}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </Screen>
  );
}

// =====================================================================
// 4 · CATEGORIA OBERTA (Peix blau · scroll)
// =====================================================================
function ScreenCategory({ nav = {}, params = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();
  const quickAdd = (id) => cart.add((window.PROD_BY_ID && window.PROD_BY_ID[id]) || { id, n: id, price: 0, unit: 'kg' });
  const cat = (window.CAT_BY_ID && window.CAT_BY_ID[params.cat]) || (window.CATALOG && window.CATALOG[0]) || { n: 'Categoria', products: [] };
  const items = cat.products;
  return (
    <Screen>
      <div style={{ padding: '64px 24px 0', flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <BackBtn onClick={() => (nav.back || go).call(null, 'categories')} />
          <div style={{ flex: 1 }}><H1>{cat.n}</H1></div>
          <CartIcon count={cart.count} onClick={() => go('cart')} />
        </div>
        <div style={{ fontSize: 13.5, color: K.muted, fontWeight: 600, marginTop: 6 }}>{items.length} {items.length === 1 ? 'producte' : 'productes'} · pescat a diari</div>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', padding: '18px 24px 24px' }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {items.map((it) => (
            <div key={it.id} onClick={() => go('product', { prod: it.id })} style={{ display: 'flex', alignItems: 'center', gap: 14, cursor: 'pointer' }}>
              <div style={{ position: 'relative', flexShrink: 0 }}>
                <ProdImg p={it.p} pos={it.pos || 'center'} style={{ width: 64, height: 64, borderRadius: 15 }} />
                {it.tag && <div style={{ position: 'absolute', top: -6, left: -4, background: K.cyan, color: '#fff', fontSize: 9.5, fontWeight: 800, padding: '3px 7px', borderRadius: 7, whiteSpace: 'nowrap' }}>{it.tag}</div>}
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 16, fontWeight: 700, color: K.ink }}>{it.n}</div>
                <div style={{ fontSize: 13, color: K.muted, fontWeight: 600, marginTop: 1 }}>{it.o}</div>
                <div style={{ fontSize: 15, fontWeight: 800, color: K.cyanDeep, marginTop: 3 }}>{eur(it.price)}<span style={{ fontSize: 12, color: K.faint, fontWeight: 600 }}> /{it.unit || 'kg'}</span></div>
              </div>
              <div onClick={(e) => { e.stopPropagation(); quickAdd(it.id); }} style={{ width: 38, height: 38, borderRadius: 12, background: K.cyanSoft, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 22, fontWeight: 700, color: K.cyanDeep, flexShrink: 0, cursor: 'pointer' }}>+</div>
            </div>
          ))}
        </div>
      </div>
    </Screen>
  );
}

// =====================================================================
// 5 · LOTS SETMANALS
// =====================================================================
function ScreenBundles({ nav = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();
  const addLot = (lot) => { cart.add({ id: lot.id, n: lot.n, price: lot.price, unit: lot.unit || 'ud', p: (lot.images && lot.images[0]) || lot.p }, { qty: 1 }); go('cart'); };
  const lots = window.BUNDLES || [];
  return (
    <Screen>
      <div style={{ padding: '64px 24px 0', flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <BackBtn onClick={() => (nav.back || go).call(null, 'home')} />
          <H1>Lots setmanals</H1>
        </div>
        <div style={{ fontSize: 14.5, color: K.muted, fontWeight: 500, lineHeight: 1.45, marginTop: 8 }}>
          Rep una selecció de peix fresc cada setmana. El peixater tria el millor de la llotja.
        </div>
        <div style={{ display: 'flex', gap: 8, background: K.field, padding: 4, borderRadius: 14, marginTop: 16 }}>
          {['Cada setmana', 'Una sola vegada'].map((t, i) => (
            <div key={t} style={{ flex: 1, height: 42, borderRadius: 11, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, fontWeight: 700, background: i === 0 ? K.cyan : 'transparent', color: i === 0 ? '#fff' : K.muted }}>{t}</div>
          ))}
        </div>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', padding: nav.tab ? '16px 24px 96px' : '16px 24px 24px' }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {lots.map((lot) => (
              <div key={lot.id} style={{ borderRadius: 20, overflow: 'hidden', border: `1.5px solid ${lot.tag ? K.cyan : K.line}`, background: '#fff' }}>
              <div style={{ display: 'flex', gap: 2, height: 96, background: K.cyanWash }}>
                {(lot.images || []).map((p, i) => <ProdImg key={i} p={p} style={{ flex: 1, height: '100%' }} />)}
              </div>
              <div style={{ padding: '14px 16px 16px' }}>
                <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10 }}>
                  <div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <div style={{ fontFamily: KD, fontSize: 19, fontWeight: 600, color: K.ink, letterSpacing: 0.2 }}>{lot.n}</div>
                      {lot.tag && <span style={{ background: K.cyanSoft, color: K.cyanDeep, fontSize: 10.5, fontWeight: 800, padding: '3px 8px', borderRadius: 7 }}>{lot.tag}</span>}
                    </div>
                    <div style={{ fontSize: 13, color: K.muted, fontWeight: 600, marginTop: 3 }}>{lot.subtitle}</div>
                  </div>
                  <div style={{ textAlign: 'right', flexShrink: 0 }}>
                    <div style={{ fontSize: 20, fontWeight: 800, color: K.cyanDeep, lineHeight: 1 }}>{eur(lot.price)}</div>
                    <div style={{ fontSize: 11.5, color: K.faint, fontWeight: 600, marginTop: 2 }}>/setmana</div>
                  </div>
                </div>
                <button onClick={() => addLot(lot)} style={{ marginTop: 14, height: 46, borderRadius: 13, width: '100%', border: 'none', background: lot.tag ? K.cyan : K.field, color: lot.tag ? '#fff' : K.ink, fontFamily: KB, fontSize: 15, fontWeight: 700, cursor: 'pointer' }}>
                  {lot.tag ? 'Subscriure-m\'hi' : 'Afegir el lot'}
                </button>
              </div>
            </div>
          ))}
        </div>
      </div>
    </Screen>
  );
}

// =====================================================================
// 6 · PRODUCTE
// =====================================================================
function ScreenProduct({ nav = {}, params = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();
  const prod = (window.PROD_BY_ID && window.PROD_BY_ID[params.prod]) || (window.PROD_BY_ID && window.PROD_BY_ID['llobarro']) || { n: 'Producte', p: 'lubina.jpeg', price: 0, o: '', desc: '', cuts: ['Sencer', 'Filet'] };
  const cortes = prod.cuts || ['Sencer', 'Filet'];
  const unit = prod.unit || 'kg';
  const step = cartStepFor(unit);
  const [cutIdx, setCutIdx] = React.useState(Math.min(1, cortes.length - 1));
  const [qty, setQty] = React.useState(unit === 'kg' ? 1 : 1);
  const lineTotal = prod.price * qty;
  const addToCart = () => {
    cart.add(prod, { qty, cut: cortes[cutIdx] });
    go('cart');
  };
  return (
    <Screen>
      <div style={{ position: 'relative', height: 360, flexShrink: 0, background: `linear-gradient(165deg, ${K.cyanSoft}, ${K.cyanWash})` }}>
        <ProdImg p={prod.p} fit="cover" bg="transparent" pos={prod.pos || 'center'} style={{ position: 'absolute', inset: 0 }} />
        <div style={{ position: 'absolute', top: 64, left: 24, right: 24, display: 'flex', justifyContent: 'space-between' }}>
          <BackBtn light onClick={() => (nav.back || go).call(null, 'home')} />
          <div style={{ width: 40, height: 40, borderRadius: 12, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 4px 12px rgba(0,0,0,0.10)' }}>
            <svg width="19" height="19" viewBox="0 0 22 22"><path d="M11 5.5C9.8 3 6 2.8 4.6 5.4c-1 1.9-.3 4 1.4 5.6L11 16l5-5c1.7-1.6 2.4-3.7 1.4-5.6C16 2.8 12.2 3 11 5.5z" stroke={K.ink} strokeWidth="1.8" fill="none" /></svg>
          </div>
        </div>
      </div>

      <div style={{ flex: 1, background: '#fff', borderRadius: '26px 26px 0 0', marginTop: -26, padding: '22px 24px 0', position: 'relative', overflow: 'hidden' }}>
        <div style={{ display: 'flex', gap: 8, marginBottom: 10, flexWrap: 'wrap' }}>
          <span style={{ background: K.cyanSoft, color: K.cyanDeep, fontSize: 12, fontWeight: 800, padding: '5px 10px', borderRadius: 8 }}>● {prod.tag || 'Pescat avui'}</span>
          <VacuumTag />
        </div>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
          <H1>{prod.n}</H1>
          <div style={{ textAlign: 'right', flexShrink: 0 }}>
            <div style={{ fontSize: 24, fontWeight: 800, color: K.cyanDeep, lineHeight: 1 }}>{eur(prod.price)}</div>
            <div style={{ fontSize: 12.5, color: K.faint, fontWeight: 600 }}>/{unit} · {t('vatIncluded')}</div>
          </div>
        </div>
        <div style={{ fontSize: 14.5, color: K.muted, lineHeight: 1.5, fontWeight: 500, marginTop: 10 }}>
          {prod.desc}
        </div>
        <AllergenList items={prod.allergens} />
        <EtiqaliBlock refx={prod.etiqali} />
        {unit === 'kg' && <div style={{ fontSize: 12.5, color: K.faint, fontWeight: 600, marginTop: 12 }}>{t('pricePerKgNote')}</div>}

        <div style={{ fontSize: 13, fontWeight: 800, color: K.muted, marginTop: 22, marginBottom: 10, letterSpacing: 0.2 }}>{t('preparation')}</div>
        <div style={{ display: 'flex', gap: 8, background: K.field, padding: 4, borderRadius: 14 }}>
          {cortes.map((c, i) => (
            <div key={c} className="tap" onClick={() => setCutIdx(i)} style={{ flex: 1, height: 42, borderRadius: 11, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14.5, fontWeight: 700, cursor: 'pointer', background: i === cutIdx ? '#fff' : 'transparent', color: i === cutIdx ? K.ink : K.muted, boxShadow: i === cutIdx ? '0 2px 6px rgba(0,0,0,0.08)' : 'none' }}>{c}</div>
          ))}
        </div>

        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 22 }}>
          <div style={{ fontSize: 16, fontWeight: 700, color: K.ink }}>{t('quantity')}</div>
          <Stepper
            value={fmtQty(qty, unit)}
            onDec={() => setQty((q) => Math.max(step, +(q - step).toFixed(2)))}
            onInc={() => setQty((q) => +(q + step).toFixed(2))}
          />
        </div>
      </div>

      <Footer>
        <KBtn onClick={addToCart}><span style={{ display: 'flex', alignItems: 'center', gap: 10 }}>{t('addToCart')}<span style={{ opacity: 0.55 }}>·</span>{eur(lineTotal)}</span></KBtn>
      </Footer>
    </Screen>
  );
}

// =====================================================================
// 7 · CISTELLA
// =====================================================================
function ScreenCart({ nav = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();
  const rows = cart.items;

  if (rows.length === 0) {
    return (
      <Screen>
        <div style={{ padding: '64px 24px 8px', display: 'flex', alignItems: 'center', gap: 14 }}>
          <BackBtn onClick={() => (nav.back || go).call(null, 'home')} />
          <H1>{t('cartTitle')}</H1>
        </div>
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 14, padding: '0 40px', textAlign: 'center' }}>
          <div style={{ width: 84, height: 84, borderRadius: 26, background: K.field, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <svg width="38" height="38" viewBox="0 0 24 24" fill="none"><path d="M3 4h2l2.4 12.2a1.5 1.5 0 001.5 1.2h8.5a1.5 1.5 0 001.5-1.2L21 8H6" stroke={K.faint} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" /><circle cx="9.5" cy="20" r="1.4" fill={K.faint} /><circle cx="17.5" cy="20" r="1.4" fill={K.faint} /></svg>
          </div>
          <div style={{ fontFamily: KD, fontSize: 22, fontWeight: 600, color: K.ink }}>{t('emptyCart')}</div>
          <div style={{ fontSize: 14.5, color: K.muted, fontWeight: 500, lineHeight: 1.5 }}>{t('emptyCartSub')}</div>
        </div>
        <Footer><KBtn onClick={() => go('home')}>{t('seeProducts')}</KBtn></Footer>
      </Screen>
    );
  }

  return (
    <Screen>
      <div style={{ padding: '64px 24px 8px', display: 'flex', alignItems: 'center', gap: 14 }}>
        <BackBtn onClick={() => (nav.back || go).call(null, 'home')} />
        <H1>{t('cartTitle')}</H1>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', padding: '12px 24px 0' }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {rows.map((r) => (
            <div key={r.id + '·' + r.cut} style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
              <ProdImg p={r.image} style={{ width: 64, height: 64, borderRadius: 15, flexShrink: 0 }} />
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 15.5, fontWeight: 700 }}>{r.name}</div>
                <div style={{ fontSize: 13, color: K.muted, fontWeight: 600, marginTop: 2 }}>{[r.cut, fmtQty(r.qty, r.unit)].filter(Boolean).join(' · ')}</div>
                <div style={{ fontSize: 15, fontWeight: 800, color: K.ink, marginTop: 4 }}>{eur(r.price * r.qty)}</div>
              </div>
              <Stepper value={fmtQty(r.qty, r.unit)} onDec={() => cart.dec(r)} onInc={() => cart.inc(r)} />
            </div>
          ))}
        </div>

        <div style={{ marginTop: 20, display: 'flex', gap: 11, alignItems: 'center', background: K.cyanSoft, borderRadius: 14, padding: '13px 15px' }}>
          <FishMark h={22} />
          <div style={{ fontSize: 12.5, color: K.cyanDeep, fontWeight: 700, lineHeight: 1.35 }}>Envasat al buit: sense olor, sense aigua i no es crema al congelar.</div>
        </div>

        <div style={{ marginTop: 22, marginBottom: 20, display: 'flex', flexDirection: 'column', gap: 10 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 14.5, color: K.muted, fontWeight: 600 }}>
            <span>{t('subtotal')}</span><span style={{ color: K.ink, fontWeight: 700 }}>{eur(cart.subtotal)}</span>
          </div>
          <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 14.5, color: K.muted, fontWeight: 600 }}>
            <span>{t('shippingCold')}</span><span style={{ color: K.ink, fontWeight: 700 }}>{t('calcAtDelivery')}</span>
          </div>
          <div style={{ height: 1, background: K.line, margin: '4px 0' }} />
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span style={{ fontSize: 17, fontWeight: 800 }}>{t('total')}</span>
            <span style={{ fontFamily: KD, fontSize: 24, fontWeight: 600, color: K.cyanDeep }}>{eur(cart.subtotal)}</span>
          </div>
        </div>
      </div>

      <Footer><KBtn onClick={() => go('checkout')}>{t('continue')}</KBtn></Footer>
    </Screen>
  );
}

// =====================================================================
// 8 · LLIURAMENT I PAGAMENT
// =====================================================================
const DELIVERY_FEE = 3.9;

function ScreenCheckout({ nav = {} }) {
  const go = nav.go || (() => {});
  const cart = useCart();

  // Config de recogida/entrega editable desde el panel (settings.fulfillment).
  const ful = (window.STORE && window.STORE.fulfillment) || {};
  const canDelivery = ful.delivery !== false;
  const canPickup = ful.pickup !== false;
  const canCourier = !!(ful.courier && ful.courier.enabled);
  const courierLabel = (ful.courier && ful.courier.label) || t('express');
  const modes = [];
  if (canDelivery) modes.push(['delivery', t('delivery')]);
  if (canCourier) modes.push(['courier', courierLabel]);
  if (canPickup) modes.push(['pickup', t('pickup')]);
  const fulSlots = ful.slots || {};
  const needsAddress = (m) => m === 'delivery' || m === 'courier';
  const pay = (window.STORE && window.STORE.payments) || {};
  const canOnline = !!pay.enabled;

  const [mode, setMode] = React.useState(canDelivery ? 'delivery' : 'pickup');
  const [name, setName] = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [address, setAddress] = React.useState('');
  const [slot, setSlot] = React.useState(0);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState('');
  const [postal, setPostal] = React.useState('');
  const [payMethod, setPayMethod] = React.useState('person');   // 'person' | 'online'
  const [zoneInfo, setZoneInfo] = React.useState(null);   // resultat de deliverySlots(CP)
  const [courierInfo, setCourierInfo] = React.useState(null); // resultat de courierQuote(CP)

  // Reparto propio por CP: al escribir 5 dígitos, consulta franjas disponibles.
  React.useEffect(() => {
    if (mode !== 'delivery' || !/^\d{5}$/.test(postal)) { setZoneInfo(null); return; }
    let alive = true;
    window.KEApi.deliverySlots(postal).then((r) => { if (alive) { setZoneInfo(r); setSlot(0); } });
    return () => { alive = false; };
  }, [postal, mode]);

  // Missatgeria externa: al escribir 5 dígitos, cotiza el envío exprés.
  React.useEffect(() => {
    if (mode !== 'courier' || !/^\d{5}$/.test(postal)) { setCourierInfo(null); return; }
    let alive = true;
    window.KEApi.courierQuote(postal, Math.round(cart.subtotal * 100)).then((r) => { if (alive) setCourierInfo(r); });
    return () => { alive = false; };
  }, [postal, mode, cart.subtotal]);

  const defaultSlots = mode === 'delivery'
    ? [['Avui', '17–19h'], ['Avui', '19–21h'], ['Demà', '9–11h']]
    : [['Avui', '18:00'], ['Avui', '19:30'], ['Demà', '10:00']];
  var rawSlots = (mode === 'delivery' ? fulSlots.delivery : fulSlots.pickup);
  if (mode === 'delivery' && zoneInfo && zoneInfo.available && zoneInfo.slots && zoneInfo.slots.length) rawSlots = zoneInfo.slots;
  const slots = (rawSlots && rawSlots.length) ? rawSlots : defaultSlots;
  const outOfArea = mode === 'delivery' && /^\d{5}$/.test(postal) && zoneInfo && zoneInfo.available === false && zoneInfo.reason === 'out_of_area';
  // Missatgeria: disponibilitat i tarifa cotitzada per al CP.
  const courierReady = mode === 'courier' && courierInfo && courierInfo.available;
  const courierNoArea = mode === 'courier' && /^\d{5}$/.test(postal) && courierInfo && courierInfo.available === false;

  const feeCents = (zoneInfo && zoneInfo.delivery_fee_cents != null) ? zoneInfo.delivery_fee_cents : ful.delivery_fee_cents;
  const fee = mode === 'delivery'
    ? (feeCents != null ? feeCents / 100 : DELIVERY_FEE)
    : (mode === 'courier' && courierReady && courierInfo.fee_cents != null ? courierInfo.fee_cents / 100 : 0);
  const total = cart.subtotal + fee;

  const inputStyle = { width: '100%', height: 48, borderRadius: 13, border: `1.5px solid ${K.line}`, background: '#fff', padding: '0 15px', fontSize: 15.5, fontFamily: KB, color: K.ink, outline: 'none', boxSizing: 'border-box' };

  const submit = async () => {
    setError('');
    if (!name.trim() || !phone.trim()) { setError(t('errName')); return; }
    if (needsAddress(mode) && !address.trim()) { setError(t('errAddress')); return; }
    if (needsAddress(mode) && !/^\d{5}$/.test(postal)) { setError(t('errPostal')); return; }
    if (outOfArea) { setError(t('errOutArea')); return; }
    if (courierNoArea) { setError(t('errCourierArea')); return; }
    if (mode === 'courier' && !courierReady) { setError(t('errCourierWait')); return; }
    if (cart.items.length === 0) { setError(t('errEmptyCart')); return; }

    const [day, time] = slots[slot];
    const when = mode === 'courier' ? ('Enviament exprés · ~' + (courierInfo.eta_min || 60) + ' min') : (day + ' ' + time);
    const payload = {
      customer: { name: name.trim(), phone: phone.trim(), consent: true },
      fulfillment: {
        type: mode, time: when,
        address: needsAddress(mode) ? (address.trim() + (postal ? ' · ' + postal : '')) : '',
        postal: needsAddress(mode) ? postal : '',
      },
      payment: canOnline && payMethod === 'online' ? 'online' : 'person',
      success_url: (typeof location !== 'undefined' ? location.href.split('#')[0] : '') + '#paid',
      cancel_url: (typeof location !== 'undefined' ? location.href.split('#')[0] : '') + '#cancel',
      items: cart.items.map((it) => ({ product_id: it.id, qty: it.qty, unit: it.unit, note: it.cut, _price: it.price })),
    };

    setSubmitting(true);
    try {
      const order = await window.KEApi.createOrder(payload);
      // Pagament online live: redirigeix a la passarel·la (Stripe). Stub/persona: confirma.
      if (order && order.payment && order.payment.url) {
        cart.clear();
        setError(t('redirecting'));
        location.href = order.payment.url;
        return;
      }
      cart.clear();
      go('confirmed', { order, fulfillment: { mode, when: mode === 'courier' ? when : (day + ' · ' + time), address: address.trim() } });
    } catch (e) {
      setError(e.message || t('errSend'));
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Screen bg={K.field}>
      <div style={{ padding: '64px 24px 14px', display: 'flex', alignItems: 'center', gap: 14, background: K.field }}>
        <div className="tap" onClick={() => (nav.back || go).call(null, 'cart')} style={{ width: 40, height: 40, borderRadius: 12, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
          <svg width="11" height="18" viewBox="0 0 11 18" fill="none"><path d="M9 2L2 9l7 7" stroke={K.ink} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" /></svg>
        </div>
        <H1>{t('checkoutTitle')}</H1>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', padding: '6px 24px 20px' }}>
        <div style={{ display: 'flex', gap: 8, background: '#fff', padding: 4, borderRadius: 15, marginBottom: 16 }}>
          {modes.map(([m, lbl]) => (
            <div key={m} className="tap" onClick={() => { setMode(m); setSlot(0); }} style={{ flex: 1, height: 46, borderRadius: 11, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 700, textAlign: 'center', cursor: 'pointer', background: mode === m ? K.ink : 'transparent', color: mode === m ? '#fff' : K.muted, padding: '0 6px' }}>{lbl}</div>
          ))}
        </div>

        <div style={{ fontSize: 13, fontWeight: 800, color: K.muted, margin: '4px 0 10px', letterSpacing: 0.2 }}>{t('yourData')}</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <input style={inputStyle} placeholder={t('nameField')} value={name} onChange={(e) => setName(e.target.value)} />
          <input style={inputStyle} placeholder={t('phoneField')} inputMode="tel" value={phone} onChange={(e) => setPhone(e.target.value)} />
          {needsAddress(mode) && (
            <input style={inputStyle} placeholder={t('addressField')} value={address} onChange={(e) => setAddress(e.target.value)} />
          )}
          {needsAddress(mode) && (
            <input style={inputStyle} placeholder={t('postalField')} inputMode="numeric" maxLength={5} value={postal} onChange={(e) => setPostal(e.target.value.replace(/\D/g, ''))} />
          )}
        </div>
        {outOfArea && (
          <div style={{ marginTop: 12, background: '#FFF6E5', color: '#8A5A00', borderRadius: 12, padding: '11px 14px', fontSize: 13.5, fontWeight: 600 }}>
            {t('outAreaMsg')} {postal}. {t('outAreaMsg2')}
          </div>
        )}
        {courierNoArea && (
          <div style={{ marginTop: 12, background: '#FFF6E5', color: '#8A5A00', borderRadius: 12, padding: '11px 14px', fontSize: 13.5, fontWeight: 600 }}>
            {t('courierNoAreaMsg')} {postal}. {t('courierNoAreaMsg2')}
          </div>
        )}
        {mode === 'delivery' && zoneInfo && zoneInfo.available && zoneInfo.zone && (
          <div style={{ marginTop: 12, fontSize: 13, color: K.muted, fontWeight: 600 }}>{t('weDeliverTo')} <b style={{ color: K.ink }}>{zoneInfo.zone}</b>{zoneInfo.cutoff_time ? ' · ' + t('ordersBefore') + ' ' + String(zoneInfo.cutoff_time).slice(0, 5) : ''}.</div>
        )}
        {courierReady && (
          <div style={{ marginTop: 12, fontSize: 13, color: K.muted, fontWeight: 600 }}>{t('courierEta')} <b style={{ color: K.ink }}>{courierInfo.eta_min} {t('min')}</b> · {eur(fee)}.</div>
        )}

        {mode !== 'courier' && (<React.Fragment>
        <div style={{ fontSize: 13, fontWeight: 800, color: K.muted, margin: '22px 0 10px', letterSpacing: 0.2 }}>{mode === 'delivery' ? t('deliverySlot') : t('pickupTime')}</div>
        <div style={{ display: 'flex', gap: 8 }}>
          {slots.map(([d, h], i) => {
            const on = i === slot;
            return (
              <div key={i} className="tap" onClick={() => setSlot(i)} style={{ flex: 1, padding: '12px 8px', borderRadius: 13, textAlign: 'center', cursor: 'pointer', background: on ? K.cyan : '#fff', border: on ? 'none' : `1.5px solid ${K.line}` }}>
                <div style={{ fontSize: 12.5, fontWeight: 600, color: on ? 'rgba(255,255,255,0.8)' : K.muted }}>{d}</div>
                <div style={{ fontSize: 14.5, fontWeight: 800, color: on ? '#fff' : K.ink, marginTop: 2 }}>{h}</div>
              </div>
            );
          })}
        </div>
        </React.Fragment>)}

        <div style={{ fontSize: 13, fontWeight: 800, color: K.muted, margin: '22px 0 10px', letterSpacing: 0.2 }}>{t('payment')}</div>
        {canOnline && (
          <div style={{ display: 'flex', gap: 8, background: '#fff', padding: 4, borderRadius: 14, marginBottom: 10 }}>
            {[['person', mode === 'pickup' ? t('payOnPickup') : t('payOnDelivery')], ['online', t('payOnline')]].map(([pm, lbl]) => (
              <div key={pm} className="tap" onClick={() => setPayMethod(pm)} style={{ flex: 1, height: 42, borderRadius: 11, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 700, textAlign: 'center', cursor: 'pointer', background: payMethod === pm ? K.cyan : 'transparent', color: payMethod === pm ? '#fff' : K.muted, padding: '0 6px' }}>{lbl}</div>
            ))}
          </div>
        )}
        <div style={{ background: '#fff', borderRadius: 16, padding: 16, display: 'flex', gap: 13, alignItems: 'center' }}>
          <div style={{ width: 38, height: 38, borderRadius: 11, background: K.cyanSoft, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M3 7h18v10H3z" stroke={K.cyanDeep} strokeWidth="1.8" /><path d="M3 10h18" stroke={K.cyanDeep} strokeWidth="1.8" /></svg>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 15, fontWeight: 700 }}>{canOnline && payMethod === 'online' ? t('payOnline') : (mode === 'pickup' ? t('payOnPickup') : t('payOnDelivery'))}</div>
            <div style={{ fontSize: 12.5, color: K.muted, fontWeight: 600 }}>{t('payMethodNote')}</div>
          </div>
        </div>

        {error && (
          <div style={{ marginTop: 16, background: '#FDECEC', color: '#C0392B', borderRadius: 12, padding: '12px 14px', fontSize: 13.5, fontWeight: 600 }}>{error}</div>
        )}
      </div>

      <Footer bg="#fff">
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 2 }}>
          <span style={{ fontSize: 14.5, color: K.muted, fontWeight: 600 }}>{mode === 'pickup' ? t('totalToPay') : t('subtotalShipping')}</span>
          <span style={{ fontFamily: KD, fontSize: 24, fontWeight: 600, color: K.ink }}>{eur(total)}</span>
        </div>
        <KBtn onClick={submitting ? undefined : submit}>{submitting ? t('sending') : t('confirmOrder')}</KBtn>
      </Footer>
    </Screen>
  );
}

// =====================================================================
// 9 · COMANDA CONFIRMADA
// =====================================================================
function ScreenConfirmed({ nav = {}, params = {} }) {
  const go = nav.go || (() => {});
  const order = params.order || { code: '#KE-0000' };
  const ful = params.fulfillment || {};
  const when = ful.when || '';
  return (
    <Screen bg={K.cyan}>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: '0 34px' }}>
        <div style={{ width: 132, height: 132, borderRadius: 40, background: 'rgba(255,255,255,0.16)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 26 }}>
          <div style={{ width: 96, height: 96, borderRadius: 30, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <svg width="46" height="46" viewBox="0 0 24 24" fill="none"><path d="M4 12.5l5 5L20 6.5" stroke={K.cyan} strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </div>
        </div>
        <div style={{ fontFamily: KD, fontSize: 32, fontWeight: 600, letterSpacing: 0.2, color: '#fff', marginBottom: 12 }}>{t('orderConfirmed')}</div>
        <div style={{ fontSize: 16.5, color: 'rgba(255,255,255,0.9)', lineHeight: 1.5, fontWeight: 500, maxWidth: 295 }}>
          {t('thanks')} · <strong style={{ color: '#fff' }}>{order.code}</strong>. {t('preparing')}.{when ? ' ' : ''}{when && <strong style={{ color: '#fff' }}>{when}</strong>}
        </div>
        <div style={{ marginTop: 30 }}><FishMark h={30} white /></div>
      </div>
      <Footer bg="transparent" border={false}>
        <KBtn kind="light" onClick={() => go('tracking', { order })}>{t('trackOrder')}</KBtn>
        <KBtn kind="ghost" onClick={() => go('home')}><span style={{ color: 'rgba(255,255,255,0.9)' }}>{t('backHome')}</span></KBtn>
      </Footer>
    </Screen>
  );
}

// =====================================================================
// 10 · SEGUIMENT
// =====================================================================
function ScreenTracking({ nav = {}, params = {} }) {
  const go = nav.go || (() => {});
  const order = params.order || { code: '#KE-2048' };
  const steps = [
    [t('orderReceived'), '16:32', 'done'],
    [t('preparing'), '16:40', 'active'],
    [t('inDelivery'), '—', 'todo'],
    [t('delivered'), '—', 'todo'],
  ];
  return (
    <Screen>
      <div style={{ position: 'relative', height: 240, flexShrink: 0 }}>
        <div style={{ position: 'absolute', inset: 0, background: 'repeating-linear-gradient(135deg,#DCEEF6 0 12px,#E9F5FB 12px 24px)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <span style={{ fontFamily: 'ui-monospace, monospace', fontSize: 11, color: 'rgba(0,123,181,0.5)' }}>mapa · ruta de repartiment</span>
        </div>
        <div style={{ position: 'absolute', top: 64, left: 24 }}><BackBtn light onClick={() => go('home')} /></div>
      </div>

      <div style={{ flex: 1, background: '#fff', borderRadius: '26px 26px 0 0', marginTop: -26, padding: '24px 24px 0', position: 'relative' }}>
        <H1>{t('onTheWay')}</H1>
        <div style={{ fontSize: 14.5, color: K.muted, fontWeight: 600, marginTop: 4, marginBottom: 24 }}>{t('orderCode')} {order.code}</div>

        <div style={{ display: 'flex', flexDirection: 'column' }}>
          {steps.map(([t, time, st], i) => {
            const done = st === 'done', active = st === 'active';
            const dot = done ? K.ok : active ? K.cyan : K.line;
            return (
              <div key={t} style={{ display: 'flex', gap: 14, minHeight: i < 3 ? 54 : 'auto' }}>
                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                  <div style={{ width: 22, height: 22, borderRadius: 11, background: dot, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, boxShadow: active ? `0 0 0 5px ${K.cyanSoft}` : 'none' }}>
                    {done && <svg width="11" height="11" viewBox="0 0 12 12"><path d="M2 6l3 3 5-6" stroke="#fff" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>}
                    {active && <div style={{ width: 7, height: 7, borderRadius: 4, background: '#fff' }} />}
                  </div>
                  {i < 3 && <div style={{ width: 2, flex: 1, background: done ? K.ok : K.line, marginTop: 2 }} />}
                </div>
                <div style={{ paddingBottom: 12 }}>
                  <div style={{ fontSize: 15.5, fontWeight: 700, color: active || done ? K.ink : K.faint }}>{t}</div>
                  <div style={{ fontSize: 13, color: K.muted, fontWeight: 600, marginTop: 1 }}>{time}</div>
                </div>
              </div>
            );
          })}
        </div>

        <div style={{ marginTop: 8, background: K.field, borderRadius: 16, padding: 14, display: 'flex', alignItems: 'center', gap: 13 }}>
          <div style={{ width: 46, height: 46, borderRadius: 23, background: K.cyanSoft, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: KD, fontWeight: 600, color: K.cyanDeep, fontSize: 17 }}>J</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 15, fontWeight: 700 }}>Jordi M.</div>
            <div style={{ fontSize: 12.5, color: K.muted, fontWeight: 600 }}>El teu repartidor</div>
          </div>
          <div style={{ width: 44, height: 44, borderRadius: 14, background: K.cyan, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M5 4h3l1.5 4-2 1.5a11 11 0 005 5l1.5-2 4 1.5v3a2 2 0 01-2 2A15 15 0 013 6a2 2 0 012-2z" fill="#fff" /></svg>
          </div>
        </div>
      </div>
    </Screen>
  );
}

Object.assign(window, {
  ScreenHome, ScreenDaily, ScreenCategories, ScreenCategory, ScreenBundles,
  ScreenProduct, ScreenCart, ScreenCheckout, ScreenConfirmed, ScreenTracking,
});
