/* Michael Style — Prototype · Website sections (single-language with EN/ES toggle).
   Adapted from the DS website UI kit. Loaded via browser Babel; uses global React + DS namespace. */

const WEB = window.MichaelStyleDesignSystem_7fd21b;
const T = (lang, en, es) => (lang === 'ES' ? es : en);

/* —— Supabase backend (real data + auth) —— */
const SB_URL = 'https://akiyuodgslajoqajnijo.supabase.co';
const SB_ANON = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFraXl1b2Rnc2xham9xYWpuaWpvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODQ2NDU2NjYsImV4cCI6MjEwMDIyMTY2Nn0.OUW15fOko7pqS_HKYYY8GeTFWaCs5UTpNbexaghbcnY';
const sb = (window.supabase && window.supabase.createClient) ? window.supabase.createClient(SB_URL, SB_ANON, { auth: { persistSession: true, autoRefreshToken: true } }) : null;
window.sb = sb;

/* —— interactive, keyboard-operable before/after reveal —— */
function BeforeAfter({ lang, before = 'assets/hero-before.png', after = 'assets/work-fade.png', hint = true }) {
  const ref = React.useRef(null);
  const [pct, setPct] = React.useState(55);
  const [w, setW] = React.useState(0);
  React.useEffect(() => {
    if (!ref.current) return;
    const ro = new ResizeObserver(() => setW(ref.current.getBoundingClientRect().width));
    ro.observe(ref.current);
    setW(ref.current.getBoundingClientRect().width);
    return () => ro.disconnect();
  }, []);
  const dragging = React.useRef(false);
  const fromE = (e) => {
    const r = ref.current.getBoundingClientRect();
    const x = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
    setPct(Math.max(2, Math.min(98, (x / r.width) * 100)));
  };
  const onKey = (e) => {
    const step = e.shiftKey ? 10 : 3;
    if (e.key === 'ArrowLeft') { setPct((p) => Math.max(2, p - step)); e.preventDefault(); }
    else if (e.key === 'ArrowRight') { setPct((p) => Math.min(98, p + step)); e.preventDefault(); }
    else if (e.key === 'Home') { setPct(2); e.preventDefault(); }
    else if (e.key === 'End') { setPct(98); e.preventDefault(); }
  };
  const glyph = { position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' };
  const lbl = (extra) => ({ position: 'absolute', bottom: '14px', fontFamily: 'var(--font-mono)', fontSize: '0.58rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--bone)', background: 'rgba(0,0,0,.55)', padding: '5px 11px', borderRadius: '20px', backdropFilter: 'blur(5px)', ...extra });
  return (
    <div ref={ref}
      role="slider" tabIndex={0} aria-label={T(lang, 'Before and after comparison', 'Comparación antes y después')}
      aria-valuemin={0} aria-valuemax={100} aria-valuenow={Math.round(pct)} aria-valuetext={`${Math.round(pct)}% ${T(lang, 'before', 'antes')}`}
      onKeyDown={onKey}
      onPointerDown={(e) => { dragging.current = true; fromE(e); e.currentTarget.setPointerCapture(e.pointerId); }}
      onPointerMove={(e) => { if (dragging.current) fromE(e); }}
      onPointerUp={() => { dragging.current = false; }}
      style={{ position: 'relative', borderRadius: 'var(--radius-md)', overflow: 'hidden', border: '1px solid var(--bd-d2)', aspectRatio: '4/5', userSelect: 'none', touchAction: 'none', cursor: 'ew-resize' }}>
      <div style={{ position: 'absolute', inset: 0 }}>
        <img src={after} alt={T(lang, 'After', 'Después')} draggable={false} style={{ position: 'absolute', inset: 0, display: 'block', width: '100%', height: '100%', objectFit: 'cover' }} />
        <span style={lbl({ right: '14px', color: 'var(--accent)', zIndex: 4 })}>{T(lang, 'After · Fresh', 'Después · Fresco')}</span>
      </div>
      <div style={{ position: 'absolute', inset: 0, width: pct + '%', overflow: 'hidden' }}>
        <img src={before} alt={T(lang, 'Before', 'Antes')} draggable={false} style={{ position: 'absolute', top: 0, left: 0, height: '100%', display: 'block', width: w ? w + 'px' : '100%', objectFit: 'cover' }} />
        <span style={lbl({ left: '14px', zIndex: 4 })}>{T(lang, 'Before', 'Antes')}</span>
      </div>
      <div style={{ position: 'absolute', top: 0, bottom: 0, left: pct + '%', width: '2px', background: 'var(--accent)', transform: 'translateX(-1px)', zIndex: 6 }}>
        <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: '42px', height: '42px', borderRadius: '50%', background: 'var(--accent)', color: 'var(--on-accent)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '0.9rem', boxShadow: 'var(--shadow-knob)' }}>⟷</div>
      </div>
      {hint && <div style={{ position: 'absolute', top: '14px', left: '14px', fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', background: 'rgba(0,0,0,.5)', padding: '4px 9px', borderRadius: '20px', backdropFilter: 'blur(5px)' }}>{T(lang, 'Drag · or ← →', 'Arrastra · o ← →')}</div>}
    </div>
  );
}

/* —— Autoplay-muted video with a transparent sound toggle —— */
function SoundVideo({ src, videoStyle }) {
  const ref = React.useRef(null);
  const [on, setOn] = React.useState(false);
  const toggle = (e) => {
    e.preventDefault(); e.stopPropagation();
    const v = ref.current; if (!v) return;
    const next = !on;
    if (next) {
      document.querySelectorAll('video').forEach((o) => { if (o !== v) o.muted = true; });
      v.muted = false; v.volume = 1;
      const p = v.play(); if (p && p.catch) p.catch(() => {});
    } else { v.muted = true; }
    setOn(next);
  };
  return (
    <>
      <video ref={ref} src={src} autoPlay muted loop playsInline preload="auto" style={videoStyle} />
      <button onClick={toggle} aria-label={on ? 'Silenciar' : 'Activar sonido'} title={on ? 'Silenciar' : 'Activar sonido'}
        style={{ position: 'absolute', bottom: '12px', right: '12px', zIndex: 3, width: '38px', height: '38px', borderRadius: '50%', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: on ? 'rgba(61,105,255,.78)' : 'rgba(0,0,0,.3)', backdropFilter: 'blur(6px)', WebkitBackdropFilter: 'blur(6px)', border: '1px solid rgba(255,255,255,.3)', color: '#fff', cursor: 'pointer', transition: 'background var(--dur-fast) var(--ease-out)' }}>
        <window.Icon name={on ? 'sound' : 'mute'} size={17} />
      </button>
    </>
  );
}

function Hero({ onSmp, onBook, lang }) {
  const { Button } = WEB;
  useContent();
  return (
    <section id="top" style={{ background: 'var(--ink)', padding: '60px 30px 52px', scrollMarginTop: '150px' }} data-screen-label="Web · Hero">
      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1.05fr) minmax(0,.95fr)', gap: '38px', alignItems: 'center' }} className="ms-hero-grid">
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: '11px', color: 'var(--muted)', fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.13em', textTransform: 'uppercase' }}>{T(lang, 'Dominican Barber Studio · Houston TX', 'Barbería Dominicana · Houston TX')}</div>
          <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.4rem,6vw,4.4rem)', textTransform: 'uppercase', margin: '18px 0 0', lineHeight: 0.92, letterSpacing: '-0.04em', color: 'var(--bone)' }}>
            {lang === 'ES'
              ? <>Más que una<br /><span style={{ color: 'var(--accent)' }}>barbería.</span></>
              : <>More than a<br /><span style={{ color: 'var(--accent)' }}>barbershop.</span></>}
          </h1>
          <div style={{ fontSize: '1.1rem', color: 'var(--muted)', marginTop: '16px', fontStyle: 'italic' }}>{T(lang, 'Not just a cut: a complete experience.', 'No solo un corte: una experiencia completa.')}</div>
          <p style={{ color: 'var(--muted)', maxWidth: '46ch', margin: '14px 0 26px', fontSize: '0.94rem', lineHeight: 1.55 }}>{T(lang,
            'We specialize in unique personal-care experiences — traditional barbering and advanced men’s aesthetics, with personalized attention to bring out your best version in image, comfort, and confidence.',
            'Nos especializamos en experiencias únicas de cuidado personal — barbería tradicional y estética masculina avanzada, con atención personalizada para resaltar tu mejor versión en imagen, comodidad y confianza.')}</p>
          <div style={{ display: 'flex', gap: '11px', flexWrap: 'wrap' }}>
            <Button variant="fill" onClick={onBook}>{T(lang, 'Book a cut', 'Reservar corte')}</Button>
            <Button variant="line" onClick={onSmp}>{T(lang, 'Explore SMP', 'Conoce el SMP')}</Button>
          </div>
        </div>
        <div style={{ position: 'relative', borderRadius: 'var(--radius-md)', overflow: 'hidden', border: '1px solid var(--bd-d2)', aspectRatio: '4/5', background: '#000' }}>
          {(() => {
            const hero = loadJSON('ms_hero', null);
            if (hero && hero.type === 'image' && hero.src) return <img src={hero.src} alt="" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />;
            return <SoundVideo src={(hero && hero.type === 'video' && hero.src) || 'assets/hero.mp4'} videoStyle={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />;
          })()}
        </div>
      </div>
    </section>
  );
}

/* —— Services menu (bilingual) —— */
/* Price — the number is the second thing you read after the service name.
   The stored string is rendered verbatim (Michael types it himself); a leading
   "Desde"/"From" is only lifted into a small label so the number stays big. */
function Price({ value, size }) {
  if (!value) return null;
  const m = String(value).match(/^\s*(desde|from)\b\s*(.*)$/i);
  let label = m ? m[1] : '';
  let amount = m ? m[2].trim() : String(value).trim();
  if (!amount) { amount = label; label = ''; }
  return (
    <div style={{ lineHeight: 1 }}>
      {label && <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: '5px' }}>{label}</div>}
      <div style={{ fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: size === 'feat' ? '2rem' : '1.5rem', letterSpacing: '-0.01em', color: 'var(--accent)', lineHeight: 1 }}>{amount}</div>
    </div>
  );
}

function ServiceCard({ name, desc, price, onBook, lang, svc }) {
  const { Button } = WEB;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', background: 'var(--card)', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-md)', padding: '20px' }}>
      <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '1.05rem', textTransform: 'uppercase', letterSpacing: '-0.02em', color: 'var(--bone)', lineHeight: 1.05 }}>{name}</div>
      <p style={{ margin: '9px 0 0', fontSize: '0.84rem', color: 'var(--muted)', lineHeight: 1.5, flex: 1 }}>{desc}</p>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px', marginTop: '16px' }}>
        <Price value={price} />
        <Button variant="line" onClick={() => onBook(svc)}>{T(lang, 'Book', 'Reservar')}</Button>
      </div>
    </div>
  );
}

