// SCN2A Australia — In Memory page.
//
// A quiet memorial space for the children of this community who have died.
// Deliberately SEPARATE from the live Family Map: the map is for present-day
// connection, this page is for remembering. Families submit a name, a photo
// and a short tribute; the SCN2A Australia team reviews every submission with
// the family before anything is published. There are NO public comments here,
// by design, and no UI for them should ever be added.
//
// Published tributes load from memorials.json (ships as [], curated by the
// team after each review). JSON cannot hold comments, so the record shape is
// documented here:
//
//   {
//     "id": "m1",                              // unique, e.g. m1, m2 …
//     "name": "Charlie",                       // the child's name (required)
//     "years": "2014 to 2022",                 // free text, optional
//     "photo": "assets/memorials/charlie.jpg", // optional; omit for the candle placeholder
//     "tribute": "…",                          // the family's words (required)
//     "family": "The Nguyen family",           // attribution, optional
//     "since": "2026"                          // year the tribute was added, optional
//   }
//
// Submissions POST to /api/memorial.js which emails the org inbox (never
// publishes anything automatically). If the POST fails, the form falls back
// to a mailto: link so a grieving family is never met with a dead end.

const MEM_TRIBUTES_URL = 'memorials.json';
const MEM_ENDPOINT = '/api/memorial';

// Same address and pattern as FMAP_SUPPORT_EMAIL in pages-family-map.jsx
// (each page file is scoped by Babel, so the constant is mirrored here).
const MEM_SUPPORT_EMAIL = 'support@scn2aaustralia.org';

const MEM_TRIBUTE_MAX = 1200;
const MEM_PHOTO_MAX_DIM = 1600; // longest edge after client-side downscale
const MEM_PHOTO_MAX_B64 = 2.5 * 1024 * 1024; // ~2.5MB of encoded data, well under the 4.5MB Vercel payload limit

