// Shared brand kit for Estimado landing concepts.
// Pulls directly from the brand document v1.0 — Newsreader / Geist / Geist Mono,
// Ink #15140F on Paper #FAF8F3, monochrome by intent.

const C = {
  ink:    '#15140F',
  ink2:   '#2A2822',
  paper:  '#FAF8F3',
  paper2: '#F4F0E6',
  rule:   '#E5E0D5',
  muted:  '#6B6960',
};

const F = {
  display: '"Newsreader", "Newsreader Placeholder", Georgia, serif',
  ui:      '"Geist", "Geist Placeholder", system-ui, -apple-system, sans-serif',
  mono:    '"Geist Mono", "Geist Mono Placeholder", ui-monospace, "SF Mono", Menlo, monospace',
};

// ─────────────────────────────────────────────────────────────
// Logo: soft black tile holding a serif E, 24% corner radius,
// ~29% inset top/bottom. Newsreader weight ~450.
// ─────────────────────────────────────────────────────────────
function EMark({ size = 28, invert = false }) {
  const bg = invert ? C.paper : C.ink;
  const fg = invert ? C.ink : C.paper;
  return (
    <div style={{
      width: size, height: size,
      borderRadius: size * 0.24,
      background: bg, color: fg,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: F.display, fontWeight: 500,
      fontSize: size * 0.72, lineHeight: 1,
      flexShrink: 0,
      paddingTop: size * 0.06,
    }}>E</div>
  );
}

function Lockup({ size = 28, invert = false, gap }) {
  const _gap = gap ?? size * 0.32;
  const wordSize = size * 0.86;
  const wordColor = invert ? C.paper : C.ink;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: _gap, lineHeight: 1 }}>
      <EMark size={size} invert={invert} />
      <span style={{
        fontFamily: F.display, fontWeight: 420,
        fontSize: wordSize, letterSpacing: '-0.035em',
        color: wordColor, lineHeight: 1,
      }}>Estimado</span>
    </span>
  );
}

// ─────────────────────────────────────────────────────────────
// Email capture form with real submit/success state.
// ─────────────────────────────────────────────────────────────
function EmailForm({ variant = 'light', size = 'lg', placeholder = 'you@company.com', cta = 'Join the waitlist' }) {
  const [email, setEmail] = React.useState('');
  const [status, setStatus] = React.useState('idle'); // idle | loading | done
  const inputRef = React.useRef(null);

  const dark = variant === 'dark';
  const inputBg = dark ? 'rgba(255,255,255,0.06)' : '#fff';
  const inputBorder = dark ? 'rgba(255,255,255,0.16)' : C.rule;
  const inputColor = dark ? C.paper : C.ink;
  const btnBg = dark ? C.paper : C.ink;
  const btnColor = dark ? C.ink : C.paper;

  const big = size === 'lg';
  const padY = big ? 18 : 13;
  const padX = big ? 22 : 16;
  const fontSize = big ? 16 : 14;

  const submit = (e) => {
    e?.preventDefault?.();
    if (!email || !/.+@.+\..+/.test(email)) {
      inputRef.current?.focus();
      return;
    }
    setStatus('loading');
    // Hand off to the modal. The webhook fires from the modal once we have
    // the reachable lead data, which avoids duplicate Meta/CAPI lead counts.
    setTimeout(() => {
      window.dispatchEvent(new CustomEvent('open-waitlist-modal', { detail: { email: email.trim() } }));
      setStatus('idle');
    }, 200);
  };

  if (false && status === 'done') {
    return (
      <div style={{
        display: 'flex', alignItems: 'center', gap: 14,
        padding: `${padY}px ${padX}px`,
        background: dark ? 'rgba(255,255,255,0.06)' : C.paper2,
        border: `1px solid ${dark ? 'rgba(255,255,255,0.16)' : C.rule}`,
        borderRadius: 12,
        fontFamily: F.ui, fontSize,
        color: dark ? C.paper : C.ink,
      }}>
        <CheckBadge color={dark ? C.paper : C.ink} />
        <div>
          <div style={{ fontWeight: 500 }}>You're on the list.</div>
          <div style={{ fontFamily: F.mono, fontSize: 12, color: dark ? 'rgba(250,248,243,0.6)' : C.muted, marginTop: 3, letterSpacing: '0.01em' }}>
            Confirmation sent to {email.toLowerCase()}
          </div>
        </div>
      </div>
    );
  }

  return (
    <form onSubmit={submit} style={{ display: 'flex', gap: 8, alignItems: 'stretch', width: '100%', maxWidth: 520 }}>
      <input
        ref={inputRef}
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder={placeholder}
        style={{
          flex: 1, minWidth: 0,
          padding: `${padY}px ${padX}px`,
          background: inputBg, color: inputColor,
          border: `1px solid ${inputBorder}`, borderRadius: 12,
          fontFamily: F.ui, fontSize, outline: 'none',
        }}
      />
      <button type="submit" style={{
        padding: `${padY}px ${padX + 6}px`,
        background: btnBg, color: btnColor,
        border: 'none', borderRadius: 12,
        fontFamily: F.ui, fontSize, fontWeight: 500,
        cursor: 'pointer', whiteSpace: 'nowrap',
        display: 'inline-flex', alignItems: 'center', gap: 8,
        transition: 'transform 0.12s ease, opacity 0.12s ease',
      }}
        onMouseDown={(e) => e.currentTarget.style.transform = 'translateY(1px)'}
        onMouseUp={(e) => e.currentTarget.style.transform = 'translateY(0)'}
        onMouseLeave={(e) => e.currentTarget.style.transform = 'translateY(0)'}
      >
        {status === 'loading' ? 'Adding…' : cta}
        {status !== 'loading' && <Arrow color={btnColor} />}
      </button>
    </form>
  );
}

