/* Shared page furniture: section rules, texture bands, page headers, inquiry band. */

/* TextureBand — real material photography used as a section divider:
   Calacatta Viola marble, fluted walnut, or the dentil cornice. */
function TextureBand({ material = 'marble', height = 16, style = {} }) {
  const files = {
    marble: './assets/texture-calacatta-viola.jpg',
    walnut: './assets/texture-walnut-plain.png',
    plaster: './assets/texture-cornice-dentil.png',
  };
  const file = files[material] || files.plaster;
  return (
    <div aria-hidden style={{
      height: `${height}px`,
      backgroundImage: `url(${file})`,
      backgroundSize: material === 'plaster' ? 'auto 100%' : 'cover',
      backgroundRepeat: material === 'plaster' ? 'repeat-x' : 'no-repeat',
      backgroundPosition: 'center',
      ...style,
    }} />
  );
}

/* SectionFrame — a thin inset frame echoing the double hairline inside the
   seal's oval. Drop inside a position:relative section.
     tone="dark"  translucent ivory  — for oxblood/espresso grounds
     tone="light" parchment          — for mid-dark grounds
     tone="ink"   ink hairline       — for light grounds (cream, washed photos),
                                       where both tones above are invisible */
function SectionFrame({ inset = 12, tone = 'dark', innerWidth = 1 }) {
  const line = tone === 'light' ? 'var(--parchment)'
    : tone === 'ink' ? 'var(--border-strong)'
    : 'var(--cream-22)';
  return (
    <span aria-hidden style={{
      position: 'absolute', inset: `${inset}px`, pointerEvents: 'none',
      border: `${innerWidth}px solid ${line}`,
    }} />
  );
}

/* Rule — the hairline used above and below column text in the reference layout. */
function Rule({ onDark = false, width = '100%', style = {} }) {
  return (
    <div aria-hidden style={{
      width, height: '1px',
      background: onDark ? 'var(--cream-22)' : 'var(--line)',
      ...style,
    }} />
  );
}

function PageHeader({ eyebrow, title, lede, image = './assets/texture-calacatta-viola.jpg', video, videoStart = 0, position = 'center', minHeight = '82vh', imageBelow = false, imageRatio = '21 / 9', imageAlt = '', align = 'bottom' }) {
  const { Eyebrow } = window.DomumDesignSystem_84ba75;

  /* imageBelow: copy sits on the light ground, photograph runs full-bleed beneath it. */
  if (imageBelow) {
    return (
      <section data-page-header>
        <div style={{ padding: 'var(--space-9) var(--gutter)', maxWidth: '980px', margin: '0 auto', textAlign: 'center' }}>
          <Eyebrow>{eyebrow}</Eyebrow>
          <h1 style={{ fontSize: 'clamp(2.4rem, 5.6vw, 4.2rem)', fontWeight: 400, margin: '22px 0 0', lineHeight: 1.08 }}>{title}</h1>
          {lede && (
            <p style={{ fontSize: 'var(--fs-lead)', color: 'var(--text-secondary)', lineHeight: 1.7, maxWidth: '58ch', margin: '24px auto 0' }}>{lede}</p>
          )}
        </div>
        <img src={image} alt={imageAlt} style={{ width: '100%', aspectRatio: imageRatio, objectFit: 'cover', objectPosition: position, display: 'block' }} />
      </section>
    );
  }

  return (
    <section data-page-header style={{
      position: 'relative', height: minHeight, display: 'flex', alignItems: align === 'center' ? 'center' : 'flex-end', justifyContent: 'center',
      padding: 'var(--space-9) var(--gutter) var(--space-8)', overflow: 'hidden', color: 'var(--ivory)',
    }}>
      {video ? (
        <video aria-hidden autoPlay muted loop playsInline preload="auto"
          onLoadedMetadata={(e) => { try { e.currentTarget.currentTime = videoStart; } catch (err) {} }}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: position }}>
          <source src={videoStart ? `${video}#t=${videoStart}` : video} type="video/mp4" />
        </video>
      ) : (
        <div aria-hidden style={{ position: 'absolute', inset: 0, background: `url(${image}) ${position} / cover no-repeat` }} />
      )}
      <div aria-hidden style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to bottom, rgba(43,33,27,.76), rgba(43,33,27,.70) 45%, rgba(43,33,27,.82))' }} />
      <div style={{ position: 'relative', maxWidth: '980px', textAlign: 'center' }}>
        <Eyebrow color="onDark">{eyebrow}</Eyebrow>
        <h1 style={{
          color: 'var(--ivory)', fontSize: 'clamp(2.1rem, 4.6vw, 3.6rem)', fontWeight: 400,
          margin: '22px 0 0', lineHeight: 1.06, textShadow: '0 1px 20px rgba(28,12,14,.55)',
        }}>{title}</h1>
        {lede && (
          <p style={{
            color: 'var(--cream-88)', fontSize: 'var(--fs-lead)', lineHeight: 1.7,
            maxWidth: '56ch', margin: '24px auto 0', textShadow: '0 1px 12px rgba(28,12,14,.7)',
          }}>{lede}</p>
        )}
      </div>
    </section>
  );
}