function ServicesSection({ lang, onBook }) {
  const { Button, Pill } = WEB;
  useContent();
  const price = T(lang, 'From $—', 'Desde $—');
  const vip = [
    ['Personalized haircut for your style & face shape', 'Corte de cabello personalizado según tu estilo y rostro'],
    ['Beard design & grooming', 'Diseño y arreglo de barba'],
    ['Eyebrow shaping', 'Perfilado de cejas'],
    ['Hair wash', 'Lavado de cabello'],
    ['Deep facial cleansing', 'Limpieza facial profunda'],
    ['Hot towel', 'Toalla caliente'],
    ['Ozone steam treatment', 'Tratamiento con vapor de ozono'],
    ['Relaxing massage', 'Masaje relajante'],
  ];
  const groups = [
    { title: T(lang, 'Barbershop', 'Barbería'), items: [
      { svc: 1, n: T(lang, 'Haircut + Beard + Eyebrows', 'Corte + Barba + Cejas'), d: T(lang, 'Full grooming: personalized cut, beard design, and eyebrow shaping for a clean, modern, defined look.', 'Servicio completo: corte personalizado, diseño de barba y perfilado de cejas para un estilo limpio, moderno y definido.') },
      { svc: 2, n: T(lang, 'Haircut', 'Corte de Cabello'), d: T(lang, 'Personalized cuts tailored to your style, personality, and needs — with professional finishes.', 'Cortes personalizados adaptados a tu estilo, personalidad y necesidades, con acabados profesionales.') },
      { svc: 3, n: T(lang, 'Beard Design & Cut', 'Diseño y Corte de Barba'), d: T(lang, 'Beard maintenance and definition — clean lines shaped to your face.', 'Mantenimiento y definición de barba, con líneas limpias acordes a la forma de tu rostro.') },
      { svc: 4, n: T(lang, 'Line-up / Shape-up', 'Cerquillo / Perfilado'), d: T(lang, 'Crisp lines, contours, and detailing to keep a fresh, sharp look.', 'Definición de líneas, contornos y detalles para una apariencia fresca y ordenada.') },
      { svc: 5, n: T(lang, 'Cuts for All Ages', 'Cortes para Todas las Edades'), d: T(lang, 'Kids, teens, and young adults — comfortable, current, high-precision styles for every age.', 'Niños, adolescentes y jóvenes — estilos cómodos, actuales y de alta precisión para cada edad.') },
    ] },
    { title: T(lang, 'Aesthetics', 'Estética'), items: [
      { svc: 6, n: T(lang, 'Scalp & Beard Micropigmentation', 'Micropigmentación Capilar y de Barba'), d: T(lang, 'Advanced technique that improves the look of density and definition where hair or beard is thinning — a natural, even, flattering effect.', 'Técnica avanzada que mejora la densidad y definición en zonas con pérdida de cabello o barba — un efecto natural, uniforme y favorecedor.') },
      { svc: 7, n: T(lang, 'Eyebrow Micropigmentation', 'Micropigmentación de Cejas'), d: T(lang, 'Eyebrow design and refinement with custom techniques: natural design, definition, and symmetry for your features.', 'Diseño y perfeccionamiento de cejas con técnicas personalizadas: diseño natural, definición y simetría según tu rostro.') },
    ] },
  ];
  const secHead = (
    <>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Services', 'Servicios')}</div>
      <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.2rem,5vw,3.4rem)', textTransform: 'uppercase', marginTop: '10px', letterSpacing: '-0.04em', color: 'var(--bone)', lineHeight: 0.92 }}>{T(lang, 'What we do.', 'Lo que hacemos.')}</h2>
      <p style={{ color: 'var(--muted)', maxWidth: '52ch', margin: '14px 0 0', fontSize: '0.95rem', lineHeight: 1.55 }}>{T(lang, 'Barbering and men’s aesthetics, done with precision and a personal touch.', 'Barbería y estética masculina, con precisión y un toque personal.')}</p>
    </>
  );
  const custom = loadJSON('ms_services', null);
  if (custom && custom.length) {
    const feat = custom.filter((s) => s.featured);
    const rest = custom.filter((s) => !s.featured);
    return (
      <section id="servicios" style={{ background: 'var(--ink)', padding: '64px 30px 70px', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · Servicios">
        {secHead}
        {feat.map((s) => (
          <div key={s.id} style={{ background: 'color-mix(in srgb,var(--accent) 12%,var(--card))', border: '1px solid color-mix(in srgb,var(--accent) 40%,transparent)', borderRadius: 'var(--radius-lg)', padding: '24px', marginTop: '26px' }}>
            <Pill variant="accent">{T(lang, 'Premium', 'Premium')}</Pill>
            <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(1.6rem,4vw,2.2rem)', textTransform: 'uppercase', letterSpacing: '-0.03em', lineHeight: 0.98, color: 'var(--bone)', margin: '12px 0 0' }}>{s.name}</div>
            {s.desc && <p style={{ color: 'var(--muted)', margin: '12px 0 0', fontSize: '0.94rem', lineHeight: 1.55, maxWidth: '46ch' }}>{s.desc}</p>}
            <div style={{ display: 'flex', alignItems: 'center', gap: '32px', marginTop: '22px', flexWrap: 'wrap' }}>
              <Price value={s.price} size="feat" />
              <Button variant="fill" onClick={onBook}>{T(lang, 'Book', 'Reservar')}</Button>
            </div>
          </div>
        ))}
        {rest.length > 0 && <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(250px,1fr))', gap: '12px', marginTop: '18px' }}>
          {rest.map((s) => <ServiceCard key={s.id} name={s.name} desc={s.desc} price={s.price} onBook={onBook} lang={lang} />)}
        </div>}
      </section>
    );
  }
  return (
    <section id="servicios" style={{ background: 'var(--ink)', padding: '64px 30px 70px', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · Servicios">
      {secHead}

      {/* VIP — featured premium package */}
      <div style={{ background: 'color-mix(in srgb,var(--accent) 12%,var(--card))', border: '1px solid color-mix(in srgb,var(--accent) 40%,transparent)', borderRadius: 'var(--radius-lg)', padding: '28px', marginTop: '26px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '30px', alignItems: 'center' }} className="ms-hero-grid">
          <div>
            <Pill variant="accent">{T(lang, 'Premium · Signature', 'Premium · Insignia')}</Pill>
            <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(1.8rem,4vw,2.6rem)', textTransform: 'uppercase', letterSpacing: '-0.03em', lineHeight: 0.95, color: 'var(--bone)', margin: '14px 0 0' }}>{T(lang, 'VIP Cut', 'Corte VIP')}<br /><span style={{ color: 'var(--accent)' }}>{T(lang, 'Premium Experience', 'Experiencia Premium')}</span></h3>
            <p style={{ color: 'var(--muted)', margin: '14px 0 0', fontSize: '0.94rem', lineHeight: 1.55, maxWidth: '42ch' }}>{T(lang, 'A complete service for those who want care, style, and relaxation in a single experience.', 'Un servicio completo para quienes buscan cuidado, estilo y relajación en una sola experiencia.')}</p>
            <div style={{ display: 'flex', alignItems: 'center', gap: '32px', marginTop: '22px', flexWrap: 'wrap' }}>
              <Price value={price} size="feat" />
              <Button variant="fill" onClick={() => onBook(0)}>{T(lang, 'Book the VIP', 'Reservar el VIP')}</Button>
            </div>
          </div>
          <div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', marginBottom: '12px' }}>{T(lang, 'Includes', 'Incluye')}</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 16px' }} className="ms-vip-grid">
              {vip.map(([en, es], i) => (
                <div key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
                  <span style={{ color: 'var(--accent)', flex: 'none', marginTop: '1px' }}><window.Icon name="check" size={15} /></span>
                  <span style={{ fontSize: '0.8rem', color: 'var(--bone)', lineHeight: 1.35 }}>{T(lang, en, es)}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* Service groups */}
      {groups.map((g) => (
        <div key={g.title} style={{ marginTop: '32px' }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--muted-2)', marginBottom: '14px' }}>{g.title}</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(250px,1fr))', gap: '12px' }}>
            {g.items.map((it) => <ServiceCard key={it.n} name={it.n} desc={it.d} price={price} onBook={onBook} lang={lang} svc={it.svc} />)}
          </div>
        </div>
      ))}
    </section>
  );
}

function SmpBento({ onSmp, onCal, lang }) {
  useContent(); // re-render when Michael publishes a new SMP video
  const smpVid = loadJSON('ms_smp_video', null);
  const benefit = { border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-md)', padding: '22px', background: 'var(--card)', color: 'var(--bone)' };
  const kk = { fontFamily: 'var(--font-mono)', fontSize: '0.55rem', textTransform: 'uppercase', letterSpacing: '0.13em', color: 'var(--accent)' };
  const bt = { fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '1.15rem', textTransform: 'uppercase', letterSpacing: '-0.02em', margin: '9px 0 6px' };
  const bp = { margin: 0, fontSize: '0.84rem', color: 'var(--muted)', lineHeight: 1.5 };
  return (
    <section id="smp" style={{ background: 'var(--ink)', color: 'var(--bone)', padding: '64px 30px 70px', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · SMP">
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Scalp Micropigmentation', 'Micropigmentación Capilar')}</div>
      <div style={{ display: 'grid', gridTemplateColumns: '1.1fr .9fr', gap: '40px', alignItems: 'center', marginTop: '18px' }} className="ms-hero-grid">
        <div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.4rem,5.5vw,4rem)', textTransform: 'uppercase', letterSpacing: '-0.04em', lineHeight: 0.92, margin: 0 }}>{lang === 'ES' ? <>Más densidad,<br />sin cirugía.</> : <>A fuller hairline,<br />no surgery.</>}</h2>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.74rem', color: 'var(--accent)', letterSpacing: '0.05em', marginTop: '18px' }}>{T(lang, 'From $X · 2–3 sessions · lasts years', 'Desde $X · 2–3 sesiones · dura años')}</div>
          <p style={{ color: 'var(--muted)', maxWidth: '46ch', margin: '14px 0 26px', fontSize: '0.95rem', lineHeight: 1.55 }}>{T(lang,
            'A private, non-surgical way to restore a full, natural hairline — built from your photos and your goal, across a few focused sessions.',
            'Una forma privada y sin cirugía de recuperar una línea capilar natural — diseñada a partir de tus fotos y tu objetivo, en pocas sesiones.')}</p>
          <div style={{ display: 'flex', gap: '11px', flexWrap: 'wrap' }}>
            <button onClick={() => onSmp(6)} style={{ fontFamily: 'var(--font-mono)', fontSize: '0.68rem', textTransform: 'uppercase', letterSpacing: '0.1em', color: 'var(--on-accent)', background: 'var(--accent)', padding: '14px 22px', borderRadius: 'var(--radius-pill)', border: 'none', cursor: 'pointer' }}>{T(lang, 'Start consultation', 'Empezar consulta')}</button>
            <button onClick={onCal} style={{ fontFamily: 'var(--font-mono)', fontSize: '0.68rem', textTransform: 'uppercase', letterSpacing: '0.1em', color: 'var(--bone)', background: 'transparent', padding: '14px 22px', borderRadius: 'var(--radius-pill)', border: '1px solid var(--bd-d2)', cursor: 'pointer' }}>{T(lang, 'See availability', 'Ver disponibilidad')}</button>
          </div>
        </div>
        <div style={{ position: 'relative', borderRadius: 'var(--radius-md)', border: '1px solid var(--bd-d2)', aspectRatio: '4/5', overflow: 'hidden', background: 'var(--ink-2, #111)' }}>
          <SoundVideo src={(smpVid && smpVid.src) || 'assets/smp.mp4'} videoStyle={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
          <span style={{ position: 'absolute', bottom: '14px', left: '15px', fontFamily: 'var(--font-mono)', fontSize: '0.55rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--bone)', background: 'rgba(0,0,0,.55)', padding: '5px 11px', borderRadius: '20px', backdropFilter: 'blur(5px)', zIndex: 1 }}>{T(lang, 'SMP', 'SMP')}</span>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: '12px', marginTop: '30px' }} className="ms-bento">
        <div style={benefit}><div style={kk}>{T(lang, 'Why it works', 'Por qué funciona')}</div><div style={bt}>{T(lang, 'Natural density', 'Densidad natural')}</div><p style={bp}>{T(lang, 'Thousands of micro-impressions read as real follicles — a sharp, intentional line.', 'Miles de microimpresiones se ven como folículos reales — una línea marcada e intencional.')}</p></div>
        <div style={benefit}><div style={kk}>{T(lang, 'No surgery', 'Sin cirugía')}</div><div style={bt}>{T(lang, 'Non-invasive', 'No invasivo')}</div><p style={bp}>{T(lang, 'No scalpels, no scars, no real downtime. Walk out and back to your day.', 'Sin bisturí, sin cicatrices, sin recuperación real. Sales y sigues con tu día.')}</p></div>
        <div style={benefit}><div style={kk}>{T(lang, 'Lasts years', 'Dura años')}</div><div style={bt}>{T(lang, 'Low maintenance', 'Poco mantenimiento')}</div><p style={bp}>{T(lang, 'A simple touch-up every few years keeps the look fresh.', 'Un retoque simple cada pocos años mantiene el look fresco.')}</p></div>
      </div>
    </section>
  );
}

function ReviewsSocial({ lang }) {
  const reviews = [
    ['"Changed how I see myself."', 'Giovannis T.', T(lang, 'SMP · 3 sessions', 'SMP · 3 sesiones')],
    ['"Sharpest fade in Houston, every time."', 'Andrés P.', T(lang, 'Weekly regular', 'Cliente semanal')],
    ['"Walked in unsure, walked out brand new."', 'Marco D.', T(lang, 'SMP · scar coverage', 'SMP · cobertura de cicatriz')],
  ];
  const tile = { fontFamily: 'var(--font-mono)', fontSize: '0.68rem', textTransform: 'uppercase', letterSpacing: '0.1em' };
  return (
    <section id="reviews" style={{ background: 'var(--ink)', padding: '64px 30px 70px', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · Reviews">
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', flexWrap: 'wrap', gap: '18px', marginBottom: '26px' }}>
        <div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Reviews', 'Reseñas')}</div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.2rem,5vw,3.4rem)', textTransform: 'uppercase', marginTop: '10px', letterSpacing: '-0.04em', color: 'var(--bone)', lineHeight: 0.92 }}>{T(lang, 'What the chair says.', 'Lo que dice la silla.')}</h2>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
          <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '3rem', letterSpacing: '-0.04em', color: 'var(--accent)', lineHeight: 0.9 }}>5.0</span>
          <div>
            <div style={{ color: 'var(--accent)', letterSpacing: '2px', fontSize: '0.85rem' }}>★★★★★</div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.55rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--muted)', marginTop: '4px' }}>{T(lang, 'Average rating', 'Calificación promedio')}</div>
          </div>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(240px,1fr))', gap: '12px' }}>
        {reviews.map(([q, name, meta], i) => (
          <div key={i} style={{ background: 'var(--card)', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-md)', padding: '22px' }}>
            <div style={{ color: 'var(--accent)', letterSpacing: '2px', fontSize: '0.78rem' }}>★★★★★</div>
            <p style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: '1.18rem', letterSpacing: '-0.02em', lineHeight: 1.2, margin: '13px 0 16px', color: 'var(--bone)' }}>{q}</p>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.55rem', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--muted)' }}>{name} · <span style={{ color: 'var(--muted-2)' }}>{meta}</span></div>
          </div>
        ))}
      </div>
      <div style={{ marginTop: '14px', background: 'var(--card)', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-lg)', padding: '24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: '14px', marginBottom: '16px' }}>
          <div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--accent)' }}>@michaelstyle23</div>
            <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.4rem', letterSpacing: '-0.03em', color: 'var(--bone)', marginTop: '4px' }}>2.2K <span style={{ fontSize: '0.8rem', color: 'var(--muted)', fontWeight: 500 }}>{T(lang, 'followers', 'seguidores')}</span></div>
          </div>
          <a href="https://www.instagram.com/michaelstyle23/" target="_blank" rel="noopener noreferrer" style={{ ...tile, color: 'var(--on-accent)', background: 'var(--accent)', padding: '13px 22px', borderRadius: 'var(--radius-pill)', textDecoration: 'none' }}>{T(lang, 'Follow on Instagram', 'Seguir en Instagram')}</a>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(110px,1fr))', gap: '8px' }}>
          {['assets/work/corte-barba-1.jpg', 'assets/work/barba-2.jpg', 'assets/work/smp-capilar-1.jpg', 'assets/work/cerquillo-1.jpg', 'assets/work/ninos-1.jpg', 'assets/work/cejas-1-after.jpg'].map((src, i) => (
            <a key={i} href="https://www.instagram.com/michaelstyle23/" target="_blank" rel="noopener noreferrer" style={{ display: 'block', aspectRatio: '1/1', borderRadius: '12px', overflow: 'hidden', border: '1px solid var(--bd-d)' }}>
              <img src={src} alt="" loading="lazy" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
            </a>
          ))}
        </div>
      </div>
    </section>
  );
}

function PortfolioTile({ tag, sub, feature, style, img }) {
  return (
    <div className="ms-ptile" style={{ position: 'relative', borderRadius: 'var(--radius-md)', overflow: 'hidden', border: '1px solid var(--bd-d)', ...style }}>
      {img
        ? <img src={img} alt={(tag || '') + (sub ? ' ' + sub : '')} className="ms-ptile__img" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', filter: 'grayscale(1)' }} />
        : <div className="ms-work-texture ms-ptile__img" style={{ position: 'absolute', inset: 0 }} />}
      {tag && (
        <div style={{ position: 'absolute', left: feature ? '20px' : '14px', bottom: feature ? '18px' : '12px', zIndex: 2 }}>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: feature ? '0.58rem' : '0.5rem', letterSpacing: '0.15em', textTransform: 'uppercase', color: 'var(--accent)' }}>{tag}</span>
          {sub && <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: feature ? '1.6rem' : '0.95rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', lineHeight: 0.95, marginTop: '4px' }}>{sub}</div>}
        </div>
      )}
      {feature && <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(10,10,11,.72), rgba(10,10,11,0) 55%)', zIndex: 1 }} />}
    </div>
  );
}