function Arrow({ color = '#fff', size = 14 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none">
      <path d="M2.5 7h9M8 3.5L11.5 7 8 10.5" stroke={color} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function CheckBadge({ color = '#15140F' }) {
  return (
    <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
      <circle cx="11" cy="11" r="10.25" stroke={color} strokeWidth="1.2" opacity="0.4"/>
      <path d="M6.5 11.2L9.5 14L15 8" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

// Generic pill button
function PillButton({ children, href = '#', invert = false, small = false, onClick, style = {} }) {
  const dark = !invert;
  return (
    <a href={href} onClick={onClick} style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: small ? '8px 14px' : '11px 18px',
      background: dark ? C.ink : C.paper,
      color: dark ? C.paper : C.ink,
      border: invert ? `1px solid ${C.ink}` : 'none',
      borderRadius: 999,
      fontFamily: F.ui, fontWeight: 500, fontSize: small ? 13 : 14,
      letterSpacing: '-0.005em',
      textDecoration: 'none', cursor: 'pointer',
      transition: 'transform 0.12s ease',
      ...style,
    }}
      onMouseEnter={(e) => e.currentTarget.style.transform = 'translateY(-1px)'}
      onMouseLeave={(e) => e.currentTarget.style.transform = 'translateY(0)'}
    >{children}</a>
  );
}

// Small mono section/eyebrow label
function MonoLabel({ children, color, style = {} }) {
  return (
    <span style={{
      fontFamily: F.mono, fontSize: 11, letterSpacing: '0.12em',
      textTransform: 'uppercase', color: color || C.muted,
      ...style,
    }}>{children}</span>
  );
}

// Hairline rule
function Rule({ color = C.rule, style = {} }) {
  return <div style={{ height: 1, background: color, width: '100%', ...style }} />;
}

// Tag / chip used in product mocks
function Chip({ children, tone = 'neutral' }) {
  const palette = {
    neutral: { bg: C.paper2, fg: C.ink },
    warn:    { bg: 'rgba(214, 154, 56, 0.12)', fg: '#8a5d0e' },
    good:    { bg: 'rgba(56, 134, 90, 0.12)', fg: '#1f5a3a' },
    info:    { bg: 'rgba(56, 96, 184, 0.10)', fg: '#234680' },
  }[tone];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center',
      padding: '4px 10px', borderRadius: 999,
      background: palette.bg, color: palette.fg,
      fontFamily: F.ui, fontWeight: 500, fontSize: 11.5,
      letterSpacing: '-0.005em',
    }}>{children}</span>
  );
}

Object.assign(window, { C, F, EMark, Lockup, EmailForm, Arrow, CheckBadge, PillButton, MonoLabel, Rule, Chip, AvatarStack });