/* submitNetlifyForm — posts a rendered <form> to Netlify Forms.
   Netlify registers forms from the static stubs in index.html; this sends the
   real values to the same endpoint. Field `name` attributes must match those
   stubs or the submission is rejected. */
function submitNetlifyForm(formName, formEl) {
  const data = new FormData(formEl);
  data.set('form-name', formName);
  const body = new URLSearchParams();
  data.forEach((v, k) => { if (typeof v === 'string') body.append(k, v); });
  return fetch('/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: body.toString(),
  }).then((r) => { if (!r.ok) throw new Error('Submission failed'); return r; });
}

/* InquiryBand — the "tell us about your home" form, in-page above the footer. */
function InquiryBand({ eyebrow = 'Start a Conversation', title = 'Tell us about your home.' }) {
  const { Input, Select, Button, Eyebrow } = window.DomumDesignSystem_84ba75;
  const [sent, setSent] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState('');

  const onSubmit = (e) => {
    e.preventDefault();
    const form = e.currentTarget;
    setSending(true); setError('');
    submitNetlifyForm('inquiry', form)
      .then(() => { setSent(true); form.reset(); })
      .catch(() => setError('Something went wrong. Please email info@springstreetbuild.com.'))
      .finally(() => setSending(false));
  };

  return (
    <div>
    <section data-static style={{ position: 'relative', background: 'var(--oxblood)', color: 'var(--ivory)', padding: 'var(--space-9) var(--gutter)' }}>
      <SectionFrame />
      <div style={{ maxWidth: '1040px', margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 1.2fr', gap: 'var(--space-8)', alignItems: 'start' }}>
        <div>
          <Eyebrow color="onDark">{eyebrow}</Eyebrow>
          <h2 style={{ color: 'var(--ivory)', fontSize: 'clamp(1.9rem, 3.2vw, 2.6rem)', margin: '18px 0 18px', lineHeight: 1.2 }}>{title}</h2>
          <p style={{ color: 'var(--cream-88)', margin: 0, lineHeight: 1.75, fontSize: 'var(--fs-small)', maxWidth: '38ch' }}>
            Share a little about the space and what you hope to create. We'll follow up to set up a
            discovery conversation.
          </p>
          <div style={{ marginTop: 'var(--space-6)', display: 'flex', flexDirection: 'column', gap: '10px' }}>
            <a href="mailto:info@springstreetbuild.com" style={{ border: 'none', color: 'var(--white-oak)', fontSize: 'var(--fs-small)' }}>info@springstreetbuild.com</a>
            <a href="tel:5017335253" style={{ border: 'none', color: 'var(--white-oak)', fontSize: 'var(--fs-small)' }}>501.733.5253</a>
          </div>
        </div>

        {sent ? (
          <div style={{ borderTop: '1px solid var(--cream-22)', paddingTop: 'var(--space-6)' }}>
            <p style={{ fontFamily: 'var(--font-display)', fontSize: '1.8rem', color: 'var(--ivory)', margin: '0 0 12px' }}>Thank you. We'll be in touch.</p>
            <p style={{ color: 'var(--cream-88)', fontSize: 'var(--fs-small)', margin: '0 0 24px', lineHeight: 1.7 }}>
              One of us will respond within two business days.
            </p>
            <Button variant="secondary" onClick={() => setSent(false)}
                    style={{ color: 'var(--ivory)', borderColor: 'var(--cream-48)' }}>Send another</Button>
          </div>
        ) : (
          <form name="inquiry" method="POST" data-netlify="true" netlify-honeypot="bot-field"
                onSubmit={onSubmit}
                style={{ display: 'flex', flexDirection: 'column', gap: '22px' }}>
            <input type="hidden" name="form-name" value="inquiry" />
            <p hidden><input name="bot-field" tabIndex={-1} autoComplete="off" /></p>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '22px' }}>
              <Input label="Name" name="name" placeholder="Jane Ellison" required onDark />
              <Input label="Email" name="email" type="email" placeholder="jane@email.com" required onDark />
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '22px' }}>
              <Input label="Phone" name="phone" type="tel" placeholder="501.555.0100" onDark />
              <Select label="Project type" name="project-type" defaultValue="" onDark>
                <option value="" disabled>Select…</option>
                <option>Whole-home renovation</option>
                <option>Kitchen or bath</option>
                <option>Addition</option>
                <option>Custom construction</option>
                <option>Not sure yet</option>
              </Select>
            </div>
            <Input label="Tell us about the space" name="message" multiline rows={3}
                   placeholder="Its age, its character, and what you hope to create…" onDark />
            {error && (
              <p role="alert" style={{ margin: 0, fontSize: 'var(--fs-small)', color: 'var(--ivory)' }}>{error}</p>
            )}
            <div>
              <Button variant="primary" size="lg" type="submit" disabled={sending}
                      style={{ background: 'var(--ivory)', color: 'var(--oxblood)', borderColor: 'var(--ivory)' }}>
                {sending ? 'Sending…' : 'Start a Conversation'}
              </Button>
            </div>
          </form>
        )}
      </div>
    </section>
    </div>
  );
}