function Portfolio({ lang }) {
  // Shows Michael's uploaded photos (from the owner panel) if any; otherwise
  // placeholder pairs. Before/after items keep the drag slider.
  const gallery = useGallery();
  const defaults = [
    { id: 'cb1', type: 'single', src: 'assets/work/corte-barba-1.jpg', cat: 'corte-barba' },
    { id: 'cb2', type: 'single', src: 'assets/work/corte-barba-2.jpg', cat: 'corte-barba' },
    { id: 'cb3', type: 'single', src: 'assets/work/corte-barba-3.jpg', cat: 'corte-barba' },
    { id: 'ba1', type: 'single', src: 'assets/work/barba-1.jpg', cat: 'barba' },
    { id: 'ba2', type: 'single', src: 'assets/work/barba-2.jpg', cat: 'barba' },
    { id: 'ce1', type: 'single', src: 'assets/work/cerquillo-1.jpg', cat: 'cerquillo' },
    { id: 'ni1', type: 'single', src: 'assets/work/ninos-1.jpg', cat: 'ninos' },
    { id: 'ni2', type: 'single', src: 'assets/work/ninos-2.jpg', cat: 'ninos' },
    { id: 'sc1', type: 'single', src: 'assets/work/smp-capilar-1.jpg', cat: 'smp-capilar' },
    { id: 'sc2', type: 'single', src: 'assets/work/smp-capilar-2.jpg', cat: 'smp-capilar' },
    { id: 'sc3', type: 'single', src: 'assets/work/smp-capilar-3.jpg', cat: 'smp-capilar' },
    { id: 'cj1', type: 'ba', before: 'assets/work/cejas-1-before.jpg', after: 'assets/work/cejas-1-after.jpg', cat: 'smp-cejas', label: 'Modelo 1' },
    { id: 'cj2', type: 'ba', before: 'assets/work/cejas-2-after.jpg', after: 'assets/work/cejas-2-before.jpg', cat: 'smp-cejas', label: 'Modelo 2' },
  ];
  const source = (gallery && gallery.length) ? gallery : defaults;
  const [cat, setCat] = React.useState('all');
  const shown = cat !== 'all' ? source.filter((x) => x.cat === cat) : source;
  const pill = (active) => ({ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.08em', textTransform: 'uppercase', padding: '8px 13px', borderRadius: 'var(--radius-pill)', cursor: 'pointer', flex: 'none', border: `1px solid ${active ? 'var(--accent)' : 'var(--bd-d)'}`, background: active ? 'var(--accent)' : 'transparent', color: active ? 'var(--on-accent)' : 'var(--muted)' });
  return (
    <section id="barberia" style={{ background: 'var(--ink)', padding: '64px 30px 70px', scrollMarginTop: '150px' }} data-screen-label="Web · Barbería">
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'The work', 'El trabajo')}</div>
      <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.4rem,5vw,3.4rem)', textTransform: 'uppercase', marginTop: '10px', letterSpacing: '-0.04em', color: 'var(--bone)', lineHeight: 0.92 }}>{T(lang, 'The work is the proof.', 'El trabajo es la prueba.')}</h2>
      <p style={{ color: 'var(--muted)', margin: '12px 0 0', fontSize: '0.92rem' }}>{T(lang, 'Drag each before/after photo to reveal the result.', 'Arrastra cada foto de antes/después para ver el resultado.')}</p>
      <div style={{ display: 'flex', gap: '7px', flexWrap: 'wrap', marginTop: '18px' }}>
        <button onClick={() => setCat('all')} style={pill(cat === 'all')}>{T(lang, 'All', 'Todos')}</button>
        {CATS.map((c) => <button key={c.id} onClick={() => setCat(c.id)} style={pill(cat === c.id)}>{lang === 'ES' ? c.es : c.en}</button>)}
      </div>
      {shown.length === 0 && (
        <p style={{ color: 'var(--muted-2)', fontStyle: 'italic', fontSize: '0.9rem', marginTop: '28px' }}>{T(lang, 'No photos in this category yet.', 'Aún no hay fotos en esta categoría.')}</p>
      )}
      <div style={{ columns: '250px', columnGap: '16px', marginTop: '24px' }}>
        {shown.map((it, i) => (
          <div key={it.id || i} style={{ breakInside: 'avoid', WebkitColumnBreakInside: 'avoid', marginBottom: '18px' }}>
            {it.type === 'single'
              ? <img src={it.src} alt={it.label || ''} style={{ display: 'block', width: '100%', height: 'auto', borderRadius: 'var(--radius-md)', border: '1px solid var(--bd-d)' }} />
              : <BeforeAfter lang={lang} before={it.before} after={it.after} hint={false} />}
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', marginTop: '10px' }}>{catLabel(lang, it.cat)}{it.label ? ' · ' + it.label : ''}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

function AboutSection({ lang }) {
  useContent();
  return (
    <section id="about" style={{ background: 'var(--ink)', padding: '64px 30px 70px', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · About">
      <div style={{ display: 'grid', gridTemplateColumns: '1.1fr .9fr', gap: '40px', alignItems: 'start' }} className="ms-hero-grid">
        <div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Our craft', 'Nuestra especialidad')}</div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.4rem,5.5vw,4rem)', textTransform: 'uppercase', letterSpacing: '-0.04em', lineHeight: 0.92, margin: '10px 0 0', color: 'var(--bone)' }}>{T(lang, 'More than a barbershop.', 'Más que una barbería.')}</h2>
          <p style={{ color: 'var(--muted)', maxWidth: '54ch', margin: '18px 0 0', fontSize: '0.98rem', lineHeight: 1.6 }}>{T(lang,
            'We specialize in creating unique personal-care experiences, blending traditional barbering with advanced men’s aesthetics.',
            'Nos especializamos en crear experiencias únicas de cuidado personal, combinando técnicas tradicionales de barbería con servicios avanzados de estética masculina.')}</p>
          <p style={{ color: 'var(--muted)', maxWidth: '54ch', margin: '14px 0 0', fontSize: '0.98rem', lineHeight: 1.6 }}>{T(lang,
            'Every client gets personalized attention — we read your style, features, and preferences to bring out your best version. Not just a cut: a full experience of image, comfort, and confidence.',
            'Cada cliente recibe atención personalizada: analizamos tu estilo, facciones y preferencias para resaltar tu mejor versión. No solo un corte: una experiencia completa de imagen, comodidad y confianza.')}</p>

          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.58rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--accent)', margin: '22px 0 12px' }}>{T(lang, 'What sets us apart', 'Nos destacamos por')}</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 18px' }} className="ms-vip-grid">
            {[
              ['Professional, personalized attention.', 'Atención profesional y personalizada.'],
              ['Cuts and designs tailored to each style.', 'Cortes y diseños adaptados a cada estilo.'],
              ['Modern barbering and aesthetic techniques.', 'Técnicas modernas de barbería y estética.'],
              ['Premium relaxation and facial-care treatments.', 'Tratamientos premium de relajación y cuidado facial.'],
              ['Specialists in scalp, beard, and eyebrow micropigmentation.', 'Especialización en micropigmentación capilar, de barba y cejas.'],
              ['Precision details for impeccable finishes.', 'Detalles de precisión para acabados impecables.'],
            ].map(([en, es], i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
                <span style={{ color: 'var(--accent)', flex: 'none', marginTop: '1px' }}><window.Icon name="check" size={15} /></span>
                <span style={{ fontSize: '0.82rem', color: 'var(--bone)', lineHeight: 1.4 }}>{T(lang, en, es)}</span>
              </div>
            ))}
          </div>
          <p style={{ color: 'var(--muted-2)', fontStyle: 'italic', maxWidth: '54ch', margin: '20px 0 0', fontSize: '0.86rem', lineHeight: 1.55 }}>{T(lang,
            'Founded by Michael Adonis — Dominican barber & micropigmentation artist in Houston.',
            'Fundada por Michael Adonis — barbero dominicano y artista de micropigmentación en Houston.')}</p>
        </div>
        <div style={{ background: 'var(--card)', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-lg)', padding: '24px' }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Visit', 'Visítanos')}</div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.5rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', margin: '10px 0 14px' }}>Michael Style Studio</div>
          <img src={loadJSON('ms_about_photo', null) || 'assets/michael.jpg'} alt="Michael Adonis" loading="lazy" style={{ display: 'block', width: '100%', aspectRatio: '4/5', objectFit: 'cover', objectPosition: 'center 25%', borderRadius: 'var(--radius-md)', border: '1px solid var(--bd-d)', marginBottom: '16px' }} />
          {(() => { const h = loadJSON('ms_hours', DEFAULT_HOURS); return [[T(lang, 'Location', 'Ubicación'), h.note], [T(lang, 'Hours', 'Horario'), h.hours], [T(lang, 'Closed', 'Cerrado'), h.closed]]; })().map(([k, v]) => (
            <div key={k} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: '14px', padding: '11px 0', borderTop: '1px solid var(--bd-d)' }}>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--muted-2)' }}>{k}</span>
              <span style={{ fontSize: '0.82rem', color: 'var(--bone)', textAlign: 'right' }}>{v}</span>
            </div>
          ))}
          <a href={'https://www.google.com/maps/search/?api=1&query=' + encodeURIComponent(loadJSON('ms_address', '') || 'Michael Style Barbershop Houston TX')} target="_blank" rel="noopener noreferrer" style={{ display: 'block', textAlign: 'center', marginTop: '18px', fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--on-accent)', background: 'var(--accent)', padding: '13px', borderRadius: 'var(--radius-pill)', textDecoration: 'none' }}>{T(lang, 'Get directions', 'Cómo llegar')}</a>
        </div>
      </div>
    </section>
  );
}

function Faith({ lang }) {
  return (
    <section id="faith" style={{ background: 'var(--ink-2)', padding: '70px 30px', textAlign: 'center', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · Faith">
      <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, textTransform: 'uppercase', fontSize: 'clamp(2.6rem,8vw,5.5rem)', letterSpacing: '-0.04em', color: 'var(--bone)', lineHeight: 0.95 }}>
        DIOS <span style={{ color: 'var(--accent)' }}>PRIMERO</span>
      </div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.62rem', letterSpacing: '0.2em', textTransform: 'uppercase', color: 'var(--muted)', marginTop: '14px' }}>{T(lang, 'Joshua 1:9 — "Be strong and courageous."', 'Josué 1:9 — "Sé fuerte y valiente."')}</div>
      <p style={{ color: 'var(--muted)', maxWidth: '52ch', margin: '18px auto 0', fontSize: '0.92rem', lineHeight: 1.55 }}>{T(lang,
        'Michael Adonis — Dominican barber & SMP artist in Houston. Faith is how he works: with care, patience, and respect for every person in the chair. Everyone is welcome.',
        'Michael Adonis — barbero dominicano y artista de SMP en Houston. La fe describe cómo trabaja: con cuidado, paciencia y respeto por cada persona en la silla. Todos son bienvenidos.')}</p>
    </section>
  );
}

function CalendarSection({ lang, onBook }) {
  const CS_DOW = { EN: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], ES: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'] };
  const CS_MON = { EN: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], ES: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'] };
  const CS_SLOTS = ['9:00A', '10:30A', '12:00P', '2:00P', '3:30P', '5:00P'];
  const [weekOffset, setWeekOffset] = React.useState(0);
  const [sel, setSel] = React.useState(null); // { di, si }
  const today = React.useMemo(() => { const d = new Date(); d.setHours(0, 0, 0, 0); return d; }, []);
  const weekStart = React.useMemo(() => {
    const d = new Date(today); const dow = d.getDay();
    d.setDate(d.getDate() + (dow === 0 ? -6 : 1 - dow) + weekOffset * 7); // Monday of the shown week
    return d;
  }, [today, weekOffset]);
  const days = [1, 2, 3, 4, 5].map((i) => { const d = new Date(weekStart); d.setDate(weekStart.getDate() + i); return d; }); // Tue–Sat
  const isPast = (d) => d < today;
  const isToday = (d) => d.getTime() === today.getTime();
  const slotOpen = (d, si) => !isPast(d) && (d.getDate() * 7 + si * 3) % 5 !== 0; // deterministic demo availability
  const first = days[0], last = days[4];
  const weekLabel = first.getMonth() === last.getMonth()
    ? `${CS_MON[lang][first.getMonth()]} ${first.getDate()}–${last.getDate()}`
    : `${CS_MON[lang][first.getMonth()]} ${first.getDate()} – ${CS_MON[lang][last.getMonth()]} ${last.getDate()}`;
  const chosen = sel ? `${CS_DOW[lang][days[sel.di].getDay()]} ${days[sel.di].getDate()} · ${CS_SLOTS[sel.si]}` : null;
  const wkBtn = (txt, onClick, disabled) => (
    <button onClick={onClick} disabled={disabled} aria-label={txt} style={{ width: '40px', height: '40px', borderRadius: '50%', flex: 'none', cursor: disabled ? 'not-allowed' : 'pointer', border: '1px solid var(--bd-d2)', background: 'transparent', color: disabled ? 'var(--muted-2)' : 'var(--bone)', fontSize: '1.05rem', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{txt}</button>
  );
  return (
    <section id="calendar" style={{ background: 'var(--ink)', padding: '64px 30px 70px', borderTop: '1px solid var(--bd-d)', scrollMarginTop: '150px' }} data-screen-label="Web · Calendar">
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Book', 'Reservar')}</div>
      <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: 'clamp(2.4rem,5vw,3.4rem)', textTransform: 'uppercase', margin: '10px 0 4px', letterSpacing: '-0.04em', color: 'var(--bone)', lineHeight: 0.92 }}>{T(lang, 'Book your visit.', 'Reserva tu cita.')}</h2>
      <div style={{ fontSize: '0.92rem', color: 'var(--muted)', marginBottom: '22px' }}>{T(lang, 'Pick a day and time. Tap a slot to hold it.', 'Elige un día y una hora. Toca un espacio para reservarlo.')}</div>
      {/* week nav */}
      <div style={{ display: 'flex', alignItems: 'center', gap: '14px', marginBottom: '20px' }}>
        {wkBtn('‹', () => { setWeekOffset((w) => Math.max(0, w - 1)); setSel(null); }, weekOffset === 0)}
        <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.2rem', letterSpacing: '-0.02em', color: 'var(--bone)', textAlign: 'center' }}>
          {weekLabel}
          <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 500, fontSize: '0.56rem', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--accent)', display: 'block', marginTop: '3px' }}>{weekOffset === 0 ? T(lang, 'This week', 'Esta semana') : (weekOffset === 1 ? T(lang, 'Next week', 'Próxima semana') : T(lang, 'In ' + weekOffset + ' weeks', 'En ' + weekOffset + ' semanas'))}</span>
        </div>
        {wkBtn('›', () => { setWeekOffset((w) => Math.min(8, w + 1)); setSel(null); }, weekOffset >= 8)}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(150px,1fr))', gap: '12px' }}>
        {days.map((day, di) => {
          const past = isPast(day);
          const todayD = isToday(day);
          return (
            <div key={di} style={{ background: 'var(--card)', border: `1px solid ${todayD ? 'var(--accent)' : 'var(--bd-d)'}`, borderRadius: 'var(--radius-md)', padding: '15px 13px', opacity: past ? 0.45 : 1 }}>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: '7px', marginBottom: '12px' }}>
                <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.58rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: todayD ? 'var(--accent)' : 'var(--muted)' }}>{CS_DOW[lang][day.getDay()]}</span>
                <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.3rem', letterSpacing: '-0.03em', color: 'var(--bone)' }}>{day.getDate()}</span>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: '7px' }}>
                {CS_SLOTS.map((time, si) => {
                  const open = slotOpen(day, si);
                  const on = sel && sel.di === di && sel.si === si;
                  return (
                    <button key={si} disabled={!open} onClick={() => setSel({ di, si })} aria-pressed={on} style={{
                      fontFamily: 'var(--font-mono)', fontSize: '0.62rem', letterSpacing: '0.04em', padding: '10px 8px',
                      borderRadius: 'var(--radius-pill)', textAlign: 'center',
                      cursor: open ? 'pointer' : 'not-allowed',
                      border: `1px solid ${on ? 'var(--accent)' : open ? 'var(--bd-d2)' : 'var(--bd-d)'}`,
                      background: on ? 'var(--accent)' : 'transparent',
                      color: on ? 'var(--on-accent)' : open ? 'var(--bone)' : 'var(--muted-2)',
                      textDecoration: open ? 'none' : 'line-through',
                      transition: 'all var(--dur-fast) var(--ease-out)',
                    }}>{time}</button>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: '14px', marginTop: '22px' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.06em', textTransform: 'uppercase', color: chosen ? 'var(--bone)' : 'var(--muted-2)' }}>
          {chosen ? <>{T(lang, 'Selected', 'Seleccionado')} · <span style={{ color: 'var(--accent)' }}>{chosen}</span></> : T(lang, 'No time selected yet', 'Aún no hay hora seleccionada')}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flexWrap: 'wrap' }}>
          <a href="Full Calendar.html" style={{
            fontFamily: 'var(--font-mono)', fontSize: '0.68rem', letterSpacing: '0.09em', textTransform: 'uppercase',
            padding: '14px 22px', borderRadius: 'var(--radius-pill)', border: '1px solid var(--bd-d2)',
            color: 'var(--bone)', textDecoration: 'none',
          }}>{T(lang, 'View full calendar →', 'Ver calendario completo →')}</a>
          <button onClick={onBook} disabled={!chosen} style={{
            fontFamily: 'var(--font-mono)', fontSize: '0.68rem', letterSpacing: '0.09em', textTransform: 'uppercase',
            padding: '14px 24px', borderRadius: 'var(--radius-pill)',
            cursor: chosen ? 'pointer' : 'not-allowed',
            background: chosen ? 'var(--accent)' : 'var(--card)', color: chosen ? 'var(--on-accent)' : 'var(--muted-2)',
            border: chosen ? 'none' : '1px solid var(--bd-d)',
          }}>{T(lang, 'Reserve this slot', 'Reservar este espacio')}</button>
        </div>
      </div>
    </section>
  );
}