// Social media icon links — monochrome, matches the ink/paper UI.
// Accurate brand glyphs (Simple Icons paths). Icons inherit currentColor.
function SocialLinks({ size = 17, gap = 18, color = C.muted, hoverColor = C.ink }) {
  const links = [
    ['Instagram', 'https://instagram.com/estimado.ai',
      'M12 2.16c3.2 0 3.58.01 4.85.07 1.17.05 1.8.25 2.23.41.56.22.96.48 1.38.9.42.42.68.82.9 1.38.16.43.36 1.06.41 2.23.06 1.27.07 1.65.07 4.85s-.01 3.58-.07 4.85c-.05 1.17-.25 1.8-.41 2.23-.22.56-.48.96-.9 1.38-.42.42-.82.68-1.38.9-.43.16-1.06.36-2.23.41-1.27.06-1.65.07-4.85.07s-3.58-.01-4.85-.07c-1.17-.05-1.8-.25-2.23-.41a3.72 3.72 0 0 1-1.38-.9 3.72 3.72 0 0 1-.9-1.38c-.16-.43-.36-1.06-.41-2.23-.06-1.27-.07-1.65-.07-4.85s.01-3.58.07-4.85c.05-1.17.25-1.8.41-2.23.22-.56.48-.96.9-1.38.42-.42.82-.68 1.38-.9.43-.16 1.06-.36 2.23-.41C8.42 2.17 8.8 2.16 12 2.16Zm0 3.68a6.16 6.16 0 1 0 0 12.32 6.16 6.16 0 0 0 0-12.32ZM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8Zm6.41-10.16a1.44 1.44 0 1 0 0 2.88 1.44 1.44 0 0 0 0-2.88Z'],
    ['Facebook', 'https://facebook.com/estimadoai',
      'M24 12.07C24 5.4 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.69.24 2.69.24v2.97h-1.52c-1.49 0-1.96.93-1.96 1.89v2.25h3.33l-.53 3.49h-2.8V24C19.61 23.1 24 18.1 24 12.07Z'],
    ['X', 'https://x.com/estimadoai',
      'M18.9 1.15h3.68l-8.04 9.19L24 22.85h-7.41l-5.8-7.58-6.64 7.58H.47l8.6-9.83L0 1.15h7.59l5.24 6.93ZM17.61 20.64h2.04L6.49 3.24H4.3Z'],
  ];
  return (
    <div style={{ display: 'flex', gap, alignItems: 'center' }}>
      {links.map(([label, href, d]) => (
        <a
          key={label}
          href={href}
          target="_blank"
          rel="noopener noreferrer"
          aria-label={label}
          title={label}
          style={{
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            color, transition: 'color 0.15s ease',
          }}
          onMouseEnter={(e) => { e.currentTarget.style.color = hoverColor; }}
          onMouseLeave={(e) => { e.currentTarget.style.color = color; }}
        >
          <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d={d} /></svg>
        </a>
      ))}
    </div>
  );
}

Object.assign(window, { SocialLinks });

// ─────────────────────────────────────────────────────────────
// Avatar stack — real contractor portraits (Estimado beta users).
// ─────────────────────────────────────────────────────────────
const AVATAR_SRCS = [
  'assets/contractor-3.png',
  'assets/contractor-1.png',
  'assets/contractor-4.png',
  'assets/contractor-5.png',
  'assets/contractor-2.png',
];

function AvatarStack({ size = 36, count = 5, overlap = 10, borderColor }) {
  const srcs = AVATAR_SRCS.slice(0, count);
  return (
    <div style={{ display: 'flex' }}>
      {srcs.map((src, i) => (
        <img
          key={src}
          src={src}
          alt=""
          loading="lazy"
          style={{
            width: size, height: size, borderRadius: 999,
            objectFit: 'cover',
            marginLeft: i === 0 ? 0 : -overlap,
            border: `2px solid ${borderColor || C.paper}`,
            background: C.paper2,
            zIndex: count - i,
          }}
        />
      ))}
    </div>
  );
}

window.AvatarStack = AvatarStack;