/* ScriptMark — the brand's engraved-invitation header device: the eyebrow set in
   script, flanked by hairlines. Borrowed from the seal's script lettering so
   section openings read as stationery rather than as web headings. */
function ScriptMark({ children, onDark = false, align = 'center', size = '2.4rem' }) {
  const line = onDark ? 'var(--cream-22)' : 'var(--line)';
  const ink = onDark ? 'var(--cream-88)' : 'var(--olive, var(--text-secondary))';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: '20px', justifyContent: align === 'left' ? 'flex-start' : 'center' }}>
      {align !== 'left' && <span aria-hidden style={{ flex: 1, maxWidth: '180px', height: '1px', background: line }} />}
      <span style={{ fontFamily: "'Sacramento', cursive", fontSize: size, lineHeight: 1, color: ink, whiteSpace: 'nowrap' }}>{children}</span>
      <span aria-hidden style={{ flex: 1, maxWidth: align === 'left' ? 'none' : '180px', height: '1px', background: line }} />
    </div>
  );
}

Object.assign(window, { PageHeader, InquiryBand, TextureBand, Rule, SectionFrame, ScriptMark, submitNetlifyForm });

/* Reveal — fades and lifts children into place the first time they enter view.
   Respects prefers-reduced-motion by rendering visible immediately. */
function Reveal({ children, delay = 0, y = 22, style = {} }) {
  const ref = React.useRef(null);
  const reduced = typeof window !== 'undefined' && window.matchMedia
    && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const [shown, setShown] = React.useState(!!reduced);

  React.useEffect(() => {
    if (reduced || shown) return;
    const el = ref.current;
    if (!el) { setShown(true); return; }

    /* Show immediately if it is already on screen, then observe for the rest.
       A safety timer guarantees content can never stay hidden. */
    const check = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || 0;
      if (r.top < vh * 0.94 && r.bottom > 0) { setShown(true); return true; }
      return false;
    };
    if (check()) return;

    let io;
    if (typeof IntersectionObserver !== 'undefined') {
      io = new IntersectionObserver((entries) => {
        if (entries.some((e) => e.isIntersecting)) { setShown(true); }
      }, { root: null, rootMargin: '0px 0px -6% 0px', threshold: 0 });
      io.observe(el);
    }
    window.addEventListener('scroll', check, { passive: true });
    window.addEventListener('resize', check);
    const safety = setTimeout(() => setShown(true), 2500);
    return () => {
      if (io) io.disconnect();
      window.removeEventListener('scroll', check);
      window.removeEventListener('resize', check);
      clearTimeout(safety);
    };
  }, [reduced, shown]);

  return (
    <div ref={ref} style={{
      opacity: shown ? 1 : 0,
      transform: shown ? 'none' : `translateY(${y}px)`,
      transition: `opacity 760ms var(--ease-quiet) ${delay}ms, transform 760ms var(--ease-quiet) ${delay}ms`,
      willChange: 'opacity, transform',
      ...style,
    }}>{children}</div>
  );
}
window.Reveal = Reveal;