/* ——— Michael's basic web app: upload & organize photos (bookings stay in Booksy) ——— */
const MS_UP_KEY = 'ms_uploads';
const BOOKSY_URL = 'https://michaelstyledominicanbarbershop.booksy.com/ig/'; /* Michael's Booksy booking page */
const MS_PANEL_PIN = 'michael';          /* simple client-side gate — change as needed */
const CATS = [
  { id: 'cortes', en: 'Cuts', es: 'Cortes' },
  { id: 'corte-barba', en: 'Cut & Beard', es: 'Corte y Barba' },
  { id: 'barba', en: 'Beard', es: 'Barba' },
  { id: 'cerquillo', en: 'Line-up', es: 'Cerquillo' },
  { id: 'ninos', en: 'Kids', es: 'Niños' },
  { id: 'smp-capilar', en: 'Scalp SMP', es: 'SMP Capilar' },
  { id: 'smp-cejas', en: 'Brow SMP', es: 'SMP Cejas' },
];
const catLabel = (lang, id) => { const c = CATS.find((x) => x.id === id); return c ? (lang === 'ES' ? c.es : c.en) : ''; };
function loadUploads() { try { return JSON.parse(localStorage.getItem(MS_UP_KEY) || '[]'); } catch (e) { return []; } }
function saveUploads(list) { localStorage.setItem(MS_UP_KEY, JSON.stringify(list)); }
function downloadDataURL(dataURL, name) { const a = document.createElement('a'); a.href = dataURL; a.download = name || 'michael-style.jpg'; document.body.appendChild(a); a.click(); a.remove(); }
async function shareOrDownload(dataURL, name) {
  try {
    const blob = await (await fetch(dataURL)).blob();
    const file = new File([blob], name || 'michael-style.jpg', { type: blob.type || 'image/jpeg' });
    if (navigator.canShare && navigator.canShare({ files: [file] })) { await navigator.share({ files: [file], title: 'Michael Style' }); return; }
  } catch (e) { /* fall through to download */ }
  downloadDataURL(dataURL, name);
}
/* resize an image file to a compact JPEG data URL so several fit in localStorage */
function fileToDataURL(file, max = 1100) {
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const img = new Image();
    img.onload = () => {
      const scale = Math.min(1, max / Math.max(img.width, img.height));
      const w = Math.round(img.width * scale), h = Math.round(img.height * scale);
      const c = document.createElement('canvas'); c.width = w; c.height = h;
      c.getContext('2d').drawImage(img, 0, 0, w, h);
      URL.revokeObjectURL(url);
      resolve(c.toDataURL('image/jpeg', 0.82));
    };
    img.onerror = (e) => { URL.revokeObjectURL(url); reject(e); };
    img.src = url;
  });
}

/* —— editable site content (localStorage; per-device until a backend is added) —— */
function loadJSON(k, d) {
  const key = k.replace(/^ms_/, '');
  const c = MS.content;
  return (c && c[key] !== undefined && c[key] !== null) ? c[key] : d;
}
async function saveJSON(k, v) {
  const key = k.replace(/^ms_/, '');
  if (!sb) return false;
  const { error } = await sb.from('site_content').upsert({ key, value: v, updated_at: new Date().toISOString() });
  if (!error) { if (!MS.content) MS.content = {}; MS.content[key] = v; MS._notify(); }
  return !error;
}

/* ===== Supabase-backed content + gallery (publishes live to everyone) ===== */
const MS = { gallery: null, content: null, _subs: [] };
window.MS = MS;
MS._notify = () => { MS._subs.slice().forEach((fn) => { try { fn(); } catch (e) {} }); };
MS.loadContent = async () => {
  if (!sb) { MS.content = {}; MS._notify(); return; }
  try {
    const { data } = await sb.from('site_content').select('key,value');
    const map = {}; (data || []).forEach((r) => { map[r.key] = r.value; });
    MS.content = map;
  } catch (e) { MS.content = {}; }
  MS._notify();
};
function useContent() {
  const [, force] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => {
    MS._subs.push(force);
    if (MS.content === null) MS.loadContent();
    return () => { MS._subs = MS._subs.filter((f) => f !== force); };
  }, []);
  return MS.content;
}
MS.loadGallery = async () => {
  if (!sb) { MS.gallery = []; MS._notify(); return; }
  try {
    const { data } = await sb.from('gallery').select('*').order('sort', { ascending: true }).order('created_at', { ascending: false });
    MS.gallery = (data || []).map((r) => ({ id: r.id, type: r.type, cat: r.cat, label: r.label, src: r.src, before: r.before_url, after: r.after_url }));
  } catch (e) { MS.gallery = []; }
  MS._notify();
};
function useGallery() {
  const [, force] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => {
    MS._subs.push(force);
    if (MS.gallery === null) MS.loadGallery();
    return () => { MS._subs = MS._subs.filter((f) => f !== force); };
  }, []);
  return MS.gallery; // null while loading; array when ready
}
function resizeToBlob(file, max = 1400) {
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const img = new Image();
    img.onload = () => {
      const scale = Math.min(1, max / Math.max(img.width, img.height));
      const w = Math.round(img.width * scale), h = Math.round(img.height * scale);
      const c = document.createElement('canvas'); c.width = w; c.height = h;
      c.getContext('2d').drawImage(img, 0, 0, w, h);
      URL.revokeObjectURL(url);
      c.toBlob((b) => (b ? resolve(b) : reject(new Error('blob'))), 'image/jpeg', 0.82);
    };
    img.onerror = (e) => { URL.revokeObjectURL(url); reject(e); };
    img.src = url;
  });
}
async function uploadPhoto(file) {
  const blob = await resizeToBlob(file, 1400);
  const name = `${Date.now()}-${Math.round(Math.random() * 1e9)}.jpg`;
  const { error } = await sb.storage.from('photos').upload(name, blob, { contentType: 'image/jpeg', upsert: false });
  if (error) throw error;
  return sb.storage.from('photos').getPublicUrl(name).data.publicUrl;
}
/* Videos can't be recompressed in the browser, so they upload as-is.
   50MB is Supabase's per-file ceiling — a 10–20s phone clip fits fine. */
const MAX_VIDEO_MB = 50;
async function uploadVideo(file) {
  if (file.size > MAX_VIDEO_MB * 1024 * 1024) {
    const err = new Error('too-big'); err.code = 'too-big'; err.mb = Math.round(file.size / 1024 / 1024); throw err;
  }
  const ext = (file.name.split('.').pop() || 'mp4').toLowerCase().replace(/[^a-z0-9]/g, '') || 'mp4';
  const name = `videos/${Date.now()}-${Math.round(Math.random() * 1e9)}.${ext}`;
  const { error } = await sb.storage.from('photos').upload(name, file, { contentType: file.type || 'video/mp4', upsert: false });
  if (error) throw error;
  return sb.storage.from('photos').getPublicUrl(name).data.publicUrl;
}
async function addGalleryItem({ type, cat, label, src, before, after }) {
  const { error } = await sb.from('gallery').insert({ type, cat, label: label || null, src: src || null, before_url: before || null, after_url: after || null });
  if (error) throw error;
  await MS.loadGallery();
}
async function removeGalleryItem(id) {
  const { error } = await sb.from('gallery').delete().eq('id', id);
  if (error) throw error;
  await MS.loadGallery();
}
async function updateGalleryItem(id, patch) {
  const { error } = await sb.from('gallery').update({ cat: patch.cat, label: patch.label || null }).eq('id', id);
  if (error) throw error;
  await MS.loadGallery();
}
const DEFAULT_SERVICES = [
  { id: 1, name: 'Corte VIP', desc: 'Experiencia premium completa: corte, barba, cejas, lavado, limpieza facial, toalla caliente, vapor de ozono y masaje.', price: 'Desde $—', featured: true },
  { id: 2, name: 'Corte + Barba + Cejas', desc: 'Corte personalizado, diseño de barba y perfilado de cejas.', price: 'Desde $—' },
  { id: 3, name: 'Corte de Cabello', desc: 'Cortes personalizados con acabados profesionales.', price: 'Desde $—' },
  { id: 4, name: 'Diseño y Corte de Barba', desc: 'Mantenimiento y definición de barba, líneas limpias.', price: 'Desde $—' },
  { id: 5, name: 'Cerquillo / Perfilado', desc: 'Definición de líneas y contornos para un look fresco.', price: 'Desde $—' },
  { id: 6, name: 'Cortes para Todas las Edades', desc: 'Niños, adolescentes y jóvenes — estilos actuales.', price: 'Desde $—' },
  { id: 7, name: 'Micropigmentación Capilar y de Barba', desc: 'Mejora densidad y definición con efecto natural.', price: 'Desde $—' },
  { id: 8, name: 'Micropigmentación de Cejas', desc: 'Diseño, definición y simetría de cejas.', price: 'Desde $—' },
];
const DEFAULT_HOURS = { hours: 'Mar–Sáb · 9A–7P', closed: 'Domingo · Lunes', note: 'Houston, TX · con cita' };

function UploadBox({ id, label, value, onFile }) {
  return (
    <label htmlFor={id} style={{ position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '8px', aspectRatio: '4/5', borderRadius: 'var(--radius-md)', border: '1px dashed var(--bd-d2)', background: 'var(--card)', color: 'var(--muted)', cursor: 'pointer', overflow: 'hidden', textAlign: 'center' }}>
      {value
        ? <img src={value} alt={label} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />
        : <><span style={{ color: 'var(--accent)' }}><window.Icon name="camera" size={22} /></span><span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.55rem', letterSpacing: '0.1em', textTransform: 'uppercase' }}>{label}</span></>}
      <input id={id} type="file" accept="image/*" onChange={(e) => onFile(e.target.files[0])} style={{ display: 'none' }} />
    </label>
  );
}

/* —— content editors (full-screen, save to localStorage) —— */
function EditorShell({ lang, onBack, title, onSave, saved, busy, children }) {
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 110, background: 'var(--ink)' }}>
      <div style={{ height: '100%', maxWidth: '480px', margin: '0 auto', display: 'flex', flexDirection: 'column', background: 'var(--ink)', boxShadow: '0 0 70px rgba(0,0,0,.55)' }}>
        <div style={{ flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '10px', padding: 'max(14px,env(safe-area-inset-top)) 16px 12px', borderBottom: '1px solid var(--bd-d)', background: 'var(--scrim-dark)', backdropFilter: 'var(--blur-glass)' }}>
          <button onClick={onBack} style={{ display: 'inline-flex', alignItems: 'center', gap: '5px', background: 'none', border: 'none', cursor: 'pointer', color: 'var(--muted)', fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.08em', textTransform: 'uppercase', minHeight: '44px' }}><span style={{ transform: 'rotate(180deg)', display: 'inline-flex' }}><window.Icon name="chevron" size={13} /></span> {T(lang, 'Back', 'Atrás')}</button>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--bone)' }}>{title}</span>
          {onSave ? <button onClick={busy ? undefined : onSave} disabled={!!busy} style={{ fontFamily: 'var(--font-mono)', fontSize: '0.58rem', letterSpacing: '0.08em', textTransform: 'uppercase', padding: '10px 16px', borderRadius: 'var(--radius-pill)', border: 'none', cursor: busy ? 'default' : 'pointer', background: saved ? 'transparent' : 'var(--accent)', color: saved ? 'var(--accent)' : 'var(--on-accent)', opacity: busy ? 0.65 : 1 }}>{busy ? T(lang, 'Uploading…', 'Subiendo…') : saved ? '✓ ' + T(lang, 'Saved', 'Guardado') : T(lang, 'Save', 'Guardar')}</button> : <span style={{ width: '40px' }} />}
        </div>
        <div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', minHeight: 0, padding: '16px 18px 30px' }} className="ms-noscroll">{children}</div>
      </div>
    </div>
  );
}
/* 16px inputs — anything smaller makes iOS Safari zoom the viewport on focus,
   which is the single biggest "this isn't a real app" tell. */
const edInput = { width: '100%', boxSizing: 'border-box', fontFamily: 'var(--font-body)', fontSize: '1rem', padding: '12px 14px', borderRadius: 'var(--radius-input)', border: '1px solid var(--bd-d)', background: 'var(--ink-2)', color: 'var(--bone)', outline: 'none', display: 'block' };
/* iOS-style switch */
function IOSSwitch({ on, onChange }) {
  return (
    <button onClick={() => onChange(!on)} role="switch" aria-checked={on} style={{ position: 'relative', width: '51px', height: '31px', borderRadius: '31px', border: 'none', padding: 0, cursor: 'pointer', flex: 'none', background: on ? 'var(--accent)' : 'rgba(255,255,255,.16)', transition: 'background .22s ease' }}>
      <span style={{ position: 'absolute', top: '2px', left: '2px', width: '27px', height: '27px', borderRadius: '50%', background: '#fff', boxShadow: '0 3px 8px rgba(0,0,0,.35), 0 0 1px rgba(0,0,0,.25)', transform: on ? 'translateX(20px)' : 'translateX(0)', transition: 'transform .22s cubic-bezier(.4,0,.2,1)' }} />
    </button>
  );
}
const edLabel = { fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--muted-2)', margin: '0 0 6px' };
function useSaved() { const [s, set] = React.useState(false); return [s, () => { set(true); setTimeout(() => set(false), 1800); }]; }