// ─────────────────────────────────────────────────────────────
// GoHighLevel inbound webhook — single endpoint. The main landing page posts
// once after the modal has email, name, and a valid US phone number.
// Always url-encoded (CORS-safelisted, no preflight, GHL parses cleanly).
// ─────────────────────────────────────────────────────────────
const GHL_HOOK = 'https://services.leadconnectorhq.com/hooks/kzxGehAT5juhdSHBWxZt/webhook-trigger/0c680fd3-029b-4394-9c7b-a46bb7a93e58';

function formatUSPhone(value) {
  const d = (value || '').replace(/\D/g, '').slice(0, 10);
  if (d.length === 0) return '';
  if (d.length < 4) return `(${d}`;
  if (d.length < 7) return `(${d.slice(0, 3)}) ${d.slice(3)}`;
  return `(${d.slice(0, 3)}) ${d.slice(3, 6)}-${d.slice(6)}`;
}

function postLead(data) {
  const body = new URLSearchParams();
  const qs = new URLSearchParams(window.location.search);
  const fbclid = qs.get('fbclid') || localStorage.getItem('estimado_fbclid') || '';
  if (fbclid) localStorage.setItem('estimado_fbclid', fbclid);
  const eventId = data.event_id || sessionStorage.getItem('estimado_event_id') || `estimado-${Date.now()}-${Math.random().toString(16).slice(2)}`;
  sessionStorage.setItem('estimado_event_id', eventId);
  if (data.email) body.set('email', data.email);
  if (data.name)  body.set('name',  data.name);
  if (data.phone) body.set('phone', data.phone);
  if (data.stage) body.set('stage', data.stage);
  if (fbclid)     body.set('fbclid', fbclid);
  body.set('event_id', eventId);
  try {
    fetch(GHL_HOOK, { method: 'POST', mode: 'no-cors', body }).catch(() => {});
  } catch (_) { /* never blocks the UI */ }
}

window.postLead = postLead;
window.GHL_HOOK = GHL_HOOK;