// Downscale + re-encode a chosen photo in the browser: longest edge capped at
// MEM_PHOTO_MAX_DIM, re-encoded as JPEG, quality stepped down until the
// base64 payload fits. Resolves { dataUrl, base64 }; rejects with
// 'not-image' | 'too-large' | 'unreadable'.
function memProcessPhoto(file) {
  return new Promise((resolve, reject) => {
    if (!file || !/^image\//.test(file.type)) { reject(new Error('not-image')); return; }
    const url = URL.createObjectURL(file);
    const img = new Image();
    img.onload = () => {
      URL.revokeObjectURL(url);
      try {
        const scale = Math.min(1, MEM_PHOTO_MAX_DIM / Math.max(img.naturalWidth, img.naturalHeight));
        const w = Math.max(1, Math.round(img.naturalWidth * scale));
        const h = Math.max(1, Math.round(img.naturalHeight * scale));
        const canvas = document.createElement('canvas');
        canvas.width = w; canvas.height = h;
        const ctx = canvas.getContext('2d');
        ctx.fillStyle = '#FFFFFF'; ctx.fillRect(0, 0, w, h); // flatten any transparency before JPEG
        ctx.drawImage(img, 0, 0, w, h);
        let quality = 0.85;
        let dataUrl = canvas.toDataURL('image/jpeg', quality);
        while (dataUrl.length > MEM_PHOTO_MAX_B64 && quality > 0.35) {
          quality -= 0.1;
          dataUrl = canvas.toDataURL('image/jpeg', quality);
        }
        if (dataUrl.length > MEM_PHOTO_MAX_B64) { reject(new Error('too-large')); return; }
        resolve({ dataUrl, base64: (dataUrl.split(',')[1] || '') });
      } catch (e) { reject(new Error('unreadable')); }
    };
    img.onerror = () => { URL.revokeObjectURL(url); reject(new Error('unreadable')); };
    img.src = url;
  });
}

// ---- Soft candle placeholder for tributes without a photo ----
function MemorialPlaceholder({ name }) {
  return (
    <div role="img" aria-label={`A candle held for ${name}`}
      style={{ aspectRatio: '4 / 3', background: '#E8E3DA', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <svg viewBox="0 0 120 120" width="88" height="88" aria-hidden="true">
        {/* soft glow */}
        <circle cx="60" cy="40" r="26" fill="#F7F4F0" opacity="0.9" />
        <circle cx="60" cy="40" r="16" fill="#FDF9EF" />
        {/* flame */}
        <path d="M60 26 C66 34 66 42 60 47 C54 42 54 34 60 26 Z" fill="#C9A15A" opacity="0.85" />
        <path d="M60 33 C63 37 63 42 60 45 C57 42 57 37 60 33 Z" fill="#F7F4F0" opacity="0.9" />
        {/* wick + candle */}
        <line x1="60" y1="47" x2="60" y2="52" stroke="#6B6659" strokeWidth="1.6" strokeLinecap="round" />
        <rect x="48" y="52" width="24" height="40" rx="4" fill="#FFFFFF" stroke="#D5CFBF" strokeWidth="1.5" />
        {/* base leaves */}
        <path d="M40 96 Q52 88 60 96 Q68 88 80 96" fill="none" stroke="#B9C2D6" strokeWidth="2" strokeLinecap="round" />
      </svg>
    </div>
  );
}

// ---- One tribute card on the wall ----
function MemorialCard({ m }) {
  return (
    <article style={{ background: '#fff', border: '1px solid #D5CFBF', borderRadius: 8, overflow: 'hidden', boxShadow: '0 1px 2px rgba(13,27,42,0.06), 0 1px 3px rgba(13,27,42,0.08)', display: 'flex', flexDirection: 'column' }}>
      {m.photo ? (
        <img src={m.photo} alt={`Photo of ${m.name}`} loading="lazy"
          style={{ display: 'block', width: '100%', aspectRatio: '4 / 3', objectFit: 'cover' }} />
      ) : (
        <MemorialPlaceholder name={m.name} />
      )}
      <div style={{ padding: '22px 24px 24px', display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
        <h3 style={{ fontSize: 21, fontWeight: 700, letterSpacing: '-0.01em', margin: 0, color: '#0D1B2A' }}>{m.name}</h3>
        {m.years && <div style={{ fontSize: 13, color: '#6B6659', marginTop: 4 }}>{m.years}</div>}
        <p style={{ fontSize: 14.5, lineHeight: 1.65, color: '#0D1B2A', margin: '14px 0 0', whiteSpace: 'pre-line' }}>{m.tribute}</p>
        <div style={{ marginTop: 'auto', paddingTop: 16 }}>
          <div style={{ borderTop: '1px solid #D5CFBF', paddingTop: 12, display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
            {m.family && <span style={{ fontSize: 12.5, fontWeight: 600, color: '#1E3A6E' }}>{m.family}</span>}
            {m.since && <span style={{ fontSize: 11.5, color: '#6B6659' }}>Remembered here since {m.since}</span>}
          </div>
        </div>
      </div>
    </article>
  );
}

// ---- "Add a tribute" form ----
function MemorialTributeForm() {
  const empty = { lovedOneName: '', years: '', tribute: '', submitterName: '', submitterEmail: '', relationship: '', consent: false };
  const [form, setForm] = React.useState(empty);
  const [photo, setPhoto] = React.useState(null); // { dataUrl, base64, name }
  const [photoBusy, setPhotoBusy] = React.useState(false);
  const [error, setError] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const [sent, setSent] = React.useState(false);
  const [failed, setFailed] = React.useState(false);
  const fileRef = React.useRef(null);
  const honeypotRef = React.useRef(null);
  const set = (patch) => { setForm(f => ({ ...f, ...patch })); setError(''); };

  const onPhotoChange = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    setError('');
    setPhotoBusy(true);
    try {
      const out = await memProcessPhoto(file);
      const base = (file.name || 'photo').replace(/\.[^.]+$/, '');
      setPhoto({ dataUrl: out.dataUrl, base64: out.base64, name: `${base}.jpg` });
    } catch (err) {
      setPhoto(null);
      if (err && err.message === 'not-image') setError('That file does not look like a photo. Please choose an image file, or leave the photo out for now.');
      else if (err && err.message === 'too-large') setError('We could not make that photo small enough to send. Please try a different photo, or leave it out and we will sort it with you by email.');
      else setError('We could not read that photo. Please try a different one, or leave it out for now.');
    } finally {
      setPhotoBusy(false);
    }
  };

  const clearPhoto = () => {
    setPhoto(null);
    if (fileRef.current) fileRef.current.value = '';
  };

  const mailtoHref = () => {
    const subject = `Memorial tribute for ${form.lovedOneName.trim() || 'our loved one'}`;
    const body =
      `Loved one's name: ${form.lovedOneName.trim()}\n` +
      `Their years: ${form.years.trim() || '(not given)'}\n\n` +
      `Tribute:\n${form.tribute.trim()}\n\n` +
      `My name: ${form.submitterName.trim()}\n` +
      `Relationship: ${form.relationship.trim() || '(not given)'}\n\n` +
      `I am a member of this child's family and I give permission for SCN2A Australia ` +
      `to publish this tribute after review.\n\n` +
      `(If you chose a photo on the page, please attach it to this email.)`;
    return `mailto:${MEM_SUPPORT_EMAIL}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
  };

  const submit = async (e) => {
    e.preventDefault();
    if (!form.lovedOneName.trim()) { setError('Please tell us your loved one’s name.'); return; }
    const tribute = form.tribute.trim();
    if (tribute.length < 4) { setError('Please write a few words for the tribute. It can be as short as you like.'); return; }
    if (tribute.length > MEM_TRIBUTE_MAX) { setError(`The tribute can be up to ${MEM_TRIBUTE_MAX} characters. Yours is a little over, feel free to trim it or email us the full version.`); return; }
    if (!form.submitterName.trim()) { setError('Please tell us your name.'); return; }
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(form.submitterEmail.trim())) { setError('That email address does not look right, please check it. We only use it to be in touch with you.'); return; }
    if (!form.consent) { setError('Please tick the permission box so we know your family is happy for us to publish this after review.'); return; }

    const payload = {
      lovedOneName: form.lovedOneName.trim(),
      years: form.years.trim(),
      photoBase64: photo ? photo.base64 : '',
      photoName: photo ? photo.name : '',
      tribute,
      submitterName: form.submitterName.trim(),
      submitterEmail: form.submitterEmail.trim(),
      relationship: form.relationship.trim(),
      consent: true,
      // Honeypot: empty for people. Bots that fill every field give
      // themselves away, and the server quietly discards the submission.
      website: (honeypotRef.current && honeypotRef.current.value) || '',
    };
    setSending(true);
    setFailed(false);
    try {
      const res = await fetch(MEM_ENDPOINT, {
        method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload),
      });
      if (!res.ok) throw new Error('send-failed');
      setSent(true);
    } catch (err) {
      // Never leave a grieving family at a dead end: offer email instead.
      setFailed(true);
    } finally {
      setSending(false);
    }
  };

  const fieldStyle = { width: '100%', boxSizing: 'border-box', padding: '10px 12px', border: '1px solid #D5CFBF', borderRadius: 5, fontFamily: 'inherit', fontSize: 14, color: '#0D1B2A', background: '#fff' };
  const labelStyle = { display: 'block', fontSize: 11.5, fontWeight: 600, color: '#0D1B2A', marginBottom: 6 };
  const helpStyle = { fontSize: 12, color: '#6B6659', lineHeight: 1.55, margin: '6px 0 0' };

  if (sent) {
    return (
      <div className="fmap-rise" style={{ background: '#fff', border: '1px solid #D5CFBF', borderRadius: 8, padding: '44px 36px', textAlign: 'center', boxShadow: '0 1px 2px rgba(13,27,42,0.06), 0 1px 3px rgba(13,27,42,0.08)' }}>
        <div style={{ width: 52, height: 52, borderRadius: 999, background: '#E5EDF8', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 18px', color: '#4A7EC7', fontSize: 24, fontWeight: 700 }} aria-hidden="true">✓</div>
        <h3 style={{ fontSize: 21, fontWeight: 700, margin: '0 0 12px', color: '#0D1B2A' }}>Thank you for trusting us with their memory.</h3>
        <p style={{ fontSize: 15, lineHeight: 1.65, color: '#0D1B2A', margin: '0 auto', maxWidth: '46ch' }}>Our team will be in touch before anything appears. Nothing is published until you have seen it and told us it is right.</p>
      </div>
    );
  }

  return (
    <form onSubmit={submit} noValidate
      style={{ background: '#fff', border: '1px solid #D5CFBF', borderRadius: 8, padding: '32px 32px 28px', boxShadow: '0 1px 2px rgba(13,27,42,0.06), 0 1px 3px rgba(13,27,42,0.08)' }} className="pad-mobile">

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 18 }} className="stack-mobile">
        <div>
          <label htmlFor="mem-loved-name" style={labelStyle}>Your loved one's name <span aria-hidden="true" style={{ color: '#8E3B5E' }}>*</span></label>
          <input id="mem-loved-name" type="text" required value={form.lovedOneName} maxLength={120}
            onChange={(e) => set({ lovedOneName: e.target.value })} placeholder="e.g. Charlie" style={fieldStyle} />
        </div>
        <div>
          <label htmlFor="mem-years" style={labelStyle}>Their years <span style={{ fontWeight: 500, color: '#6B6659' }}>(optional)</span></label>
          <input id="mem-years" type="text" value={form.years} maxLength={80}
            onChange={(e) => set({ years: e.target.value })} placeholder="e.g. 2014 to 2022" style={fieldStyle} />
          <p style={helpStyle}>Written however feels right to you, or left blank.</p>
        </div>
      </div>

      <div style={{ marginBottom: 18 }}>
        <label htmlFor="mem-photo" style={labelStyle}>A photo <span style={{ fontWeight: 500, color: '#6B6659' }}>(optional)</span></label>
        <input id="mem-photo" ref={fileRef} type="file" accept="image/*" onChange={onPhotoChange}
          aria-describedby="mem-photo-help" style={{ ...fieldStyle, padding: '9px 12px' }} />
        <p id="mem-photo-help" style={helpStyle}>{photoBusy ? 'Preparing your photo…' : 'Large photos are gently resized in your browser before they reach us. We will confirm the photo with you before it appears.'}</p>
        {photo && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginTop: 10, padding: 10, background: '#F7F4F0', border: '1px solid #D5CFBF', borderRadius: 5 }}>
            <img src={photo.dataUrl} alt={form.lovedOneName.trim() ? `Photo of ${form.lovedOneName.trim()}, ready to send` : 'Your chosen photo, ready to send'}
              style={{ width: 64, height: 64, objectFit: 'cover', borderRadius: 4, flexShrink: 0 }} />
            <span style={{ fontSize: 12.5, color: '#0D1B2A', lineHeight: 1.5 }}>Your photo is ready to send with the tribute.</span>
            <button type="button" onClick={clearPhoto}
              style={{ marginLeft: 'auto', background: 'none', border: 'none', color: '#6B6659', fontSize: 12.5, fontFamily: 'inherit', textDecoration: 'underline', textUnderlineOffset: 3, cursor: 'pointer', padding: 4 }}>
              Remove photo
            </button>
          </div>
        )}
      </div>

      <div style={{ marginBottom: 18 }}>
        <label htmlFor="mem-tribute" style={labelStyle}>The tribute <span aria-hidden="true" style={{ color: '#8E3B5E' }}>*</span></label>
        <textarea id="mem-tribute" required value={form.tribute} maxLength={MEM_TRIBUTE_MAX} rows="6"
          onChange={(e) => set({ tribute: e.target.value })} aria-describedby="mem-tribute-help"
          placeholder="Who they were, what they loved, what you would like the community to know…"
          style={{ ...fieldStyle, lineHeight: 1.6, resize: 'vertical' }} />
        <p id="mem-tribute-help" style={{ ...helpStyle, display: 'flex', justifyContent: 'space-between', gap: 12 }}>
          <span>A few words or a few paragraphs, whatever you would like to say.</span>
          <span>{form.tribute.length} / {MEM_TRIBUTE_MAX}</span>
        </p>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 18 }} className="stack-mobile">
        <div>
          <label htmlFor="mem-your-name" style={labelStyle}>Your name <span aria-hidden="true" style={{ color: '#8E3B5E' }}>*</span></label>
          <input id="mem-your-name" type="text" required value={form.submitterName} maxLength={120}
            onChange={(e) => set({ submitterName: e.target.value })} placeholder="e.g. Sam Nguyen" style={fieldStyle} />
        </div>
        <div>
          <label htmlFor="mem-relationship" style={labelStyle}>Your relationship to them <span style={{ fontWeight: 500, color: '#6B6659' }}>(optional)</span></label>
          <input id="mem-relationship" type="text" value={form.relationship} maxLength={120}
            onChange={(e) => set({ relationship: e.target.value })} placeholder="e.g. Mum, Dad, grandparent" style={fieldStyle} />
        </div>
      </div>

      <div style={{ marginBottom: 20 }}>
        <label htmlFor="mem-email" style={labelStyle}>Your email <span aria-hidden="true" style={{ color: '#8E3B5E' }}>*</span></label>
        <input id="mem-email" type="email" required value={form.submitterEmail} maxLength={200}
          onChange={(e) => set({ submitterEmail: e.target.value })} aria-describedby="mem-email-help"
          placeholder="you@example.com" style={fieldStyle} />
        <p id="mem-email-help" style={helpStyle}>Private. We only use it so our team can check the details with you. It is never published.</p>
      </div>

      {/* Honeypot: hidden from people, tempting to bots. Kept out of the tab order. */}
      <div aria-hidden="true" style={{ position: 'absolute', left: '-9999px', width: 1, height: 1, overflow: 'hidden' }}>
        <label htmlFor="mem-website">Website</label>
        <input id="mem-website" ref={honeypotRef} type="text" tabIndex={-1} autoComplete="off" defaultValue="" />
      </div>

      <label style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginBottom: 20, cursor: 'pointer' }}>
        <input type="checkbox" required checked={form.consent} onChange={(e) => set({ consent: e.target.checked })}
          style={{ marginTop: 3, width: 16, height: 16, flexShrink: 0, accentColor: '#1E3A6E' }} />
        <span style={{ fontSize: 13.5, lineHeight: 1.6, color: '#0D1B2A' }}>I am a member of this child's family and I give permission for SCN2A Australia to publish this tribute after review. <span aria-hidden="true" style={{ color: '#8E3B5E' }}>*</span></span>
      </label>

      {error && <div role="alert" style={{ fontSize: 13, color: '#8E3B5E', lineHeight: 1.55, margin: '0 0 16px' }}>{error}</div>}

      {failed && (
        <div role="alert" style={{ background: '#F7F4F0', border: '1px solid #D5CFBF', borderRadius: 5, padding: '16px 18px', margin: '0 0 16px' }}>
          <p style={{ fontSize: 13.5, lineHeight: 1.6, color: '#0D1B2A', margin: '0 0 12px' }}>We could not reach our server just now. Nothing you wrote has been lost, it is still on this page. If you would like, you can send the tribute to us by email instead, or simply try again in a little while.</p>
          <Button variant="outline" size="sm" as="a" href={mailtoHref()} icon="mail">Email the tribute to us instead</Button>
          {photo && <p style={{ fontSize: 12, color: '#6B6659', lineHeight: 1.5, margin: '10px 0 0' }}>If you email us, please attach your photo to the email, it cannot travel with the mail link.</p>}
        </div>
      )}

      <Button variant="navy" full type="submit">{sending ? 'Sending…' : 'Send the tribute for review'}</Button>

      <div style={{ borderTop: '1px solid #D5CFBF', marginTop: 24, paddingTop: 18 }}>
        <p style={{ fontSize: 13, lineHeight: 1.65, color: '#0D1B2A', margin: 0 }}>Every tribute is read by a real person on our team, and nothing is ever published automatically. We will be in touch with you first, and your words appear only once you have told us they are right. You can ask for changes, or for the tribute to come down, at any time. We treat those requests as same-day.</p>
      </div>
    </form>
  );
}

// ---- Page ----
function MemorialPage({ navigate }) {
  const [memorials, setMemorials] = React.useState([]);

  // Load the published tributes. Ships empty; the team adds each reviewed
  // record to memorials.json. Failure (or a missing file) leaves the wall
  // in its gentle empty state.
  React.useEffect(() => {
    let alive = true;
    fetch(MEM_TRIBUTES_URL, { cache: 'no-cache' })
      .then(r => (r.ok ? r.json() : []))
      .then(d => { if (alive && Array.isArray(d)) setMemorials(d); })
      .catch(() => { /* keep empty on error */ });
    return () => { alive = false; };
  }, []);

  const scrollToForm = (e) => {
    if (e && e.preventDefault) e.preventDefault();
    const el = document.getElementById('add-tribute');
    if (el) el.scrollIntoView({ behavior: 'smooth' });
  };

  const hasMemorials = memorials.length > 0;

  return (
    <div data-screen-label="In Memory">

      {/* ============ HERO (quiet, warm canvas) ============ */}
      <section style={{ background: '#F7F4F0', borderBottom: '1px solid #D5CFBF' }}>
        <div style={{ height: 4, background: '#1E3A6E' }} aria-hidden="true" />
        <div className="container" style={{ padding: '80px 32px 64px' }}>
          <div style={{ maxWidth: 640 }}>
            <div className="eyebrow" style={{ color: '#6B6659', marginBottom: 18 }}>In memory</div>
            <h1 className="h2-mobile" style={{ fontSize: 'clamp(32px, 4vw, 42px)', fontWeight: 800, letterSpacing: '-0.02em', lineHeight: 1.15, margin: '0 0 22px', color: '#0D1B2A', textWrap: 'balance' }}>The children of our community are never forgotten.</h1>
            <p style={{ fontSize: 17, lineHeight: 1.7, color: '#0D1B2A', margin: '0 0 14px', maxWidth: '56ch' }}>SCN2A and the developmental and epileptic encephalopathies take some of the children this community loves. This page belongs to their families. It is a quiet place to say their names, to remember who they were, and to keep them part of us.</p>
            <p style={{ fontSize: 14.5, lineHeight: 1.65, color: '#6B6659', margin: 0, maxWidth: '56ch' }}>This space is separate from our Family Map. Everything here has been placed with a family's permission, and there are no public comments.</p>
          </div>
        </div>
      </section>

      <Breadcrumbs items={[{ label: 'Support', to: 'support' }, { label: 'In memory' }]} navigate={navigate} />

      {/* ============ TRIBUTE WALL ============ */}
      <section style={{ background: '#F7F4F0', padding: '56px 0 72px' }}>
        <div className="container">
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 24, marginBottom: 28, flexWrap: 'wrap' }}>
            <div>
              <div className="eyebrow" style={{ color: '#6B6659', marginBottom: 10 }}>Tributes</div>
              <h2 className="h2-mobile" style={{ fontSize: 28, fontWeight: 700, letterSpacing: '-0.01em', margin: 0, color: '#0D1B2A' }}>Their names, remembered</h2>
            </div>
            {hasMemorials && (
              <span style={{ fontSize: 13, color: '#6B6659' }}>{memorials.length === 1 ? 'One child remembered here' : `${memorials.length} children remembered here`}</span>
            )}
          </div>

          {!hasMemorials ? (
            <div style={{ background: '#fff', border: '1px solid #D5CFBF', borderRadius: 8, padding: '48px 36px', textAlign: 'center', boxShadow: '0 1px 2px rgba(13,27,42,0.06), 0 1px 3px rgba(13,27,42,0.08)' }}>
              <div style={{ width: 120, margin: '0 auto 6px' }}>
                <MemorialPlaceholderInline />
              </div>
              <p style={{ fontSize: 15.5, lineHeight: 1.7, color: '#0D1B2A', margin: '0 auto 10px', maxWidth: '50ch' }}>This space is here whenever a family wants it. Some families come to it soon, some after many years, and some not at all. There is no pressure and no time limit, whatever feels right for your family is right.</p>
              <p style={{ fontSize: 13.5, lineHeight: 1.6, color: '#6B6659', margin: '0 auto', maxWidth: '48ch' }}>When a family shares a tribute and it has been reviewed together, it will appear here.</p>
            </div>
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 20 }}>
              {memorials.map(m => <MemorialCard key={m.id} m={m} />)}
            </div>
          )}
        </div>
      </section>

      {/* ============ ADD A TRIBUTE (sandstone band) ============ */}
      <section id="add-tribute" style={{ background: '#E8E3DA', padding: '72px 0' }}>
        <div className="container">
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.35fr', gap: 48, alignItems: 'start' }} className="stack-mobile">
            <div>
              <div className="eyebrow" style={{ color: '#6B6659', marginBottom: 14 }}>Add a tribute</div>
              <h2 className="h2-mobile" style={{ fontSize: 28, fontWeight: 700, letterSpacing: '-0.01em', lineHeight: 1.2, margin: '0 0 18px', color: '#0D1B2A', textWrap: 'balance' }}>If you would like your child remembered here, we would be honoured.</h2>
              <p style={{ fontSize: 15, lineHeight: 1.7, color: '#0D1B2A', margin: '0 0 14px', maxWidth: '48ch' }}>Tell us about them in your own words. Take all the time you need, you can come back to this whenever you are ready.</p>
              <p style={{ fontSize: 15, lineHeight: 1.7, color: '#0D1B2A', margin: '0 0 24px', maxWidth: '48ch' }}>Nothing you send is published straight away. A member of our team reads every tribute, checks the details with you, and only then does it appear.</p>
              <div style={{ background: '#fff', border: '1px solid #D5CFBF', borderRadius: 5, padding: '18px 20px' }}>
                <h3 style={{ fontSize: 14.5, fontWeight: 700, margin: '0 0 6px', color: '#0D1B2A' }}>Rather talk to a person?</h3>
                <p style={{ fontSize: 13.5, lineHeight: 1.6, color: '#0D1B2A', margin: '0 0 12px' }}>You do not have to fill in a form. Our family support coordinator can take the tribute over email or a call, gently and at your pace.</p>
                <a href={`mailto:${MEM_SUPPORT_EMAIL}`} style={{ fontSize: 13.5, fontWeight: 600, color: '#1E3A6E', textDecoration: 'underline', textUnderlineOffset: 3 }}>Email our family support coordinator</a>
              </div>
            </div>
            <MemorialTributeForm />
          </div>
        </div>
      </section>
    </div>
  );
}

// Small standalone candle used in the empty state (no aspect-ratio wrapper).
function MemorialPlaceholderInline() {
  return (
    <svg viewBox="0 0 120 120" width="100%" aria-hidden="true">
      <path d="M60 26 C66 34 66 42 60 47 C54 42 54 34 60 26 Z" fill="#C9A15A" opacity="0.85" />
      <path d="M60 33 C63 37 63 42 60 45 C57 42 57 37 60 33 Z" fill="#F7F4F0" opacity="0.95" />
      <line x1="60" y1="47" x2="60" y2="52" stroke="#6B6659" strokeWidth="1.6" strokeLinecap="round" />
      <rect x="48" y="52" width="24" height="40" rx="4" fill="#FFFFFF" stroke="#D5CFBF" strokeWidth="1.5" />
      <path d="M40 96 Q52 88 60 96 Q68 88 80 96" fill="none" stroke="#B9C2D6" strokeWidth="2" strokeLinecap="round" />
    </svg>
  );
}

Object.assign(window, { MemorialPage });