function ServicesEditor({ lang, onBack }) {
  const [list, setList] = React.useState(() => loadJSON('ms_services', DEFAULT_SERVICES));
  const [saved, flash] = useSaved();
  const upd = (id, k, v) => setList((l) => l.map((s) => (s.id === id ? { ...s, [k]: v } : s)));
  const [delId, setDelId] = React.useState(null);
  const del = (id) => setList((l) => l.filter((s) => s.id !== id));
  const add = () => setList((l) => [...l, { id: Date.now(), name: '', desc: '', price: 'Desde $—' }]);
  const save = () => { saveJSON('ms_services', list).then((ok) => { if (ok) flash(); }); };
  return (
    <EditorShell lang={lang} onBack={onBack} title={T(lang, 'Services', 'Servicios')} onSave={save} saved={saved}>
      <p style={{ color: 'var(--muted)', fontSize: '0.78rem', margin: '2px 0 18px' }}>{T(lang, 'Edit the services shown on the site.', 'Edita los servicios que se muestran en el sitio.')}</p>
      {list.map((s) => {
        const rowLabel = { fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)', margin: '0 0 3px' };
        const rowInput = { width: '100%', boxSizing: 'border-box', fontFamily: 'var(--font-body)', fontSize: '1rem', padding: '2px 0 0', border: 'none', background: 'transparent', color: 'var(--bone)', outline: 'none', display: 'block' };
        const hairline = <div style={{ height: '1px', background: 'var(--bd-d)', marginLeft: '16px' }} />;
        return (
          <div key={s.id} style={{ background: 'var(--card)', borderRadius: '20px', marginBottom: '14px', overflow: 'hidden' }}>
            <div style={{ padding: '13px 16px 11px' }}>
              <div style={rowLabel}>{T(lang, 'Name', 'Nombre')}</div>
              <input value={s.name} onChange={(e) => upd(s.id, 'name', e.target.value)} placeholder={T(lang, 'e.g. VIP Cut', 'Ej. Corte VIP')} style={{ ...rowInput, fontWeight: 600 }} />
            </div>
            {hairline}
            <div style={{ padding: '11px 16px' }}>
              <div style={rowLabel}>{T(lang, 'Description', 'Descripción')}</div>
              <textarea value={s.desc} onChange={(e) => upd(s.id, 'desc', e.target.value)} placeholder={T(lang, 'What it includes', 'Qué incluye')} rows={2} style={{ ...rowInput, resize: 'none', lineHeight: 1.45 }} />
            </div>
            {hairline}
            <div style={{ padding: '11px 16px' }}>
              <div style={rowLabel}>{T(lang, 'Price', 'Precio')}</div>
              <input value={s.price} onChange={(e) => upd(s.id, 'price', e.target.value)} placeholder={T(lang, '$40 or From $200', '$40 o Desde $200')} inputMode="text" style={{ ...rowInput, fontFamily: 'var(--font-mono)', fontWeight: 700, color: 'var(--accent)' }} />
            </div>
            {hairline}
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px', padding: '8px 16px', minHeight: '44px', boxSizing: 'border-box' }}>
              <span style={{ fontSize: '0.94rem', color: 'var(--bone)' }}>{T(lang, 'Featured', 'Destacado')}</span>
              <IOSSwitch on={!!s.featured} onChange={(v) => upd(s.id, 'featured', v)} />
            </div>
            {hairline}
            <button onClick={() => setDelId(s.id)} style={{ width: '100%', minHeight: '46px', background: 'none', border: 'none', cursor: 'pointer', color: '#FF453A', fontFamily: 'var(--font-body)', fontSize: '0.94rem', fontWeight: 500 }}>{T(lang, 'Delete service', 'Borrar servicio')}</button>
          </div>
        );
      })}
      <button onClick={add} style={{ width: '100%', minHeight: '48px', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '8px', fontFamily: 'var(--font-mono)', fontSize: '0.62rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '13px', borderRadius: '20px', border: '1px dashed var(--bd-d2)', background: 'transparent', color: 'var(--accent)', cursor: 'pointer' }}><window.Icon name="plus" size={15} /> {T(lang, 'Add service', 'Agregar servicio')}</button>
      <ConfirmDialog lang={lang} open={delId !== null} title={T(lang, 'Delete service?', '¿Borrar servicio?')} message={T(lang, 'Remember to press Save to publish the change.', 'Recuerda presionar Guardar para publicar el cambio.')} confirmText={T(lang, 'Delete', 'Borrar')} danger onCancel={() => setDelId(null)} onConfirm={() => { del(delId); setDelId(null); }} />
    </EditorShell>
  );
}

/* Shared video-picker UI: preview + upload + reset-to-default. */
function VideoPicker({ lang, inputId, defaultSrc, customSrc, pending, onPick, onReset, err }) {
  const activeSrc = pending ? pending.preview : (customSrc || defaultSrc);
  const badge = pending ? T(lang, 'New video', 'Video nuevo') : customSrc ? T(lang, 'Your video', 'Tu video') : T(lang, 'Default video', 'Video por defecto');
  return (
    <>
      <div style={{ position: 'relative', aspectRatio: '4/5', maxWidth: '64%', borderRadius: 'var(--radius-md)', overflow: 'hidden', border: '1px solid var(--bd-d2)', background: '#000' }}>
        <video key={activeSrc} src={activeSrc} autoPlay muted loop playsInline style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />
        <span style={{ position: 'absolute', bottom: '10px', left: '10px', fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--bone)', background: 'rgba(0,0,0,.6)', padding: '4px 9px', borderRadius: '20px', backdropFilter: 'blur(5px)' }}>{badge}</span>
      </div>
      <input id={inputId} type="file" accept="video/*" style={{ display: 'none' }} onChange={(e) => { onPick(e.target.files && e.target.files[0]); e.target.value = ''; }} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: '9px', marginTop: '14px' }}>
        <label htmlFor={inputId} style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '8px', minHeight: '46px', boxSizing: 'border-box', fontFamily: 'var(--font-mono)', fontSize: '0.62rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '13px', borderRadius: 'var(--radius-pill)', border: 'none', background: 'var(--accent)', color: 'var(--on-accent)', cursor: 'pointer' }}><window.Icon name="upload" size={15} /> {T(lang, 'Upload new video', 'Subir video nuevo')}</label>
        {(customSrc || pending) && <button onClick={onReset} style={{ minHeight: '46px', boxSizing: 'border-box', fontFamily: 'var(--font-mono)', fontSize: '0.62rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '13px', borderRadius: 'var(--radius-pill)', border: '1px solid var(--bd-d2)', background: 'transparent', color: 'var(--bone)', cursor: 'pointer' }}>{T(lang, 'Use the default video', 'Usar el video por defecto')}</button>}
      </div>
      {err && <div style={{ color: '#FF453A', fontSize: '0.78rem', marginTop: '10px', lineHeight: 1.45 }}>{err}</div>}
      <p style={{ color: 'var(--muted)', fontSize: '0.72rem', fontStyle: 'italic', marginTop: '14px', lineHeight: 1.5 }}>{T(lang, `Tip: a 10–20 second clip works best (max ${MAX_VIDEO_MB}MB). Press Save to publish.`, `Consejo: un clip de 10–20 segundos funciona mejor (máx. ${MAX_VIDEO_MB}MB). Presiona Guardar para publicar.`)}</p>
    </>
  );
}

function HeroEditor({ lang, onBack }) {
  useContent();
  const cur = loadJSON('ms_hero', null);
  const customVid = cur && cur.type === 'video' ? cur.src : null;
  const [mode, setMode] = React.useState(cur && cur.type === 'image' ? 'photo' : 'video');
  const [img, setImg] = React.useState(cur && cur.type === 'image' ? cur.src : null);
  const [file, setFile] = React.useState(null);
  const [vid, setVid] = React.useState(null);          // pending video file
  const [resetVid, setResetVid] = React.useState(false); // "use default" chosen
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [saved, flash] = useSaved();
  const pickPhoto = (f) => { if (!f) return; setErr(''); setFile({ f, preview: URL.createObjectURL(f) }); setMode('photo'); };
  const pickVideo = (f) => {
    if (!f) return;
    setErr('');
    if (f.size > MAX_VIDEO_MB * 1024 * 1024) { setErr(T(lang, `That video is ${Math.round(f.size / 1024 / 1024)}MB — the max is ${MAX_VIDEO_MB}MB. Record a shorter clip.`, `Ese video pesa ${Math.round(f.size / 1024 / 1024)}MB — el máximo es ${MAX_VIDEO_MB}MB. Graba un clip más corto.`)); return; }
    setVid({ f, preview: URL.createObjectURL(f) }); setResetVid(false);
  };
  const save = async () => {
    setBusy(true); setErr('');
    try {
      if (mode === 'photo') {
        let url = img;
        if (file) url = await uploadPhoto(file.f);
        if (url && await saveJSON('ms_hero', { type: 'image', src: url })) { setImg(url); setFile(null); flash(); }
      } else if (vid) {
        const url = await uploadVideo(vid.f);
        if (await saveJSON('ms_hero', { type: 'video', src: url })) { setVid(null); flash(); }
      } else if (customVid && !resetVid) {
        flash(); // nothing changed
      } else if (await saveJSON('ms_hero', null)) { setImg(null); setFile(null); setVid(null); setResetVid(false); flash(); }
    } catch (e) {
      setErr(e && e.code === 'too-big'
        ? T(lang, `That video is ${e.mb}MB — the max is ${MAX_VIDEO_MB}MB.`, `Ese video pesa ${e.mb}MB — el máximo es ${MAX_VIDEO_MB}MB.`)
        : T(lang, 'Could not upload. Check your connection and try again.', 'No se pudo subir. Revisa tu conexión e inténtalo de nuevo.'));
    } finally { setBusy(false); }
  };
  const previewSrc = file ? file.preview : img;
  const seg = (id, label) => {
    const on = mode === id;
    return <button onClick={() => setMode(id)} style={{ flex: 1, minHeight: '44px', fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.08em', textTransform: 'uppercase', padding: '11px 8px', borderRadius: 'var(--radius-pill)', cursor: 'pointer', border: `1px solid ${on ? 'var(--accent)' : 'var(--bd-d2)'}`, background: on ? 'var(--accent)' : 'transparent', color: on ? 'var(--on-accent)' : 'var(--muted)' }}>{label}</button>;
  };
  return (
    <EditorShell lang={lang} onBack={onBack} title="Hero" onSave={save} saved={saved} busy={busy}>
      <p style={{ color: 'var(--muted)', fontSize: '0.78rem', margin: '2px 0 16px', lineHeight: 1.5 }}>{T(lang, 'The big video or photo at the top of your site.', 'El video o foto grande al inicio de tu sitio.')}</p>
      <div style={{ display: 'flex', gap: '8px', margin: '0 0 16px' }}>
        {seg('video', T(lang, 'Video', 'Video'))}
        {seg('photo', T(lang, 'Photo', 'Foto'))}
      </div>
      {mode === 'video'
        ? <VideoPicker lang={lang} inputId="hero_vid_up" defaultSrc="assets/hero.mp4" customSrc={resetVid ? null : customVid} pending={vid} onPick={pickVideo} onReset={() => { setVid(null); setResetVid(true); }} err={err} />
        : <>
            <div style={{ position: 'relative', aspectRatio: '4/5', maxWidth: '64%', borderRadius: 'var(--radius-md)', overflow: 'hidden', border: '1px solid var(--bd-d2)', background: '#000' }}>
              {previewSrc
                ? <img src={previewSrc} alt="" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }} />
                : <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--muted-2)', fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.1em', textTransform: 'uppercase' }}>{T(lang, 'No photo yet', 'Sin foto aún')}</div>}
              <span style={{ position: 'absolute', bottom: '10px', left: '10px', fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--bone)', background: 'rgba(0,0,0,.6)', padding: '4px 9px', borderRadius: '20px', backdropFilter: 'blur(5px)' }}>{T(lang, 'Photo', 'Foto')}</span>
            </div>
            <div style={{ maxWidth: '64%', marginTop: '14px' }}><UploadBox id="hero_up" label={T(lang, 'Choose photo', 'Elegir foto')} value={previewSrc} onFile={pickPhoto} /></div>
            {err && <div style={{ color: '#FF453A', fontSize: '0.78rem', marginTop: '10px' }}>{err}</div>}
          </>}
    </EditorShell>
  );
}

function SmpVideoEditor({ lang, onBack }) {
  useContent();
  const cur = loadJSON('ms_smp_video', null); // { src } | null
  const customVid = cur && cur.src ? cur.src : null;
  const [vid, setVid] = React.useState(null);
  const [resetVid, setResetVid] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [saved, flash] = useSaved();
  const pickVideo = (f) => {
    if (!f) return;
    setErr('');
    if (f.size > MAX_VIDEO_MB * 1024 * 1024) { setErr(T(lang, `That video is ${Math.round(f.size / 1024 / 1024)}MB — the max is ${MAX_VIDEO_MB}MB. Record a shorter clip.`, `Ese video pesa ${Math.round(f.size / 1024 / 1024)}MB — el máximo es ${MAX_VIDEO_MB}MB. Graba un clip más corto.`)); return; }
    setVid({ f, preview: URL.createObjectURL(f) }); setResetVid(false);
  };
  const save = async () => {
    setBusy(true); setErr('');
    try {
      if (vid) {
        const url = await uploadVideo(vid.f);
        if (await saveJSON('ms_smp_video', { src: url })) { setVid(null); flash(); }
      } else if (customVid && !resetVid) {
        flash();
      } else if (await saveJSON('ms_smp_video', null)) { setVid(null); setResetVid(false); flash(); }
    } catch (e) {
      setErr(e && e.code === 'too-big'
        ? T(lang, `That video is ${e.mb}MB — the max is ${MAX_VIDEO_MB}MB.`, `Ese video pesa ${e.mb}MB — el máximo es ${MAX_VIDEO_MB}MB.`)
        : T(lang, 'Could not upload. Check your connection and try again.', 'No se pudo subir. Revisa tu conexión e inténtalo de nuevo.'));
    } finally { setBusy(false); }
  };
  return (
    <EditorShell lang={lang} onBack={onBack} title={T(lang, 'SMP video', 'Video de SMP')} onSave={save} saved={saved} busy={busy}>
      <p style={{ color: 'var(--muted)', fontSize: '0.78rem', margin: '2px 0 16px', lineHeight: 1.5 }}>{T(lang, 'The video on the scalp micropigmentation card.', 'El video de la tarjeta de micropigmentación capilar.')}</p>
      <VideoPicker lang={lang} inputId="smp_vid_up" defaultSrc="assets/smp.mp4" customSrc={resetVid ? null : customVid} pending={vid} onPick={pickVideo} onReset={() => { setVid(null); setResetVid(true); }} err={err} />
    </EditorShell>
  );
}

function ImagesEditor({ lang, onBack }) {
  const [photo, setPhoto] = React.useState(loadJSON('ms_about_photo', null));
  const [file, setFile] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [saved, flash] = useSaved();
  const pick = (f) => { if (!f) return; setFile({ f, preview: URL.createObjectURL(f) }); };
  const save = async () => {
    setBusy(true);
    try {
      let url = photo;
      if (file) url = await uploadPhoto(file.f);
      if (url && await saveJSON('ms_about_photo', url)) { setPhoto(url); setFile(null); flash(); }
    } catch (e) {} finally { setBusy(false); }
  };
  const resetPhoto = async () => { if (await saveJSON('ms_about_photo', null)) { setPhoto(null); setFile(null); flash(); } };
  const previewSrc = file ? file.preview : (photo || 'assets/michael.jpg');
  return (
    <EditorShell lang={lang} onBack={onBack} title={T(lang, "Michael’s photo", 'Foto de Michael')} onSave={save} saved={saved}>
      <p style={{ color: 'var(--muted-2)', fontSize: '0.74rem', margin: '0 0 16px', lineHeight: 1.5 }}>{T(lang, 'The photo of you in the “About” section of the site.', 'La foto tuya que aparece en la sección “Nosotros” del sitio.')}</p>
      <div style={{ maxWidth: '64%' }}><UploadBox id="about_up" label={busy ? T(lang, 'Saving…', 'Guardando…') : T(lang, 'Change photo', 'Cambiar foto')} value={previewSrc} onFile={pick} /></div>
      <button onClick={resetPhoto} style={{ marginTop: '14px', background: 'none', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-pill)', padding: '10px 16px', cursor: 'pointer', color: 'var(--muted)', fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.08em', textTransform: 'uppercase' }}>{T(lang, 'Reset to default', 'Restablecer')}</button>
    </EditorShell>
  );
}

const HRS_DOW = { EN: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], ES: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'] };
const HRS_TIMES = ['7A', '8A', '9A', '10A', '11A', '12P', '1P', '2P', '3P', '4P', '5P', '6P', '7P', '8P', '9P'];
const hrsFmt = (t) => t.slice(0, -1) + (t.slice(-1) === 'A' ? ' AM' : ' PM');
const hrsCompress = (list, dow) => {
  if (!list.length) return '—';
  const runs = []; let start = list[0], prev = list[0];
  for (let k = 1; k < list.length; k++) { if (list[k] === prev + 1) { prev = list[k]; } else { runs.push([start, prev]); start = list[k]; prev = list[k]; } }
  runs.push([start, prev]);
  return runs.map(([a, b]) => a === b ? dow[a] : (b === a + 1 ? `${dow[a]} · ${dow[b]}` : `${dow[a]}–${dow[b]}`)).join(' · ');
};

function HoursEditor({ lang, onBack }) {
  const stored = loadJSON('ms_hours', DEFAULT_HOURS);
  const [days, setDays] = React.useState(() => Array.isArray(stored.days) ? stored.days : [2, 3, 4, 5, 6]);
  const [open, setOpen] = React.useState(() => stored.open || '9A');
  const [close, setClose] = React.useState(() => stored.close || '7P');
  const [note, setNote] = React.useState(stored.note || DEFAULT_HOURS.note);
  const [saved, flash] = useSaved();
  const dow = HRS_DOW[lang];
  const toggleDay = (i) => setDays((p) => p.includes(i) ? p.filter((d) => d !== i) : [...p, i].sort((a, b) => a - b));
  const closedDays = [0, 1, 2, 3, 4, 5, 6].filter((d) => !days.includes(d));
  const hoursStr = days.length ? `${hrsCompress(days, dow)} · ${open}–${close}` : T(lang, 'Closed', 'Cerrado');
  const closedStr = hrsCompress(closedDays, dow);
  const save = () => { saveJSON('ms_hours', { hours: hoursStr, closed: closedStr, note, days, open, close }).then((ok) => { if (ok) flash(); }); };
  const timeSel = (val, setVal, label) => (
    <div style={{ flex: 1 }}>
      <div style={edLabel}>{label}</div>
      <div style={{ position: 'relative' }}>
        <select value={val} onChange={(e) => setVal(e.target.value)} style={{ width: '100%', appearance: 'none', WebkitAppearance: 'none', MozAppearance: 'none', fontFamily: 'var(--font-mono)', fontSize: '0.8rem', padding: '12px 34px 12px 14px', borderRadius: 'var(--radius-input)', border: '1px solid var(--bd-d)', background: 'var(--ink-2)', color: 'var(--bone)', cursor: 'pointer', outline: 'none' }}>
          {HRS_TIMES.map((t) => <option key={t} value={t} style={{ background: 'var(--ink-2)', color: 'var(--bone)' }}>{hrsFmt(t)}</option>)}
        </select>
        <span style={{ position: 'absolute', right: '10px', top: 0, bottom: 0, display: 'flex', alignItems: 'center', pointerEvents: 'none', color: 'var(--accent)' }}><span style={{ transform: 'rotate(90deg)', display: 'inline-flex' }}><window.Icon name="chevron" size={13} /></span></span>
      </div>
    </div>
  );
  return (
    <EditorShell lang={lang} onBack={onBack} title={T(lang, 'Hours', 'Horario')} onSave={save} saved={saved}>
      <p style={{ color: 'var(--muted-2)', fontSize: '0.74rem', margin: '0 0 16px', lineHeight: 1.5 }}>{T(lang, 'Shown in the “Visit us” card on your site.', 'Se muestra en la tarjeta “Visítanos” de tu sitio.')}</p>
      <div style={edLabel}>{T(lang, 'Open days', 'Días abiertos')}</div>
      <div style={{ display: 'flex', gap: '6px', marginBottom: '20px' }}>
        {dow.map((d, i) => {
          const on = days.includes(i);
          return <button key={i} onClick={() => toggleDay(i)} aria-pressed={on} style={{ flex: 1, fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.02em', textTransform: 'uppercase', padding: '11px 2px', borderRadius: 'var(--radius-md)', cursor: 'pointer', border: `1px solid ${on ? 'var(--accent)' : 'var(--bd-d2)'}`, background: on ? 'var(--accent)' : 'transparent', color: on ? 'var(--on-accent)' : 'var(--muted-2)' }}>{d}</button>;
        })}
      </div>
      <div style={{ display: 'flex', gap: '12px', marginBottom: '20px' }}>
        {timeSel(open, setOpen, T(lang, 'Opens', 'Abre'))}
        {timeSel(close, setClose, T(lang, 'Closes', 'Cierra'))}
      </div>
      <div style={edLabel}>{T(lang, 'Location note', 'Nota de ubicación')}</div>
      <input value={note} onChange={(e) => setNote(e.target.value)} style={{ ...edInput, marginBottom: '20px' }} />
      {/* live preview of the card */}
      <div style={{ background: 'var(--card)', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-md)', padding: '16px' }}>
        <div style={{ ...edLabel, color: 'var(--accent)' }}>{T(lang, 'Preview', 'Vista previa')}</div>
        <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '1.05rem', color: 'var(--bone)', marginTop: '4px' }}>{hoursStr}</div>
        <div style={{ fontSize: '0.78rem', color: 'var(--muted)', marginTop: '3px' }}>{T(lang, 'Closed', 'Cerrado')}: {closedStr}</div>
        <div style={{ fontSize: '0.78rem', color: 'var(--muted)', marginTop: '2px' }}>{note}</div>
      </div>
      <p style={{ color: 'var(--muted-2)', fontSize: '0.7rem', fontStyle: 'italic', marginTop: '16px', lineHeight: 1.5 }}>{T(lang, 'Real availability and appointments live in Booksy.', 'La disponibilidad y las citas reales están en Booksy.')}</p>
    </EditorShell>
  );
}

function AddressEditor({ lang, onBack }) {
  const [addr, setAddr] = React.useState(loadJSON('ms_address', ''));
  const [saved, flash] = useSaved();
  const save = () => { saveJSON('ms_address', addr).then((ok) => { if (ok) flash(); }); };
  return (
    <EditorShell lang={lang} onBack={onBack} title={T(lang, 'Address', 'Dirección')} onSave={save} saved={saved}>
      <p style={{ color: 'var(--muted-2)', fontSize: '0.74rem', margin: '0 0 16px', lineHeight: 1.5 }}>{T(lang, 'Your shop address — it opens in Maps from the “Get directions” button on your site.', 'La dirección de tu barbería — abre en Maps desde el botón “Cómo llegar” de tu sitio.')}</p>
      <div style={edLabel}>{T(lang, 'Full address', 'Dirección completa')}</div>
      <textarea value={addr} onChange={(e) => setAddr(e.target.value)} rows={3} placeholder={T(lang, 'e.g. 1234 Main St, Houston, TX 77001', 'ej. 1234 Main St, Houston, TX 77001')} style={{ ...edInput, resize: 'vertical', fontFamily: 'var(--font-body)' }} />
    </EditorShell>
  );
}

/* —— Reusable confirm dialog — styled like a native iOS alert —— */
function ConfirmDialog({ lang, open, title, message, confirmText, danger, onConfirm, onCancel }) {
  if (!open) return null;
  return (
    <div onClick={onCancel} style={{ position: 'fixed', inset: 0, zIndex: 300, background: 'rgba(0,0,0,.55)', backdropFilter: 'blur(6px)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '24px' }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: 'min(280px, 84vw)', background: 'var(--ink-2)', border: '1px solid var(--bd-d)', borderRadius: '16px', overflow: 'hidden', textAlign: 'center', boxShadow: '0 24px 70px -20px rgba(0,0,0,.8)' }}>
        <div style={{ padding: '22px 18px 18px' }}>
          <div style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: '1rem', color: 'var(--bone)', lineHeight: 1.25 }}>{title}</div>
          {message && <p style={{ color: 'var(--muted)', fontSize: '0.8rem', margin: '7px 0 0', lineHeight: 1.45 }}>{message}</p>}
        </div>
        <div style={{ height: '1px', background: 'var(--bd-d)' }} />
        <div style={{ display: 'flex' }}>
          <button onClick={onCancel} style={{ flex: 1, minHeight: '46px', border: 'none', background: 'transparent', cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: '0.95rem', fontWeight: 400, color: 'var(--accent)' }}>{T(lang, 'Cancel', 'Cancelar')}</button>
          <div style={{ width: '1px', background: 'var(--bd-d)' }} />
          <button onClick={onConfirm} style={{ flex: 1, minHeight: '46px', border: 'none', background: 'transparent', cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: '0.95rem', fontWeight: 600, color: danger ? '#FF453A' : 'var(--accent)' }}>{confirmText || T(lang, 'Confirm', 'Confirmar')}</button>
        </div>
      </div>
    </div>
  );
}

/* Michael's app — full-screen iOS-style shell (top bar · screens · bottom tab bar) */
function OwnerPanel({ lang, setLang, onBack }) {
  const [authed, setAuthed] = React.useState(false);
  const [checking, setChecking] = React.useState(true);
  const [email, setEmail] = React.useState('');
  const [pw, setPw] = React.useState('');
  const [authErr, setAuthErr] = React.useState('');
  const [busyAuth, setBusyAuth] = React.useState(false);
  React.useEffect(() => {
    if (!sb) { setChecking(false); return; }
    sb.auth.getSession().then(({ data }) => { setAuthed(!!(data && data.session)); setChecking(false); });
    const { data: sub } = sb.auth.onAuthStateChange((_e, session) => { setAuthed(!!session); });
    return () => { try { sub.subscription.unsubscribe(); } catch (e) {} };
  }, []);
  const tryLogin = async () => {
    if (!sb) { setAuthErr(T(lang, 'No connection.', 'Sin conexión.')); return; }
    setBusyAuth(true); setAuthErr('');
    const { error } = await sb.auth.signInWithPassword({ email: email.trim(), password: pw });
    setBusyAuth(false);
    if (error) setAuthErr(T(lang, 'Wrong email or password.', 'Correo o contraseña incorrectos.'));
  };
  const logout = async () => { try { if (sb) await sb.auth.signOut(); } catch (e) {} setAuthed(false); setEmail(''); setPw(''); };

  const [tab, setTab] = React.useState('hoy');
  const [uploadFrom, setUploadFrom] = React.useState('hoy');
  const goUpload = (from) => { setUploadFrom(from); setTab('subir'); };
  const [edit, setEdit] = React.useState(null);
  const items = useGallery() || [];
  useContent();
  const [isBA, setIsBA] = React.useState(false);
  const [cat, setCat] = React.useState('corte-barba');
  const [label, setLabel] = React.useState('');
  const [before, setBefore] = React.useState(null);
  const [after, setAfter] = React.useState(null);
  const [single, setSingle] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [filter, setFilter] = React.useState('all');
  const [confirm, setConfirm] = React.useState(null); // { title, message, confirmText, onConfirm }
  const [editing, setEditing] = React.useState(null); // gallery item being edited
  const [editCat, setEditCat] = React.useState('corte-barba');
  const [editLabel, setEditLabel] = React.useState('');
  const [editBusy, setEditBusy] = React.useState(false);

  // —— Add to home screen ——
  const [canInstall, setCanInstall] = React.useState(!!window.__msInstallPrompt);
  const [showInstallHelp, setShowInstallHelp] = React.useState(false);
  React.useEffect(() => {
    const on = () => setCanInstall(true);
    window.addEventListener('ms-installable', on);
    return () => window.removeEventListener('ms-installable', on);
  }, []);
  const isStandalone = (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) || window.navigator.standalone === true;
  const doInstall = async () => {
    const p = window.__msInstallPrompt;
    if (p) {
      p.prompt();
      try { await p.userChoice; } catch (e) { /* dismissed */ }
      window.__msInstallPrompt = null;
      setCanInstall(false);
    } else {
      setShowInstallHelp((v) => !v); // iPhone/Safari: no prompt exists, show the steps
    }
  };

  const openEdit = (it) => { setEditing(it); setEditCat(it.cat || 'corte-barba'); setEditLabel(it.label || ''); };
  const saveEdit = async () => {
    if (!editing) return;
    setEditBusy(true);
    try { await updateGalleryItem(editing.id, { cat: editCat, label: editLabel }); setEditing(null); }
    catch (e) { setErr(T(lang, 'Could not save.', 'No se pudo guardar.')); }
    finally { setEditBusy(false); }
  };
  const askDelete = (it) => setConfirm({
    title: T(lang, 'Delete photo?', '¿Borrar foto?'),
    message: T(lang, 'It will be removed from the gallery and your site. This cannot be undone.', 'Se quitará de la galería y de tu sitio. No se puede deshacer.'),
    confirmText: T(lang, 'Delete', 'Borrar'),
    onConfirm: async () => { setConfirm(null); await remove(it.id); },
  });

  const pick = (file, setter) => { if (!file) return; setErr(''); setter({ file, preview: URL.createObjectURL(file) }); };
  const reset = () => { [before, after, single].forEach((x) => { if (x && x.preview) { try { URL.revokeObjectURL(x.preview); } catch (e) {} } }); setBefore(null); setAfter(null); setSingle(null); setLabel(''); };
  const canAdd = isBA ? (before && after) : single;
  const add = async () => {
    if (!canAdd || busy) return;
    setBusy(true); setErr('');
    try {
      if (isBA) {
        const [bu, au] = await Promise.all([uploadPhoto(before.file), uploadPhoto(after.file)]);
        await addGalleryItem({ type: 'ba', cat, label, before: bu, after: au });
      } else {
        const su = await uploadPhoto(single.file);
        await addGalleryItem({ type: 'single', cat, label, src: su });
      }
      reset(); setTab('galeria');
    } catch (e) { setErr(T(lang, 'Upload failed — check your connection.', 'No se pudo subir — revisa tu conexión.')); }
    finally { setBusy(false); }
  };
  const remove = async (id) => { setErr(''); try { await removeGalleryItem(id); } catch (e) { setErr(T(lang, 'Could not delete.', 'No se pudo borrar.')); } };
  const shown = filter === 'all' ? items : items.filter((x) => x.cat === filter);

  const pill = (active, sm) => ({ fontFamily: 'var(--font-mono)', fontSize: sm ? '0.5rem' : '0.55rem', letterSpacing: '0.08em', textTransform: 'uppercase', padding: sm ? '7px 11px' : '8px 12px', borderRadius: 'var(--radius-pill)', cursor: 'pointer', flex: 'none', border: `1px solid ${active ? 'var(--accent)' : 'var(--bd-d)'}`, background: active ? 'var(--accent)' : 'transparent', color: active ? 'var(--on-accent)' : 'var(--muted)' });
  const eyebrow = (t) => <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--accent)' }}>{t}</div>;
  const appH = (t) => <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.75rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', margin: '6px 0 16px', lineHeight: 0.95 }}>{t}</div>;
  const wordmark = (sz) => <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: sz || '1rem', textTransform: 'uppercase', letterSpacing: '-0.02em', color: 'var(--bone)', lineHeight: 1 }}>MICHAEL<span style={{ color: 'var(--accent)' }}>/</span>STYLE</div>;
  /* iOS Settings-style row: tinted icon square, 16px label, thin chevron. */
  const settingRow = (icon, text, right, onClick, danger) => (
    <div onClick={onClick} style={{ display: 'flex', alignItems: 'center', gap: '13px', padding: '9px 16px', minHeight: '50px', boxSizing: 'border-box', cursor: onClick ? 'pointer' : 'default' }}>
      <span style={{ width: '30px', height: '30px', borderRadius: '8px', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', background: danger ? 'rgba(255,69,58,.14)' : 'color-mix(in srgb,var(--accent) 16%,var(--card))', color: danger ? '#FF453A' : 'var(--accent)' }}><window.Icon name={icon} size={16} /></span>
      <span style={{ flex: 1, fontSize: '0.95rem', color: danger ? '#FF453A' : 'var(--bone)' }}>{text}</span>
      <span style={{ display: 'inline-flex', alignItems: 'center', color: 'var(--muted-2)' }}>{right}</span>
    </div>
  );
  /* Inset-grouped card of rows (skips falsy rows, hairlines start after the icon column). */
  const group = (...rows) => {
    const kids = rows.filter(Boolean);
    return (
      <div style={{ background: 'var(--card)', borderRadius: '20px', overflow: 'hidden', marginBottom: '10px' }}>
        {kids.map((k, i) => <React.Fragment key={i}>{k}{i < kids.length - 1 && <div style={{ height: '1px', background: 'var(--bd-d)', marginLeft: '59px' }} />}</React.Fragment>)}
      </div>
    );
  };
  const groupHead = (t, accentColor) => <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.52rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: accentColor ? 'var(--accent)' : 'var(--muted)', margin: '22px 16px 8px' }}>{t}</div>;

  /* —— PIN gate (full screen) —— */
  if (checking) {
    return (
      <div style={{ position: 'fixed', inset: 0, zIndex: 100, background: 'var(--ink)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted-2)' }}>{T(lang, 'Loading…', 'Cargando…')}</div>
      </div>
    );
  }
  if (!authed) {
    const authInput = { width: '100%', boxSizing: 'border-box', fontFamily: 'var(--font-body)', fontSize: '1rem', padding: '14px 15px', borderRadius: 'var(--radius-input)', border: `1px solid ${authErr ? 'var(--accent)' : 'var(--bd-d)'}`, background: 'var(--card)', color: 'var(--bone)', outline: 'none', display: 'block' };
    return (
      <div style={{ position: 'fixed', inset: 0, zIndex: 100, background: 'var(--ink)' }}>
        <div style={{ height: '100%', width: '100%', maxWidth: '480px', margin: '0 auto', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 'max(24px,env(safe-area-inset-top)) 28px max(24px,env(safe-area-inset-bottom))' }}>
          {wordmark('1.35rem')}
          <div style={{ marginTop: '30px' }}>{eyebrow(T(lang, 'Owner panel', 'Panel de Michael'))}</div>
          <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '2rem', textTransform: 'uppercase', letterSpacing: '-0.04em', color: 'var(--bone)', margin: '8px 0 20px', lineHeight: 0.95 }}>{T(lang, 'Log in', 'Iniciar sesión')}</h2>
          <input type="email" value={email} onChange={(e) => { setEmail(e.target.value); setAuthErr(''); }} placeholder={T(lang, 'Email', 'Correo')} autoCapitalize="none" autoCorrect="off" inputMode="email" style={{ ...authInput, marginBottom: '10px' }} />
          <input type="password" value={pw} onChange={(e) => { setPw(e.target.value); setAuthErr(''); }} onKeyDown={(e) => { if (e.key === 'Enter') tryLogin(); }} placeholder={T(lang, 'Password', 'Contraseña')} style={authInput} />
          {authErr && <div style={{ color: 'var(--accent)', fontSize: '0.74rem', marginTop: '9px' }}>{authErr}</div>}
          <button onClick={tryLogin} disabled={busyAuth} style={{ width: '100%', marginTop: '14px', fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '15px', borderRadius: 'var(--radius-pill)', border: 'none', cursor: busyAuth ? 'default' : 'pointer', background: 'var(--accent)', color: 'var(--on-accent)', opacity: busyAuth ? 0.7 : 1 }}>{busyAuth ? T(lang, 'Entering…', 'Entrando…') : T(lang, 'Log in', 'Entrar')}</button>
        </div>
      </div>
    );
  }

  if (edit === 'servicios') return <ServicesEditor lang={lang} onBack={() => setEdit(null)} />;
  if (edit === 'hero') return <HeroEditor lang={lang} onBack={() => setEdit(null)} />;
  if (edit === 'smpvideo') return <SmpVideoEditor lang={lang} onBack={() => setEdit(null)} />;
  if (edit === 'imagenes') return <ImagesEditor lang={lang} onBack={() => setEdit(null)} />;
  if (edit === 'calendario') return <HoursEditor lang={lang} onBack={() => setEdit(null)} />;
  if (edit === 'direccion') return <AddressEditor lang={lang} onBack={() => setEdit(null)} />;

  /* —— screens —— */
  const photoCard = (it) => (
    <div key={it.id} style={{ position: 'relative' }}>
      {it.type === 'ba'
        ? <BeforeAfter lang={lang} before={it.before} after={it.after} hint={false} />
        : <img src={it.src} alt={it.label || ''} style={{ display: 'block', width: '100%', aspectRatio: '4/5', objectFit: 'cover', borderRadius: 'var(--radius-md)', border: '1px solid var(--bd-d)' }} />}
      <div style={{ position: 'absolute', top: '9px', right: '9px', display: 'flex', gap: '6px', zIndex: 8 }}>
        <button onClick={() => openEdit(it)} aria-label="Edit" style={{ width: '30px', height: '30px', borderRadius: '50%', border: 'none', cursor: 'pointer', background: 'rgba(0,0,0,.6)', color: 'var(--bone)', display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(4px)' }}><window.Icon name="pencil" size={14} /></button>
        <button onClick={() => shareOrDownload(it.type === 'ba' ? it.after : it.src, (it.label || 'michael-style') + '.jpg')} aria-label="Share" style={{ width: '30px', height: '30px', borderRadius: '50%', border: 'none', cursor: 'pointer', background: 'rgba(0,0,0,.6)', color: 'var(--bone)', display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(4px)' }}><window.Icon name="share" size={14} /></button>
        <button onClick={() => askDelete(it)} aria-label="Delete" style={{ width: '30px', height: '30px', borderRadius: '50%', border: 'none', cursor: 'pointer', background: 'rgba(0,0,0,.6)', color: 'var(--bone)', display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(4px)' }}><window.Icon name="x" size={15} /></button>
      </div>
      <div style={{ display: 'flex', gap: '7px', alignItems: 'center', marginTop: '8px', flexWrap: 'wrap' }}>
        {it.type === 'ba' && <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.46rem', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--accent)', border: '1px solid var(--bd-d2)', borderRadius: '20px', padding: '2px 7px' }}>{T(lang, 'B/A', 'A/D')}</span>}
        {it.cat && <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--muted)' }}>{catLabel(lang, it.cat)}</span>}
      </div>
    </div>
  );

  let screen;
  if (tab === 'subir') {
    screen = (
      <div style={{ padding: '12px 18px 24px' }}>
        <button onClick={() => setTab(uploadFrom)} style={{ display: 'inline-flex', alignItems: 'center', gap: '5px', background: 'none', border: 'none', cursor: 'pointer', color: 'var(--muted)', fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.08em', textTransform: 'uppercase', padding: 0, marginBottom: '12px' }}>
          <span style={{ transform: 'rotate(180deg)', display: 'inline-flex' }}><window.Icon name="chevron" size={13} /></span> {T(lang, 'Back', 'Atrás')}
        </button>
        {eyebrow(T(lang, 'New photo', 'Nueva foto'))}
        {appH(T(lang, 'Upload', 'Subir'))}
        <div style={{ background: 'var(--card)', borderRadius: '16px', padding: '8px 16px', minHeight: '48px', boxSizing: 'border-box', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px', marginBottom: '14px' }}>
          <span style={{ fontSize: '0.95rem', color: 'var(--bone)' }}>{T(lang, 'Before & after', 'Antes y después')}</span>
          <IOSSwitch on={isBA} onChange={() => { setIsBA((v) => !v); reset(); }} />
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: isBA ? '1fr 1fr' : '1fr', gap: '12px', maxWidth: isBA ? '100%' : '55%' }}>
          {isBA
            ? <><UploadBox id="up_before" label={T(lang, 'Before', 'Antes')} value={before?.preview} onFile={(f) => pick(f, setBefore)} /><UploadBox id="up_after" label={T(lang, 'After', 'Después')} value={after?.preview} onFile={(f) => pick(f, setAfter)} /></>
            : <UploadBox id="up_single" label={T(lang, 'Photo', 'Foto')} value={single?.preview} onFile={(f) => pick(f, setSingle)} />}
        </div>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--muted-2)', margin: '18px 0 8px' }}>{T(lang, 'Category', 'Categoría')}</div>
        <div style={{ display: 'flex', gap: '7px', flexWrap: 'wrap' }}>
          {CATS.map((c) => <button key={c.id} onClick={() => setCat(c.id)} style={pill(cat === c.id)}>{lang === 'ES' ? c.es : c.en}</button>)}
        </div>
        <input value={label} onChange={(e) => setLabel(e.target.value)} placeholder={T(lang, 'Note (optional)', 'Nota (opcional)')} style={{ width: '100%', boxSizing: 'border-box', fontFamily: 'var(--font-body)', fontSize: '1rem', padding: '12px 14px', borderRadius: 'var(--radius-input)', border: '1px solid var(--bd-d)', background: 'var(--ink-2)', color: 'var(--bone)', marginTop: '16px', outline: 'none', display: 'block' }} />
        {err && <div style={{ color: 'var(--accent)', fontSize: '0.74rem', marginTop: '10px' }}>{err}</div>}
        <button onClick={add} disabled={!canAdd || busy} style={{ width: '100%', marginTop: '16px', fontFamily: 'var(--font-mono)', fontSize: '0.68rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '15px', borderRadius: 'var(--radius-pill)', border: 'none', cursor: canAdd && !busy ? 'pointer' : 'not-allowed', background: canAdd && !busy ? 'var(--accent)' : 'var(--card)', color: canAdd && !busy ? 'var(--on-accent)' : 'var(--muted-2)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '8px' }}><window.Icon name="plus" size={16} /> {busy ? T(lang, 'Processing…', 'Procesando…') : T(lang, 'Upload', 'Subir')}</button>
      </div>
    );
  } else if (tab === 'yo') {
    screen = (
      <div style={{ padding: '12px 18px 24px' }}>
        {/* iOS profile header: centered circular avatar + name */}
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', margin: '10px 0 20px' }}>
          <img src={loadJSON('ms_about_photo', null) || 'assets/michael.jpg'} alt="Michael Adonis" loading="lazy" style={{ width: '110px', height: '110px', borderRadius: '50%', objectFit: 'cover', objectPosition: 'center top', border: '2px solid var(--bd-d2)', display: 'block' }} />
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.5rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', margin: '14px 0 4px', lineHeight: 0.95 }}>Michael Adonis</div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.52rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted)' }}>{T(lang, 'Dominican Barbershop & SMP · Houston', 'Barbería Dominicana & SMP · Houston')}</div>
        </div>
        <a href={BOOKSY_URL} target="_blank" rel="noopener noreferrer" style={{ display: 'inline-flex', width: '100%', boxSizing: 'border-box', alignItems: 'center', justifyContent: 'center', gap: '8px', minHeight: '48px', fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '14px', borderRadius: 'var(--radius-pill)', background: 'var(--accent)', color: 'var(--on-accent)', textDecoration: 'none' }}><window.Icon name="book" size={15} /> {T(lang, 'Open Booksy', 'Abrir Booksy')}</a>

        {groupHead(T(lang, 'Edit site', 'Editar sitio'), true)}
        {group(
          settingRow('scissors', T(lang, 'Services', 'Servicios'), <window.Icon name="chevron" size={15} />, () => setEdit('servicios')),
          settingRow('camera', T(lang, 'Hero photo/video', 'Foto/Video del hero'), <window.Icon name="chevron" size={15} />, () => setEdit('hero')),
          settingRow('upload', T(lang, 'SMP video', 'Video de SMP'), <window.Icon name="chevron" size={15} />, () => setEdit('smpvideo')),
          settingRow('me', T(lang, "Michael’s photo", 'Foto de Michael'), <window.Icon name="chevron" size={15} />, () => setEdit('imagenes')),
          settingRow('clock', T(lang, 'Calendar / Hours', 'Calendario / Horario'), <window.Icon name="chevron" size={15} />, () => setEdit('calendario')),
          settingRow('pin', T(lang, 'Address', 'Dirección'), <window.Icon name="chevron" size={15} />, () => setEdit('direccion'))
        )}

        {groupHead(T(lang, 'Settings', 'Ajustes'))}
        {group(
          settingRow('globe', T(lang, 'Language', 'Idioma'), <window.LangToggle value={lang} onChange={setLang} />),
          !isStandalone && settingRow('plus', T(lang, 'Install app', 'Instalar app'), <window.Icon name="chevron" size={15} />, doInstall),
          isStandalone && settingRow('check', T(lang, 'App installed', 'App instalada'), null)
        )}
        {!isStandalone && showInstallHelp && (
          <div style={{ background: 'var(--ink-2)', border: '1px solid var(--bd-d)', borderLeft: '3px solid var(--accent)', borderRadius: 'var(--radius-md)', padding: '14px 16px', margin: '0 0 10px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--accent)', marginBottom: '8px' }}>{T(lang, 'On iPhone', 'En iPhone')}</div>
            <div style={{ fontSize: '0.8rem', color: 'var(--bone)', lineHeight: 1.55 }}>
              {T(lang, '1. Open this page in Safari.  2. Tap Share at the bottom.  3. Choose “Add to Home Screen”.',
                     '1. Abre esta página en Safari.  2. Toca Compartir (⬆) abajo.  3. Elige “Añadir a pantalla de inicio”.')}
            </div>
            <div style={{ fontSize: '0.72rem', color: 'var(--muted)', marginTop: '8px', fontStyle: 'italic' }}>{T(lang, 'The icon will open straight into your panel.', 'El icono abrirá directo en tu panel.')}</div>
          </div>
        )}
        {group(
          settingRow('lock', T(lang, 'Lock app', 'Bloquear app'), null, logout, true)
        )}
        <div style={{ margin: '14px 16px 0', fontSize: '0.7rem', color: 'var(--muted-2)', fontStyle: 'italic', lineHeight: 1.5 }}>{T(lang, 'Your changes (photos, services, hours…) publish live to your site, on every device.', 'Tus cambios (fotos, servicios, horario…) se publican en vivo en tu sitio, en todos los dispositivos.')}</div>
        <div style={{ textAlign: 'center', marginTop: '28px', paddingTop: '20px', borderTop: '1px solid var(--bd-d)' }}>
          <div style={{ display: 'inline-flex' }}>{wordmark('1.1rem')}</div>
          <div style={{ fontStyle: 'italic', color: 'var(--muted-2)', fontSize: '0.72rem', marginTop: '8px' }}>Dios primero.</div>
        </div>
      </div>
    );
  } else if (tab === 'galeria') {
    screen = (
      <div style={{ padding: '12px 18px 24px' }}>
        {eyebrow(T(lang, 'The work', 'El trabajo'))}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px', margin: '6px 0 16px' }}>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.75rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', lineHeight: 0.95 }}>{T(lang, 'Gallery', 'Galería')}</div>
          <button onClick={() => goUpload('galeria')} aria-label={T(lang, 'Upload photo', 'Subir foto')} title={T(lang, 'Upload photo', 'Subir foto')} style={{ flex: 'none', width: '44px', height: '44px', borderRadius: '50%', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', background: 'color-mix(in srgb,var(--accent) 16%,var(--card))', border: '1px solid color-mix(in srgb,var(--accent) 40%,transparent)', color: 'var(--accent)' }}><window.Icon name="upload" size={20} /></button>
        </div>
        {items.length > 0 && (
          <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap', marginBottom: '16px' }}>
            <button onClick={() => setFilter('all')} style={pill(filter === 'all', true)}>{T(lang, 'All', 'Todos')}</button>
            {CATS.map((c) => <button key={c.id} onClick={() => setFilter(c.id)} style={pill(filter === c.id, true)}>{lang === 'ES' ? c.es : c.en}</button>)}
          </div>
        )}
        {shown.length === 0
          ? <div style={{ color: 'var(--muted-2)', fontStyle: 'italic', fontSize: '0.85rem', padding: '30px 0', textAlign: 'center' }}>{items.length === 0 ? T(lang, 'No photos yet — tap the upload button above.', 'Aún no hay fotos — toca el botón de subir arriba.') : T(lang, 'None in this category.', 'Ninguna en esta categoría.')}</div>
          : <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: '12px' }}>{shown.map(photoCard)}</div>}
      </div>
    );
  } else {
    const recent = items.slice(0, 6);
    let today = T(lang, 'Today', 'Hoy');
    try { today = new Date().toLocaleDateString(lang === 'ES' ? 'es-ES' : 'en-US', { weekday: 'long', day: 'numeric', month: 'short' }); } catch (e) {}
    const quick = (icon, text, onClick) => (
      <button onClick={onClick} style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '12px', padding: '16px', background: 'var(--card)', border: '1px solid var(--bd-d)', borderRadius: 'var(--radius-md)', cursor: 'pointer', textAlign: 'left' }}>
        <span style={{ width: '34px', height: '34px', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'color-mix(in srgb,var(--accent) 16%,var(--card))', color: 'var(--accent)' }}><window.Icon name={icon} size={17} /></span>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--bone)' }}>{text}</span>
      </button>
    );
    screen = (
      <div style={{ padding: '12px 18px 24px' }}>
        {eyebrow(today)}
        {appH(T(lang, 'Hi, Michael', 'Buenas, Michael'))}
        <a href={BOOKSY_URL} target="_blank" rel="noopener noreferrer" style={{ display: 'block', textDecoration: 'none', background: 'color-mix(in srgb,var(--accent) 12%,var(--card))', border: '1px solid color-mix(in srgb,var(--accent) 40%,transparent)', borderRadius: 'var(--radius-lg)', padding: '20px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.55rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Bookings & income', 'Citas & ingresos')}</span>
            <span style={{ color: 'var(--accent)' }}><window.Icon name="book" size={18} /></span>
          </div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.7rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', margin: '10px 0 2px', lineHeight: 0.95 }}>{T(lang, 'All in Booksy', 'Todo en Booksy')}</div>
          <div style={{ fontSize: '0.74rem', color: 'var(--muted)' }}>{T(lang, 'Your appointments, clients and payments.', 'Tus citas, clientes y cobros.')}</div>
          <div style={{ display: 'inline-flex', alignItems: 'center', gap: '6px', marginTop: '14px', fontFamily: 'var(--font-mono)', fontSize: '0.62rem', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--accent)' }}>{T(lang, 'Open Booksy', 'Abrir Booksy')} <window.Icon name="chevron" size={13} /></div>
        </a>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', marginTop: '12px' }}>
          {quick('camera', T(lang, 'Upload photo', 'Subir foto'), () => goUpload('hoy'))}
          {quick('pencil', T(lang, 'Edit site', 'Editar sitio'), () => setTab('yo'))}
        </div>
        {recent.length > 0 && <>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--muted-2)', margin: '26px 0 12px' }}>{T(lang, 'Recent', 'Recientes')}</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: '8px' }}>
            {recent.map((it) => <img key={it.id} src={it.type === 'ba' ? it.after : it.src} alt="" onClick={() => setTab('galeria')} style={{ display: 'block', width: '100%', aspectRatio: '1/1', objectFit: 'cover', borderRadius: '10px', border: '1px solid var(--bd-d)', cursor: 'pointer' }} />)}
          </div>
        </>}
      </div>
    );
  }

  const tabs = [
    { id: 'hoy', label: T(lang, 'Home', 'Inicio'), icon: 'home' },
    { id: 'galeria', label: T(lang, 'Gallery', 'Galería'), icon: 'work' },
    { id: 'yo', label: T(lang, 'Me', 'Yo'), icon: 'me' },
  ];

  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 100, background: 'var(--ink)' }}>
      <div style={{ height: '100%', maxWidth: '480px', margin: '0 auto', display: 'flex', flexDirection: 'column', background: 'var(--ink)', boxShadow: '0 0 70px rgba(0,0,0,.55)' }}>
        {/* top bar — centered small title, iOS-style */}
        <div style={{ flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 'max(14px,env(safe-area-inset-top)) 18px 12px', borderBottom: '1px solid var(--bd-d)', background: 'var(--scrim-dark)', backdropFilter: 'var(--blur-glass)' }}>
          {wordmark('0.95rem')}
        </div>
        {/* screen */}
        <div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch', minHeight: 0 }} className="ms-noscroll">{screen}</div>
        {/* bottom tab bar — iOS metrics: 24px icons, tight labels, blur chrome */}
        <div style={{ flex: 'none', display: 'flex', justifyContent: 'space-around', padding: '7px 6px max(18px,env(safe-area-inset-bottom))', borderTop: '1px solid var(--bd-d)', background: 'var(--scrim-dark)', backdropFilter: 'var(--blur-glass)' }}>
          {tabs.map((t) => {
            const on = t.id === tab;
            return (
              <button key={t.id} onClick={() => setTab(t.id)} aria-current={on ? 'page' : undefined} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '3px', flex: 1, fontFamily: 'var(--font-mono)', fontSize: '0.52rem', letterSpacing: '0.05em', textTransform: 'uppercase', color: on ? 'var(--accent)' : 'var(--muted-2)', background: 'none', border: 'none', cursor: 'pointer', padding: '3px 8px', transition: 'color .15s ease' }}>
                <window.Icon name={t.icon} size={24} /> {t.label}
              </button>
            );
          })}
        </div>
      </div>

      {/* edit-photo sheet */}
      {editing && (
        <div onClick={() => setEditing(null)} style={{ position: 'fixed', inset: 0, zIndex: 250, background: 'rgba(0,0,0,.72)', backdropFilter: 'blur(5px)', display: 'flex', alignItems: 'flex-end', justifyContent: 'center' }}>
          <div onClick={(e) => e.stopPropagation()} style={{ width: '100%', maxWidth: '480px', background: 'var(--ink-2)', borderTopLeftRadius: '22px', borderTopRightRadius: '22px', borderTop: '1px solid var(--bd-d2)', padding: '10px 20px max(24px,env(safe-area-inset-bottom))' }}>
            <div style={{ width: '36px', height: '5px', borderRadius: '3px', background: 'var(--bd-d2)', margin: '0 auto 14px' }} />
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '14px' }}>
              <span style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '1.1rem', color: 'var(--bone)', textTransform: 'uppercase', letterSpacing: '-0.02em' }}>{T(lang, 'Edit photo', 'Editar foto')}</span>
              <button onClick={() => setEditing(null)} aria-label="Close" style={{ background: 'none', border: 'none', color: 'var(--muted)', cursor: 'pointer', display: 'inline-flex' }}><window.Icon name="x" size={18} /></button>
            </div>
            <img src={editing.type === 'ba' ? editing.after : editing.src} alt="" style={{ width: '70px', height: '88px', objectFit: 'cover', borderRadius: 'var(--radius-md)', border: '1px solid var(--bd-d)', display: 'block', marginBottom: '16px' }} />
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.5rem', letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--muted-2)', marginBottom: '8px' }}>{T(lang, 'Category', 'Categoría')}</div>
            <div style={{ display: 'flex', gap: '7px', flexWrap: 'wrap' }}>
              {CATS.map((c) => <button key={c.id} onClick={() => setEditCat(c.id)} style={pill(editCat === c.id)}>{lang === 'ES' ? c.es : c.en}</button>)}
            </div>
            <input value={editLabel} onChange={(e) => setEditLabel(e.target.value)} placeholder={T(lang, 'Note (optional)', 'Nota (opcional)')} style={{ width: '100%', boxSizing: 'border-box', fontFamily: 'var(--font-body)', fontSize: '1rem', padding: '12px 14px', borderRadius: 'var(--radius-input)', border: '1px solid var(--bd-d)', background: 'var(--ink)', color: 'var(--bone)', marginTop: '16px', outline: 'none', display: 'block' }} />
            {err && <div style={{ color: 'var(--accent)', fontSize: '0.74rem', marginTop: '10px' }}>{err}</div>}
            <div style={{ display: 'flex', gap: '10px', marginTop: '18px' }}>
              <button onClick={() => setEditing(null)} style={{ flex: '0 0 auto', fontFamily: 'var(--font-mono)', fontSize: '0.66rem', letterSpacing: '0.08em', textTransform: 'uppercase', padding: '14px 18px', borderRadius: 'var(--radius-pill)', border: '1px solid var(--bd-d2)', background: 'transparent', color: 'var(--bone)', cursor: 'pointer' }}>{T(lang, 'Cancel', 'Cancelar')}</button>
              <button onClick={saveEdit} disabled={editBusy} style={{ flex: 1, fontFamily: 'var(--font-mono)', fontSize: '0.68rem', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '14px', borderRadius: 'var(--radius-pill)', border: 'none', background: 'var(--accent)', color: 'var(--on-accent)', cursor: 'pointer', opacity: editBusy ? 0.7 : 1 }}>{editBusy ? T(lang, 'Saving…', 'Guardando…') : T(lang, 'Save', 'Guardar')}</button>
            </div>
          </div>
        </div>
      )}

      <ConfirmDialog lang={lang} open={!!confirm} title={confirm && confirm.title} message={confirm && confirm.message} confirmText={confirm && confirm.confirmText} danger onCancel={() => setConfirm(null)} onConfirm={() => { if (confirm && confirm.onConfirm) confirm.onConfirm(); }} />
    </div>
  );
}