// ─────────────────────────────────────────────────────────────
// WaitlistModal — name + phone capture after email submit.
// Open by dispatching: window.dispatchEvent(new CustomEvent('open-waitlist-modal', { detail: { email } }))
// On submit it redirects to the confirmation page.
//
// → GoHighLevel integration: replace the setTimeout in `submit` with
//   a fetch() to your GHL inbound webhook URL, POST'ing { email, name, phone }.
//   GHL webhook example:
//     fetch('https://services.leadconnectorhq.com/hooks/<your-hook-id>', {
//       method: 'POST',
//       headers: { 'Content-Type': 'application/json' },
//       body: JSON.stringify({ email, name, phone }),
//     }).then(() => window.location.href = 'confirmation.html');
// ─────────────────────────────────────────────────────────────
function WaitlistModal({ redirect = 'confirmation.html' }) {
  const [open, setOpen] = React.useState(false);
  const [email, setEmail] = React.useState('');
  const [name, setName] = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [status, setStatus] = React.useState('idle');
  const emailRef = React.useRef(null);
  const nameRef = React.useRef(null);

  React.useEffect(() => {
    const onOpen = (e) => {
      const seedEmail = e?.detail?.email || '';
      setEmail(seedEmail);
      setName(''); setPhone(''); setStatus('idle');
      setOpen(true);
      setTimeout(() => {
        // If we came from the email form, jump straight to the name field.
        // Otherwise start at email.
        (seedEmail ? nameRef.current : emailRef.current)?.focus();
      }, 80);
    };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    window.addEventListener('open-waitlist-modal', onOpen);
    window.addEventListener('keydown', onKey);
    return () => {
      window.removeEventListener('open-waitlist-modal', onOpen);
      window.removeEventListener('keydown', onKey);
    };
  }, []);

  if (!open) return null;

  const emailValid = /.+@.+\..+/.test(email.trim());
  const nameValid  = name.trim().length >= 2;
  const phoneDigits = phone.replace(/[^0-9]/g, '');
  const phoneValid = phoneDigits.length === 10;
  const valid = emailValid && nameValid && phoneValid;

  const submit = (e) => {
    e?.preventDefault?.();
    if (!valid || status === 'loading') return;
    setStatus('loading');

    postLead({
      email: email.trim(),
      name:  name.trim(),
      phone: phoneDigits,
      stage: 'complete',
    });

    // Short delay so the spinner reads, then redirect.
    setTimeout(() => {
      const url = new URL(redirect, window.location.href);
      url.searchParams.set('name', name.trim().split(/\s+/)[0]);
      const eventId = sessionStorage.getItem('estimado_event_id');
      if (eventId) url.searchParams.set('event_id', eventId);
      window.location.href = url.toString();
    }, 700);
  };

  const inp = {
    width: '100%',
    padding: '14px 16px',
    background: '#fff',
    color: C.ink,
    border: `1px solid ${C.rule}`,
    borderRadius: 12,
    fontFamily: F.ui, fontSize: 15, outline: 'none',
    boxSizing: 'border-box',
  };

  return (
    <div onMouseDown={() => setOpen(false)} style={{
      position: 'fixed', inset: 0,
      background: 'rgba(21,20,15,0.55)',
      backdropFilter: 'blur(4px)',
      WebkitBackdropFilter: 'blur(4px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      zIndex: 9999, padding: 20,
      animation: 'wm-fade 0.18s ease both',
    }}>
      <div onMouseDown={(e) => e.stopPropagation()} style={{
        width: '100%', maxWidth: 440,
        background: C.paper, color: C.ink,
        borderRadius: 20, border: `1px solid ${C.rule}`,
        padding: '32px 32px 26px', position: 'relative',
        fontFamily: F.ui, lineHeight: 1.5,
        animation: 'wm-pop 0.22s cubic-bezier(0.2,0.8,0.2,1) both',
        boxShadow: '0 40px 100px -40px rgba(21,20,15,0.5), 0 8px 24px -12px rgba(21,20,15,0.18)',
        boxSizing: 'border-box',
      }}>
        <button onClick={() => setOpen(false)} aria-label="Close" style={{
          position: 'absolute', top: 14, right: 14,
          width: 32, height: 32, borderRadius: 999,
          background: 'transparent', border: 'none', cursor: 'pointer',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          color: C.muted,
        }}>
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
            <path d="M2 2L12 12M12 2L2 12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
          </svg>
        </button>

        <MonoLabel>One last thing</MonoLabel>
        <h2 style={{
          fontFamily: F.display, fontWeight: 400, fontSize: 30,
          letterSpacing: '-0.02em', margin: '12px 0 8px', lineHeight: 1.15,
        }}>
          Secure your spot.
        </h2>
        <p style={{ fontSize: 14.5, color: C.ink2, margin: '0 0 20px' }}>
          So we know who you are when we open the beta. We'll text you the
          morning it's your turn.
        </p>

        <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <input ref={emailRef} type="email" value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="you@yourcompany.com" autoComplete="email" style={inp} />
          <input ref={nameRef} type="text" value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="Full name" autoComplete="name" style={inp} />
          <div style={{ display: 'grid', gridTemplateColumns: '74px 1fr', gap: 8 }}>
            <div aria-label="United States country code" style={{
              ...inp,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              gap: 6,
              paddingLeft: 10,
              paddingRight: 10,
              fontWeight: 500,
            }}>
              <span aria-hidden="true">🇺🇸</span>
              <span>+1</span>
            </div>
            <input type="tel" value={phone}
              onChange={(e) => setPhone(formatUSPhone(e.target.value))}
              placeholder="(555) 123-4567" autoComplete="tel"
              inputMode="tel" maxLength={14} style={inp} />
          </div>
          <button type="submit" disabled={!valid || status === 'loading'} style={{
            marginTop: 6,
            padding: '14px 18px',
            background: C.ink, color: C.paper,
            border: 'none', borderRadius: 12,
            fontFamily: F.ui, fontWeight: 500, fontSize: 15,
            cursor: valid && status !== 'loading' ? 'pointer' : 'not-allowed',
            opacity: valid || status === 'loading' ? 1 : 0.55,
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            transition: 'opacity 0.15s ease',
          }}>
            {status === 'loading' ? 'Securing your spot…' : 'Secure my spot'}
            {status !== 'loading' && <Arrow color={C.paper} />}
          </button>
        </form>

        <div style={{
          marginTop: 18,
          fontFamily: F.mono, fontSize: 10.5, letterSpacing: '0.06em',
          textTransform: 'uppercase', color: C.muted, textAlign: 'center',
        }}>
          We won't spam · we text only when it's your turn
        </div>
      </div>
    </div>
  );
}

window.WaitlistModal = WaitlistModal;

// ─────────────────────────────────────────────────────────────
// Typewriter — cycles through a list of words, typing each one
// out character-by-character, holding, then erasing.
// ─────────────────────────────────────────────────────────────
function Typewriter({
  words,
  typeMs = 85,
  eraseMs = 45,
  holdAfterTypeMs = 1800,
  holdAfterEraseMs = 250,
  caretColor,
  caretWidth = '0.06em',
}) {
  const [idx, setIdx] = React.useState(0);
  const [text, setText] = React.useState('');
  const [phase, setPhase] = React.useState('typing'); // 'typing' | 'erasing'

  React.useEffect(() => {
    const word = words[idx % words.length] || '';
    let timer;
    if (phase === 'typing') {
      if (text.length < word.length) {
        timer = setTimeout(() => setText(word.slice(0, text.length + 1)), typeMs);
      } else {
        timer = setTimeout(() => setPhase('erasing'), holdAfterTypeMs);
      }
    } else {
      if (text.length > 0) {
        timer = setTimeout(() => setText(text.slice(0, -1)), eraseMs);
      } else {
        timer = setTimeout(() => {
          setIdx((i) => (i + 1) % words.length);
          setPhase('typing');
        }, holdAfterEraseMs);
      }
    }
    return () => clearTimeout(timer);
  }, [text, phase, idx, words, typeMs, eraseMs, holdAfterTypeMs, holdAfterEraseMs]);

  return (
    <span style={{ whiteSpace: 'pre' }}>
      {text}
      <span
        aria-hidden="true"
        style={{
          display: 'inline-block',
          width: caretWidth,
          height: '0.85em',
          background: caretColor || 'currentColor',
          marginLeft: '0.04em',
          verticalAlign: '-0.08em',
          animation: 'tw-caret-blink 0.7s steps(1) infinite',
        }}
      />
    </span>
  );
}

if (typeof document !== 'undefined' && !document.getElementById('tw-caret-kf')) {
  const s = document.createElement('style');
  s.id = 'tw-caret-kf';
  s.textContent = '@keyframes tw-caret-blink { 50% { opacity: 0; } }';
  document.head.appendChild(s);
}

window.Typewriter = Typewriter;

// ─────────────────────────────────────────────────────────────
// Photo placeholder — subtly striped SVG with mono label.
// Used for warm imagery slots until real photography is dropped in.
// ─────────────────────────────────────────────────────────────
function PhotoPlaceholder({ label = 'Photograph', tone = 'dusk' }) {
  const palettes = {
    dusk:    ['#2a2822', '#3a342a', '#5a4a38'],
    morning: ['#d6c8a8', '#e0d4b8', '#ece3c8'],
    rust:    ['#3a2a20', '#5a3a28', '#7a4a30'],
  };
  const [c1, c2, c3] = palettes[tone] || palettes.dusk;
  const uid = `pp-${tone}`;
  return (
    <svg viewBox="0 0 1200 600" preserveAspectRatio="xMidYMid slice" style={{
      width: '100%', height: '100%', display: 'block', position: 'absolute', inset: 0,
    }}>
      <defs>
        <linearGradient id={`grad-${uid}`} x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor={c1} />
          <stop offset="55%" stopColor={c2} />
          <stop offset="100%" stopColor={c3} />
        </linearGradient>
        <pattern id={`stripes-${uid}`} patternUnits="userSpaceOnUse" width="14" height="14" patternTransform="rotate(48)">
          <rect width="14" height="14" fill="transparent" />
          <line x1="0" y1="0" x2="0" y2="14" stroke="rgba(255,255,255,0.025)" strokeWidth="6" />
        </pattern>
      </defs>
      <rect width="1200" height="600" fill={`url(#grad-${uid})`} />
      <rect width="1200" height="600" fill={`url(#stripes-${uid})`} />
      <text x="56" y="76" fill="rgba(255,255,255,0.5)" fontFamily="ui-monospace, monospace" fontSize="11" letterSpacing="2">
        PHOTO PLACEHOLDER
      </text>
      <text x="56" y="98" fill="rgba(255,255,255,0.75)" fontFamily="ui-monospace, monospace" fontSize="13">
        {label}
      </text>
    </svg>
  );
}

window.PhotoPlaceholder = PhotoPlaceholder;