function WebFooter({ lang, onPanel }) {
  return (
    <footer style={{ padding: '46px 24px 90px', textAlign: 'center', color: 'var(--muted-2)', fontSize: '0.76rem', background: 'var(--ink)', borderTop: '1px solid var(--bd-d)' }}>
      <div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.6rem', textTransform: 'uppercase', letterSpacing: '-0.03em', color: 'var(--bone)', marginBottom: '6px' }}>
        Michael<span style={{ color: 'var(--accent)' }}>/</span>Style
      </div>
      <div style={{ fontStyle: 'italic', color: 'var(--muted)', marginBottom: '10px' }}>{T(lang, 'A cut above. A perfect line.', 'Un corte superior. Una línea perfecta.')}</div>
      <div>{T(lang, 'Michael Adonis · Dominican Barber & SMP · Houston, TX · ', 'Michael Adonis · Barbería Dominicana & SMP · Houston, TX · ')}<a href="https://www.instagram.com/michaelstyle23/" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--accent)', textDecoration: 'none' }}>@michaelstyle23</a></div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: '0.6rem', letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--accent)', marginTop: '16px' }}>{T(lang, 'God first', 'Dios primero')}</div>
      <div style={{ marginTop: '24px', paddingTop: '18px', borderTop: '1px solid var(--bd-d)', fontFamily: 'var(--font-mono)', fontSize: '0.56rem', letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--muted-2)' }}>
        Designed by <a href="https://www.abdesignstrategy.com/" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--muted)', textDecoration: 'none' }}>AB Design &amp; Strategy</a>
      </div>
    </footer>
  );
}

Object.assign(window, { BeforeAfter, Hero, ServicesSection, SmpBento, ReviewsSocial, Portfolio, CalendarSection, AboutSection, Faith, WebFooter, OwnerPanel });
