// Direction 3: Dark Room
// Black background, cinematic, images glow. Tasteful 3D: cards tilt slightly
// on mouse-move (parallax card effect), soft emissive glow behind featured
// images, subtle grain overlay for that projection-room feel.

const DR_BG = '#0a0a0a';
const DR_BG2 = '#141414';
const DR_INK = '#f0ebe2';       // warm cream text
const DR_DIM = '#8a8578';
const DR_LINE = 'rgba(240,235,226,0.12)';
const DR_ACCENT = '#d4c59a';    // warm brass

// Append the build-stamped ?v=HASH to image URLs so content changes propagate
// to returning visitors without depending on cache-control heuristics.
const srcV = (src) => (typeof window !== 'undefined' && window.__IMG_VER ? `${src}?v=${window.__IMG_VER}` : src);

// Responsive tier helper — three tiers so layout scales smoothly across
// phone, iPad, and desktop. Breakpoints chosen to match common devices:
//   mobile:   < 720   (phones, small phones in landscape)
//   tablet:  720..1099 (iPad portrait 810/834, iPad landscape 1024/1180)
//   desktop: >= 1100  (laptops and up)
function useTier() {
  const get = () => {
    const w = typeof window !== 'undefined' ? window.innerWidth : 1440;
    if (w < 720) return 'mobile';
    if (w < 1100) return 'tablet';
    return 'desktop';
  };
  const [tier, setTier] = React.useState(get);
  React.useEffect(() => {
    const on = () => setTier(get());
    window.addEventListener('resize', on);
    window.addEventListener('orientationchange', on);
    return () => {
      window.removeEventListener('resize', on);
      window.removeEventListener('orientationchange', on);
    };
  }, []);
  return {
    tier,
    isMob: tier === 'mobile',
    isTab: tier === 'tablet',
    isDesk: tier === 'desktop',
    // isNarrow = phone OR tablet — useful where the change is "not desktop"
    isNarrow: tier !== 'desktop',
  };
}
// Back-compat: some call sites still just need the phone/narrow distinction
function useIsMobile() {
  return useTier().isMob;
}

function DR_Root() {
  // `open` is null or { photo, list, index }. Keeping list + index alongside
  // the selected photo lets the lightbox page through the current view
  // (gallery filter order, hero, etc.) with arrow keys or a swipe.
  const [open, setOpen] = React.useState(null);
  const [scroll, setScroll] = React.useState(0);
  const [filter, setFilter] = React.useState('All');
  const [enquiry, setEnquiry] = React.useState(null); // null | { mode: 'prints'|'contact', photoTitle?: string }
  const rootRef = React.useRef(null);

  const openPhoto = React.useCallback((photo, list, startIndex) => {
    const l = (list && list.length) ? list : [photo];
    const i = Number.isInteger(startIndex) ? startIndex : l.indexOf(photo);
    setOpen({ photo, list: l, index: i >= 0 ? i : 0 });
  }, []);
  const gotoOffset = React.useCallback((offset) => {
    setOpen((prev) => {
      if (!prev) return prev;
      const len = prev.list.length;
      if (len <= 1) return prev;
      const next = (prev.index + offset + len) % len;
      return { ...prev, photo: prev.list[next], index: next };
    });
  }, []);

  React.useEffect(() => {
    const el = rootRef.current; if (!el) return;
    const onScroll = () => setScroll(el.scrollTop);
    el.addEventListener('scroll', onScroll, { passive: true });
    return () => el.removeEventListener('scroll', onScroll);
  }, []);

  return (
    <div
      ref={rootRef}
      style={{
        width: '100%', height: '100%', overflowY: 'auto', overflowX: 'hidden',
        background: DR_BG, color: DR_INK,
        fontFamily: '"Inter", -apple-system, system-ui, sans-serif',
        fontSize: 14, lineHeight: 1.6,
        position: 'relative',
      }}
    >
      {/* Faint film grain overlay */}
      <div style={{
        position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 200,
        opacity: 0.05, mixBlendMode: 'screen',
        backgroundImage: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='3'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.8 0'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>")`,
      }} />
      <DR_Nav scroll={scroll} onPrints={() => setEnquiry({ mode: 'prints' })} onContact={() => setEnquiry({ mode: 'contact' })} />
      <DR_Hero scroll={scroll} onOpen={openPhoto} />
      <DR_Series onFilter={setFilter} />
      <DR_Gallery onOpen={openPhoto} filter={filter} setFilter={setFilter} />
      <DR_About />
      <DR_Footer onPrints={() => setEnquiry({ mode: 'prints' })} onContact={() => setEnquiry({ mode: 'contact' })} />
      {open && (
        <DR_Lightbox
          photo={open.photo}
          canNavigate={open.list.length > 1}
          onClose={() => setOpen(null)}
          onPrev={() => gotoOffset(-1)}
          onNext={() => gotoOffset(1)}
        />
      )}
      {enquiry && <DR_EnquiryModal mode={enquiry.mode} prefill={enquiry.photoTitle} onClose={() => setEnquiry(null)} />}
    </div>
  );
}

function DR_Nav({ scroll, onPrints, onContact }) {
  const solid = scroll > 80;
  const { isMob, isTab, isNarrow } = useTier();
  const [open, setOpen] = React.useState(false);
  const items = [
    { label: 'Works', href: '#works' },
    { label: 'Series', href: '#series' },
    { label: 'About', href: '#about' },
    { label: 'Prints', href: '#', onClick: (e) => { e.preventDefault(); onPrints(); setOpen(false); } },
    { label: 'Contact', href: '#', onClick: (e) => { e.preventDefault(); onContact(); setOpen(false); } },
  ];
  // Tablet uses a compact horizontal menu — shorter gap, smaller type, no "Photography" tag
  const padX = isMob ? 20 : isTab ? 32 : 48;
  const padY = isMob ? 14 : 18;
  return (
    <nav style={{
      position: 'sticky', top: 0, zIndex: 50,
      // Respect iOS dynamic island / notch — env() kicks in on real devices;
      // fallback adds a sensible top inset so the bar clears the island area.
      paddingTop: isMob ? `max(env(safe-area-inset-top, 0px), 44px)` : padY,
      paddingBottom: padY,
      paddingLeft: `max(env(safe-area-inset-left, 0px), ${padX}px)`,
      paddingRight: `max(env(safe-area-inset-right, 0px), ${padX}px)`,
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      background: solid || (isMob && open) ? 'rgba(10,10,10,0.92)' : 'transparent',
      backdropFilter: solid || (isMob && open) ? 'blur(16px) saturate(140%)' : 'none',
      WebkitBackdropFilter: solid || (isMob && open) ? 'blur(16px) saturate(140%)' : 'none',
      borderBottom: solid ? `1px solid ${DR_LINE}` : '1px solid transparent',
      transition: 'all .3s',
    }}>
      <button
        type="button"
        aria-label="Back to top"
        onClick={() => {
          let el = document.querySelector('nav')?.parentElement;
          while (el && getComputedStyle(el).overflowY !== 'auto') el = el.parentElement;
          if (el) el.scrollTo({ top: 0, behavior: 'smooth' });
          else window.scrollTo({ top: 0, behavior: 'smooth' });
        }}
        style={{
          background: 'transparent', border: 'none', padding: 0, margin: 0,
          display: 'flex', alignItems: 'center', gap: isMob ? 10 : 14, minWidth: 0,
          cursor: 'pointer', color: 'inherit', fontFamily: 'inherit',
        }}>
        <img src={srcV("img/signature-white.png")} alt="Karl Rauch"
          style={{ height: isMob ? 32 : isTab ? 36 : 40, width: 'auto', display: 'block',
                   filter: 'drop-shadow(0 0 8px rgba(212,197,154,0.15))' }} />
        {!isNarrow && (
          <span style={{
            fontSize: 9, letterSpacing: '0.24em', textTransform: 'uppercase',
            color: DR_DIM, borderLeft: `1px solid ${DR_LINE}`, paddingLeft: 14,
            whiteSpace: 'nowrap',
          }}>Karl Rauch - Photographer</span>
        )}
      </button>

      {isMob ? (
        <>
          <button onClick={() => setOpen(!open)} aria-label="Menu" style={{
            background: 'transparent', border: `1px solid ${DR_LINE}`, borderRadius: 2,
            padding: '8px 10px', cursor: 'pointer', color: DR_INK,
            display: 'flex', flexDirection: 'column', gap: 4,
          }}>
            <span style={{ width: 18, height: 1, background: DR_INK, transition: 'transform .25s', transform: open ? 'translateY(2.5px) rotate(45deg)' : 'none' }} />
            <span style={{ width: 18, height: 1, background: DR_INK, transition: 'transform .25s', transform: open ? 'translateY(-2.5px) rotate(-45deg)' : 'none' }} />
          </button>
          {open && (
            <div style={{
              position: 'absolute', top: '100%', left: 0, right: 0,
              background: 'rgba(10,10,10,0.98)',
              backdropFilter: 'blur(20px)',
              borderBottom: `1px solid ${DR_LINE}`,
              padding: '8px 20px 24px',
              display: 'flex', flexDirection: 'column',
            }}>
              {items.map(l => (
                <a key={l.label} href={l.href} onClick={(e) => { l.onClick?.(e); setOpen(false); }}
                  style={{
                    color: DR_INK, textDecoration: 'none',
                    fontSize: 16, letterSpacing: '0.02em',
                    fontFamily: '"Fraunces", serif', fontStyle: 'italic', fontWeight: 300,
                    padding: '14px 0', borderBottom: `1px solid ${DR_LINE}`,
                  }}>{l.label}</a>
              ))}
            </div>
          )}
        </>
      ) : (
        <div style={{ display: 'flex', gap: isTab ? 20 : 28, fontSize: isTab ? 10 : 11, letterSpacing: '0.16em', textTransform: 'uppercase', color: DR_DIM }}>
          {items.map(l => (
            <a key={l.label} href={l.href} onClick={l.onClick}
               style={{ color: DR_DIM, textDecoration: 'none', transition: 'color .2s', cursor: 'pointer' }}
               onMouseEnter={e => e.currentTarget.style.color = DR_INK}
               onMouseLeave={e => e.currentTarget.style.color = DR_DIM}>{l.label}</a>
          ))}
        </div>
      )}
    </nav>
  );
}

function DR_Hero({ scroll, onOpen }) {
  const hero = window.PHOTOS.find(p => p.id === 'colorado') || window.PHOTOS[0];
  const parallax = Math.min(scroll * 0.35, 220);
  const { isMob, isTab } = useTier();
  const [tilt, setTilt] = React.useState({ rx: 0, ry: 0 });
  const heroRef = React.useRef(null);

  const onMove = (e) => {
    if (isMob) return;
    const el = heroRef.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width;
    const y = (e.clientY - r.top) / r.height;
    setTilt({ rx: -(y - 0.5) * 2.5, ry: (x - 0.5) * 2.5 });
  };
  const onLeave = () => { setTilt({ rx: 0, ry: 0 }); };

  const padX = isMob ? 20 : isTab ? 32 : 48;
  const padTop = isMob ? 32 : isTab ? 48 : 60;
  const padBottom = isMob ? 60 : isTab ? 90 : 120;

  return (
    <section style={{ padding: `${padTop}px ${padX}px ${padBottom}px`, position: 'relative' }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: isMob ? 24 : 40, gap: 16 }}>
        <div style={{ fontSize: isMob ? 9 : 11, letterSpacing: '0.2em', textTransform: 'uppercase', color: DR_DIM }}>
          Selected work · 2019 – 2026
        </div>
        <div style={{ fontSize: isMob ? 9 : 11, letterSpacing: '0.2em', textTransform: 'uppercase', color: DR_DIM, textAlign: 'right' }}>
          Twenty-nine plates
        </div>
      </div>

      <h1 style={{
        fontFamily: '"Fraunces", "Cormorant Garamond", serif',
        fontWeight: 300, fontSize: 'clamp(44px, 11vw, 120px)', lineHeight: 0.95, letterSpacing: '-0.035em',
        margin: isMob ? '0 0 40px' : '0 0 72px', color: DR_INK,
        fontVariationSettings: '"SOFT" 100, "WONK" 0',
      }}>
        Waves, weather,<br />
        and mostly <em style={{ fontStyle: 'italic', color: DR_ACCENT }}>wild</em> places.
      </h1>

      <div
        ref={heroRef}
        onMouseMove={onMove}
        onMouseLeave={onLeave}
        onClick={() => onOpen(hero)}
        style={{
          position: 'relative', perspective: 1400,
          cursor: 'zoom-in',
        }}>
        {/* Glow backdrop */}
        <div style={{
          position: 'absolute', inset: -40,
          background: `radial-gradient(ellipse at center, rgba(212,197,154,0.18), transparent 70%)`,
          filter: 'blur(40px)', pointerEvents: 'none',
        }} />
        <div style={{
          position: 'relative', width: '100%', height: 'clamp(340px, 60vh, 640px)', overflow: 'hidden',
          transformStyle: 'preserve-3d',
          transform: `rotateX(${tilt.rx}deg) rotateY(${tilt.ry}deg)`,
          transition: 'transform .4s cubic-bezier(.2,.7,.3,1)',
          boxShadow: `0 60px 120px -20px rgba(0,0,0,0.8), 0 0 0 1px ${DR_LINE}`,
        }}>
          <img src={srcV(hero.src)} alt={hero.title}
            style={{ width: '100%', height: '125%', objectFit: 'cover',
                     transform: `translateY(-${parallax}px)`, willChange: 'transform' }} />
          {/* Vignette */}
          <div style={{
            position: 'absolute', inset: 0, pointerEvents: 'none',
            background: 'radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.5) 100%)',
          }} />
          {/* Print-thickness edges: thin inner highlight top, deep inner shadow bottom */}
          <div style={{
            position: 'absolute', inset: 0, pointerEvents: 'none',
            boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.08), inset 0 -1px 0 rgba(0,0,0,0.6)',
          }} />
        </div>
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 18, fontSize: isMob ? 9 : 11, letterSpacing: '0.12em', textTransform: 'uppercase', color: DR_DIM, gap: 16 }}>
        <span>I — {hero.title}</span>
        <span style={{ textAlign: 'right' }}>{hero.location} · {hero.year}</span>
      </div>
    </section>
  );
}

function DR_Marquee() {
  const names = window.SERIES.map(s => s.name).join('   ·   ');
  const txt = `   ${names}   ·   `;
  return (
    <section style={{ padding: '0 0 80px', overflow: 'hidden', borderTop: `1px solid ${DR_LINE}`, borderBottom: `1px solid ${DR_LINE}` }}>
      <div style={{
        whiteSpace: 'nowrap',
        padding: '40px 0',
        fontFamily: '"Fraunces", serif',
        fontStyle: 'italic',
        fontSize: 'clamp(34px, 7vw, 64px)',
        fontWeight: 300,
        color: 'transparent',
        WebkitTextStroke: `1px ${DR_DIM}`,
        letterSpacing: '-0.01em',
        animation: 'dr-marquee 40s linear infinite',
      }}>
        {txt.repeat(4)}
      </div>
      <style>{`@keyframes dr-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }`}</style>
    </section>
  );
}

function DR_Gallery({ onOpen, filter, setFilter }) {
  const series = ['All', ...window.SERIES.map(s => s.name)];
  // Shuffle once per page load (Fisher-Yates). Stable across re-renders via
  // useMemo so filter-chip clicks don't re-shuffle mid-session.
  const shuffled = React.useMemo(() => {
    const arr = [...window.PHOTOS];
    for (let i = arr.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
  }, []);
  const photos = filter === 'All' ? shuffled : shuffled.filter(p => p.series === filter);
  const { isMob, isTab } = useTier();
  const padX = isMob ? 20 : isTab ? 32 : 48;
  const padY = isMob ? 60 : isTab ? 80 : 100;
  // Masonry everywhere: 2 cols on phone, 3 on iPad, 3 on desktop.
  const cols = isMob ? 2 : 3;
  const gap = isMob ? 12 : isTab ? 20 : 32;

  return (
    <section id="works" style={{ padding: `${padY}px ${padX}px` }}>
      <div style={{
        display: 'flex',
        flexDirection: isMob ? 'column' : 'row',
        alignItems: isMob ? 'flex-start' : 'baseline',
        justifyContent: 'space-between',
        marginBottom: isMob ? 32 : isTab ? 40 : 56,
        gap: isMob ? 20 : isTab ? 16 : 0,
        flexWrap: 'wrap',
      }}>
        <h2 style={{
          fontFamily: '"Fraunces", serif', fontWeight: 300,
          fontSize: 'clamp(40px, 8vw, 64px)', margin: 0, letterSpacing: '-0.025em',
        }}>Works</h2>
        <div style={{
          display: 'flex', gap: 4,
          fontSize: isMob ? 10 : 11, letterSpacing: '0.14em', textTransform: 'uppercase',
          overflowX: isMob ? 'auto' : 'visible',
          width: isMob ? '100%' : 'auto',
          paddingBottom: isMob ? 4 : 0,
          WebkitOverflowScrolling: 'touch',
          scrollbarWidth: 'none',
        }}>
          {series.map(s => (
            <button key={s} onClick={() => setFilter(s)}
              style={{
                background: filter === s ? DR_ACCENT : 'transparent',
                color: filter === s ? DR_BG : DR_DIM,
                border: `1px solid ${filter === s ? DR_ACCENT : DR_LINE}`,
                padding: isMob ? '7px 12px' : '8px 14px', borderRadius: 100, cursor: 'pointer',
                fontFamily: 'inherit', fontSize: 'inherit', letterSpacing: 'inherit',
                textTransform: 'inherit', transition: 'all .2s',
                whiteSpace: 'nowrap', flexShrink: 0,
              }}>
              {s}
            </button>
          ))}
        </div>
      </div>

      <div style={{ display: 'flex', gap, alignItems: 'flex-start' }}>
        {(() => {
          // Wrap the open callback so the lightbox gets the currently visible
          // (filtered + shuffled) list for arrow-key / swipe navigation.
          const handleOpen = (photo) => onOpen(photo, photos, photos.indexOf(photo));
          const columns = Array.from({ length: cols }, () => []);
          const heights = new Array(cols).fill(0);
          photos.forEach((p, i) => {
            const h = p.aspect === 'portrait' ? 1.5 : 1;
            let shortest = 0;
            for (let c = 1; c < cols; c++) {
              if (heights[c] < heights[shortest]) shortest = c;
            }
            columns[shortest].push({ photo: p, index: i });
            heights[shortest] += h;
          });
          return columns.map((col, ci) => (
            <div key={ci} style={{ flex: 1, minWidth: 0 }}>
              {col.map(({ photo, index }) => (
                <DR_Card key={photo.id} photo={photo} index={index} onOpen={handleOpen} />
              ))}
            </div>
          ));
        })()}
      </div>
    </section>
  );
}

function DR_Card({ photo, index, onOpen }) {
  const { isMob, isTab } = useTier();
  const bottomGap = isMob ? 16 : isTab ? 24 : 40;
  const [hover, setHover] = React.useState(false);
  const [tilt, setTilt] = React.useState({ rx: 0, ry: 0, mx: 50, my: 50 });
  const [revealed, setRevealed] = React.useState(false);
  const ref = React.useRef(null);

  // Scroll-triggered settle: as the card enters the viewport, rise 16px with
  // a gentle ease. Reads as "the print being placed."
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(en => { if (en.isIntersecting) { setRevealed(true); io.disconnect(); } });
    }, { threshold: 0.15, rootMargin: '0px 0px -40px 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width;
    const y = (e.clientY - r.top) / r.height;
    setTilt({ rx: -(y - 0.5) * 6, ry: (x - 0.5) * 6, mx: x * 100, my: y * 100 });
  };
  const onLeave = () => { setHover(false); setTilt({ rx: 0, ry: 0, mx: 50, my: 50 }); };

  return (
    <figure
      ref={ref}
      onMouseEnter={() => setHover(true)}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      onClick={() => onOpen(photo)}
      style={{
        breakInside: 'avoid', margin: `0 0 ${bottomGap}px`, cursor: 'zoom-in',
        perspective: 1200,
        opacity: revealed ? 1 : 0,
        transform: revealed ? 'translateY(0)' : 'translateY(16px)',
        transition: `opacity .9s cubic-bezier(.2,.7,.3,1) ${Math.min(index * 60, 360)}ms, transform .9s cubic-bezier(.2,.7,.3,1) ${Math.min(index * 60, 360)}ms`,
      }}>
      <div style={{
        position: 'relative',
        transformStyle: 'preserve-3d',
        transform: `rotateX(${tilt.rx}deg) rotateY(${tilt.ry}deg) translateZ(${hover ? 10 : 0}px)`,
        transition: 'transform .35s cubic-bezier(.2,.7,.3,1)',
      }}>
        {/* Glow backdrop */}
        <div style={{
          position: 'absolute', inset: -6,
          background: 'radial-gradient(ellipse at center, rgba(212,197,154,0.22), transparent 70%)',
          filter: 'blur(24px)', opacity: hover ? 1 : 0,
          transition: 'opacity .5s', pointerEvents: 'none',
        }} />
        <div style={{
          position: 'relative', overflow: 'hidden',
          background: DR_BG2,
          boxShadow: hover
            ? `0 40px 70px -20px rgba(0,0,0,0.9), 0 0 0 1px rgba(212,197,154,0.25)`
            : `0 20px 40px -18px rgba(0,0,0,0.7), 0 0 0 1px ${DR_LINE}`,
          transition: 'box-shadow .4s',
        }}>
          <img src={srcV(photo.src)} alt={photo.title}
            style={{ width: '100%', display: 'block',
                     transition: 'transform 1s cubic-bezier(.2,.7,.3,1), filter .4s',
                     transform: hover ? 'scale(1.04)' : 'scale(1)',
                     filter: hover ? 'brightness(1.08)' : 'brightness(0.96)' }} />
          {/* Specular highlight following cursor */}
          <div style={{
            position: 'absolute', inset: 0, pointerEvents: 'none',
            background: `radial-gradient(circle at ${tilt.mx}% ${tilt.my}%, rgba(255,255,255,0.12), transparent 40%)`,
            opacity: hover ? 1 : 0, transition: 'opacity .3s', mixBlendMode: 'overlay',
          }} />
          {/* Print-thickness edge */}
          <div style={{
            position: 'absolute', inset: 0, pointerEvents: 'none',
            boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.07), inset 0 -1px 0 rgba(0,0,0,0.55)',
          }} />
        </div>
      </div>
      <figcaption style={{
        marginTop: isMob ? 8 : 14,
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'baseline',
        gap: 8,
      }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{
            fontSize: isMob ? 12 : 14, color: DR_INK, marginBottom: 2,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{photo.title}</div>
          <div style={{
            fontSize: isMob ? 9 : 11, color: DR_DIM, letterSpacing: '0.04em',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{photo.location}</div>
        </div>
        <div style={{
          fontSize: isMob ? 9 : 11, color: DR_DIM, letterSpacing: '0.1em',
          flexShrink: 0,
        }}>
          {isMob ? String(index + 1).padStart(2, '0') : `${String(index + 1).padStart(2, '0')} / ${photo.year}`}
        </div>
      </figcaption>
    </figure>
  );
}

function DR_Series({ onFilter }) {
  const { isMob, isTab } = useTier();
  const padX = isMob ? 20 : isTab ? 32 : 48;
  const padY = isMob ? 60 : isTab ? 80 : 100;
  const seriesCols = isMob ? 2 : isTab ? 3 : 4;
  const handleClick = (e, name) => {
    e.preventDefault();
    onFilter(name);
    // Find the scrollable root and the Works section, scroll manually.
    requestAnimationFrame(() => {
      const works = document.getElementById('works');
      if (!works) return;
      let root = works.parentElement;
      while (root && getComputedStyle(root).overflowY !== 'auto') root = root.parentElement;
      if (root) {
        const top = works.getBoundingClientRect().top - root.getBoundingClientRect().top + root.scrollTop;
        root.scrollTo({ top, behavior: 'smooth' });
      }
    });
  };
  return (
    <section id="series" style={{ padding: `${padY}px ${padX}px`, borderTop: `1px solid ${DR_LINE}` }}>
      <h2 style={{
        fontFamily: '"Fraunces", serif', fontWeight: 300,
        fontSize: 'clamp(40px, 8vw, 64px)', margin: isMob ? '0 0 32px' : isTab ? '0 0 40px' : '0 0 56px', letterSpacing: '-0.025em',
      }}>Series</h2>
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${seriesCols}, 1fr)`, gap: 2 }}>
        {window.SERIES.map(s => {
          const cover = window.PHOTOS.find(p => s.coverId ? p.id === s.coverId : p.series === s.name);
          return (
            <a href="#works" key={s.id}
               onClick={(e) => handleClick(e, s.name)}
               style={{ textDecoration: 'none', color: 'inherit', display: 'block', position: 'relative', overflow: 'hidden', aspectRatio: '3/4', cursor: 'pointer' }}
               className="dr-series-tile">
              <img src={cover ? srcV(cover.src) : undefined} alt={s.name}
                style={{ width: '100%', height: '100%', objectFit: 'cover', filter: 'brightness(0.6) saturate(0.9)', transition: 'all .6s' }} />
              <div style={{
                position: 'absolute', inset: 0, padding: 24,
                display: 'flex', flexDirection: 'column', justifyContent: 'flex-end',
                background: 'linear-gradient(to top, rgba(10,10,10,0.85), transparent 60%)',
              }}>
                <div style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: DR_DIM, marginBottom: 6 }}>
                  {s.count} works · {s.years}
                </div>
                <div style={{ fontFamily: '"Fraunces", serif', fontStyle: 'italic', fontSize: 26, lineHeight: 1.1, fontWeight: 300 }}>
                  {s.name}
                </div>
              </div>
            </a>
          );
        })}
      </div>
      <style>{`
        .dr-series-tile:hover img { filter: brightness(0.85) saturate(1.05); transform: scale(1.04); }
        .dr-series-tile img { transform: scale(1); }
      `}</style>
    </section>
  );
}

function DR_About() {
  const { isMob, isTab, isNarrow } = useTier();
  const padX = isMob ? 20 : isTab ? 32 : 48;
  const padY = isMob ? 72 : isTab ? 96 : 120;
  return (
    <section id="about" style={{ padding: `${padY}px ${padX}px`, borderTop: `1px solid ${DR_LINE}` }}>
      <div style={{
        display: 'grid',
        gridTemplateColumns: isNarrow ? '1fr' : '1fr 1.4fr',
        gap: isMob ? 32 : isTab ? 48 : 80,
        maxWidth: 1200,
      }}>
        <div>
          <div style={{ fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase', color: DR_DIM, marginBottom: 16 }}>
            About
          </div>
          <div style={{
            aspectRatio: '3/4', background: DR_BG2, position: 'relative', overflow: 'hidden',
            maxWidth: isMob ? 280 : isTab ? 360 : 'none',
            boxShadow: `0 30px 60px -20px rgba(0,0,0,0.7), 0 0 0 1px ${DR_LINE}`,
          }}>
            <img src={srcV((window.PHOTOS.find(p => p.id === 'lone-surfer') || window.PHOTOS[0]).src)} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', filter: 'saturate(0.85)' }} />
          </div>
        </div>
        <div>
          <p style={{
            fontFamily: '"Fraunces", serif', fontWeight: 300,
            fontSize: 'clamp(24px, 4vw, 34px)', lineHeight: 1.35, letterSpacing: '-0.01em',
            margin: '0 0 32px',
          }}>
            Karl is a travel and landscape photographer based on
            <em style={{ color: DR_ACCENT, fontStyle: 'italic' }}> Oahu's North Shore</em>,
            by way of Media, PA.
          </p>
          <p style={{ fontSize: 15, lineHeight: 1.8, color: DR_DIM, margin: '0 0 20px', maxWidth: 560 }}>
            Recent work spans Hawaiʻi, Colorado, French Polynesia,
            Scotland, and the quarter-mile between his front door and
            the water. Prints are hand-made on archival paper on request.
          </p>
          <div style={{ marginTop: 48, display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 32, maxWidth: 480, paddingTop: 32, borderTop: `1px solid ${DR_LINE}` }}>
            {[
              { n: '20+', l: 'countries' },
              { n: '29', l: 'final plates' },
              { n: '4', l: 'series' },
            ].map(s => (
              <div key={s.l}>
                <div style={{ fontFamily: '"Fraunces", serif', fontWeight: 300, fontSize: 'clamp(34px, 6vw, 44px)', lineHeight: 1, color: DR_ACCENT, letterSpacing: '-0.02em' }}>
                  {s.n}
                </div>
                <div style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: DR_DIM, marginTop: 6 }}>
                  {s.l}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

function DR_Footer({ onPrints, onContact }) {
  const { isMob, isTab } = useTier();
  const padX = isMob ? 20 : isTab ? 32 : 48;
  return (
    <footer style={{ padding: isMob ? `56px ${padX}px 40px` : `64px ${padX}px 48px`, borderTop: `1px solid ${DR_LINE}` }}>
      <div style={{
        fontFamily: '"Fraunces", serif', fontWeight: 300,
        fontSize: 'clamp(52px, 12vw, 96px)', letterSpacing: '-0.03em', lineHeight: 1,
        margin: isMob ? '0 0 28px' : '0 0 40px', color: DR_INK,
      }}>
        Get in <em style={{ color: DR_ACCENT, fontStyle: 'italic' }}>touch.</em>
      </div>
      <div style={{
        display: 'flex',
        flexDirection: isMob ? 'column' : 'row',
        justifyContent: 'space-between',
        alignItems: isMob ? 'flex-start' : 'flex-end',
        gap: isMob ? 32 : 0,
        fontSize: 12, color: DR_DIM, letterSpacing: '0.06em',
      }}>
        <div>
          <div style={{ display: 'flex', gap: 12 }}>
            <button onClick={onPrints} style={{
              background: DR_ACCENT, color: DR_BG, border: 'none',
              padding: '14px 24px', fontSize: 11, letterSpacing: '0.18em',
              textTransform: 'uppercase', fontFamily: 'inherit', cursor: 'pointer',
              borderRadius: 2,
            }}>Prints</button>
            <button onClick={onContact} style={{
              background: 'transparent', color: DR_INK,
              border: `1px solid ${DR_LINE}`,
              padding: '14px 24px', fontSize: 11, letterSpacing: '0.18em',
              textTransform: 'uppercase', fontFamily: 'inherit', cursor: 'pointer',
              borderRadius: 2,
            }}>Contact</button>
          </div>
          <div style={{ marginTop: 20 }}>© 2026 Karl Rauch</div>
        </div>
        <img src={srcV("img/signature-white.png")} alt="Karl Rauch"
          style={{ width: isMob ? 160 : 220, height: 'auto', opacity: 0.55,
                   filter: 'drop-shadow(0 0 12px rgba(212,197,154,0.1))' }} />
      </div>
    </footer>
  );
}

function DR_Lightbox({ photo, onClose, onPrev, onNext, canNavigate }) {
  const { isMob, isNarrow } = useTier();
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
      else if (canNavigate && e.key === 'ArrowLeft') onPrev();
      else if (canNavigate && e.key === 'ArrowRight') onNext();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose, onPrev, onNext, canNavigate]);
  const [mounted, setMounted] = React.useState(false);
  React.useEffect(() => { requestAnimationFrame(() => setMounted(true)); }, []);

  const navBtn = (side) => ({
    position: 'fixed', top: '50%', [side]: 20, transform: 'translateY(-50%)',
    width: 48, height: 48, borderRadius: '50%',
    background: 'rgba(10,10,10,0.6)', backdropFilter: 'blur(8px)',
    border: `1px solid ${DR_LINE}`, cursor: 'pointer',
    color: DR_INK, fontSize: 28, lineHeight: 1, fontFamily: 'inherit',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    padding: 0, zIndex: 2, transition: 'background .2s, border-color .2s',
  });

  // Zoom + gesture state. Pinch = zoom (1x–4x), 1-finger drag while zoomed = pan,
  // 1-finger drag at 1x = swipe to prev/next.
  const [zoom, setZoom] = React.useState({ scale: 1, x: 0, y: 0 });
  const [isGesturing, setIsGesturing] = React.useState(false);
  React.useEffect(() => {
    setZoom({ scale: 1, x: 0, y: 0 });
  }, [photo?.src]);
  const gesture = React.useRef(null);
  const touchStart = React.useRef(null);
  const onTouchStart = (e) => {
    if (e.touches.length === 2) {
      const [a, b] = e.touches;
      gesture.current = {
        type: 'pinch',
        startDist: Math.hypot(b.clientX - a.clientX, b.clientY - a.clientY),
        startScale: zoom.scale,
      };
      touchStart.current = null;
      setIsGesturing(true);
    } else if (e.touches.length === 1) {
      const t = e.touches[0];
      if (zoom.scale > 1) {
        gesture.current = {
          type: 'pan',
          startX: t.clientX, startY: t.clientY,
          origX: zoom.x, origY: zoom.y,
        };
        setIsGesturing(true);
      } else {
        touchStart.current = { x: t.clientX, y: t.clientY, time: Date.now() };
        gesture.current = null;
      }
    }
  };
  const onTouchMove = (e) => {
    const g = gesture.current;
    if (!g) return;
    if (g.type === 'pinch' && e.touches.length === 2) {
      const [a, b] = e.touches;
      const dist = Math.hypot(b.clientX - a.clientX, b.clientY - a.clientY);
      const scale = Math.max(1, Math.min(4, g.startScale * (dist / g.startDist)));
      setZoom(z => ({ ...z, scale }));
    } else if (g.type === 'pan' && e.touches.length === 1) {
      const t = e.touches[0];
      setZoom(z => ({
        ...z,
        x: g.origX + (t.clientX - g.startX),
        y: g.origY + (t.clientY - g.startY),
      }));
    }
  };
  const onTouchEnd = (e) => {
    const g = gesture.current;
    if (g?.type === 'pinch' && zoom.scale <= 1.05) {
      setZoom({ scale: 1, x: 0, y: 0 });
    }
    if (!g && touchStart.current && canNavigate) {
      const t = e.changedTouches[0];
      const dx = t.clientX - touchStart.current.x;
      const dy = t.clientY - touchStart.current.y;
      const dt = Date.now() - touchStart.current.time;
      if (dt <= 700 && Math.abs(dx) >= 50 && Math.abs(dy) <= Math.abs(dx) * 0.8) {
        if (dx < 0) onNext(); else onPrev();
      }
    }
    touchStart.current = null;
    if (e.touches.length === 0) {
      gesture.current = null;
      setIsGesturing(false);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 300,
      background: mounted ? 'rgba(6,6,6,0.97)' : 'rgba(6,6,6,0)',
      backdropFilter: 'blur(14px)', WebkitBackdropFilter: 'blur(14px)',
      display: 'flex', justifyContent: 'center',
      alignItems: isNarrow ? 'flex-start' : 'center',
      padding: isMob ? '60px 16px 48px' : isNarrow ? '56px 32px 48px' : 48,
      transition: 'background .3s', cursor: 'zoom-out',
      overflowY: isNarrow ? 'auto' : 'hidden',
      WebkitOverflowScrolling: 'touch',
      touchAction: 'pan-y',
    }}>
      <button onClick={onClose} style={{
        position: 'fixed', top: isMob ? 14 : 28, right: isMob ? 14 : 28, background: 'rgba(10,10,10,0.8)',
        backdropFilter: 'blur(8px)',
        border: `1px solid ${DR_LINE}`, cursor: 'pointer',
        fontSize: isMob ? 10 : 11, letterSpacing: '0.16em', textTransform: 'uppercase',
        color: DR_INK, padding: isMob ? '7px 12px' : '8px 14px', borderRadius: 100, fontFamily: 'inherit',
        zIndex: 2,
      }}>{isMob ? 'Close' : 'Close · Esc'}</button>
      {canNavigate && !isMob && (
        <>
          <button aria-label="Previous" onClick={(e) => { e.stopPropagation(); onPrev(); }} style={navBtn('left')}>‹</button>
          <button aria-label="Next" onClick={(e) => { e.stopPropagation(); onNext(); }} style={navBtn('right')}>›</button>
        </>
      )}
      <div
        onClick={(e) => e.stopPropagation()}
        onTouchStart={onTouchStart}
        onTouchMove={onTouchMove}
        onTouchEnd={onTouchEnd}
        style={{
          display: 'grid',
          gridTemplateColumns: isNarrow ? '1fr' : '1fr 300px',
          gap: isMob ? 24 : isNarrow ? 32 : 48,
          maxWidth: 1400, width: '100%',
          perspective: 1800,
          cursor: 'default',
        }}>
        <div style={{
          position: 'relative',
          display: 'flex', justifyContent: 'center',
          opacity: mounted ? 1 : 0,
          transform: mounted ? 'translateZ(0) scale(1)' : 'translateZ(-40px) scale(0.96)',
          transition: 'opacity .5s, transform .6s cubic-bezier(.2,.7,.3,1)',
          transformStyle: 'preserve-3d',
        }}>
          <div style={{
            position: 'absolute', inset: -30,
            background: 'radial-gradient(ellipse at center, rgba(212,197,154,0.18), transparent 70%)',
            filter: 'blur(40px)', pointerEvents: 'none',
          }} />
          <img
            src={srcV(photo.src)}
            alt={photo.title}
            draggable={false}
            style={{
              maxWidth: '100%',
              maxHeight: isMob ? '65vh' : isNarrow ? '70vh' : '82vh',
              display: 'block',
              position: 'relative',
              boxShadow: `0 60px 100px -20px rgba(0,0,0,0.9), 0 0 0 1px ${DR_LINE}`,
              transform: `translate(${zoom.x}px, ${zoom.y}px) scale(${zoom.scale})`,
              transformOrigin: 'center center',
              transition: isGesturing ? 'none' : 'transform .25s ease-out',
              touchAction: zoom.scale > 1 ? 'none' : 'pan-y',
              willChange: 'transform',
            }} />
        </div>
        <aside style={{
          opacity: mounted ? 1 : 0,
          transform: mounted ? 'translateX(0) translateZ(0)' : 'translateX(24px) translateZ(40px)',
          transition: 'opacity .5s .15s, transform .6s .15s cubic-bezier(.2,.7,.3,1)',
        }}>
          <div style={{ fontSize: 11, letterSpacing: '0.18em', textTransform: 'uppercase', color: DR_ACCENT, marginBottom: 16 }}>
            {photo.series}
          </div>
          <h3 style={{
            fontFamily: '"Fraunces", serif', fontWeight: 300,
            fontSize: 36, letterSpacing: '-0.01em', margin: '0 0 8px',
          }}>{photo.title}</h3>
          <div style={{ fontSize: 12, color: DR_DIM, letterSpacing: '0.04em' }}>
            {photo.location} · {photo.year}
          </div>
        </aside>
      </div>
    </div>
  );
}

window.DR_Root = DR_Root;

// ─────────────────────────────────────────────────────────────
// Print enquiry modal
// ─────────────────────────────────────────────────────────────
// Submits to Formspree. To wire: create a form at formspree.io, then replace
// FORMSPREE_ENDPOINT below. Until then it falls back to mailto on submit.
const FORMSPREE_ENDPOINT = 'https://formspree.io/f/mqewwbdg';

function DR_EnquiryModal({ mode = 'prints', prefill, onClose }) {
  const isPrints = mode === 'prints';
  const isMob = useIsMobile();
  const [mounted, setMounted] = React.useState(false);
  const [state, setState] = React.useState('idle'); // idle | sending | sent | error
  const [form, setForm] = React.useState({
    name: '', email: '',
    photo: prefill || '',
    size: '8.5 × 11"',
    message: '',
  });

  React.useEffect(() => { requestAnimationFrame(() => setMounted(true)); }, []);
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape' && state !== 'sending') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose, state]);

  const update = (k) => (e) => setForm({ ...form, [k]: e.target.value });

  const mailtoFallback = () => {
    const subjectBase = isPrints
      ? (form.photo ? `Print enquiry: ${form.photo}` : 'Print enquiry')
      : 'Hello from your site';
    const lines = [
      `Name: ${form.name}`,
      `Email: ${form.email}`,
    ];
    if (isPrints) {
      if (form.photo) lines.push(`Photograph: ${form.photo}`);
      lines.push(`Size: ${form.size}`);
    }
    lines.push('', form.message);
    window.location.href = `mailto:krauch025@gmail.com?subject=${encodeURIComponent(subjectBase)}&body=${encodeURIComponent(lines.join('\n'))}`;
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!form.name || !form.email) return;
    const subject = isPrints
      ? (form.photo ? `Print enquiry: ${form.photo}` : 'Print enquiry')
      : 'Hello from karlrauch.com';
    const payload = { mode, ...form, _subject: subject, _replyto: form.email };
    if (!isPrints) { delete payload.photo; delete payload.size; }
    if (!FORMSPREE_ENDPOINT) {
      mailtoFallback();
      setState('sent');
      return;
    }
    setState('sending');
    try {
      const res = await fetch(FORMSPREE_ENDPOINT, {
        method: 'POST',
        headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (res.ok) setState('sent');
      else setState('error');
    } catch (err) {
      setState('error');
    }
  };

  const inputStyle = {
    width: '100%', padding: '12px 14px', background: 'rgba(255,255,255,0.04)',
    border: `1px solid ${DR_LINE}`, borderRadius: 2, color: DR_INK,
    fontFamily: 'inherit', fontSize: 16, letterSpacing: '0.01em',
    transition: 'border-color .2s, background .2s',
    boxSizing: 'border-box',
  };
  const labelStyle = {
    display: 'block', fontSize: 10, letterSpacing: '0.18em',
    textTransform: 'uppercase', color: DR_DIM, marginBottom: 8,
  };

  return (
    <div onClick={() => state !== 'sending' && onClose()} style={{
      position: 'fixed', inset: 0, zIndex: 400,
      background: mounted ? 'rgba(6,6,6,0.94)' : 'rgba(6,6,6,0)',
      backdropFilter: 'blur(16px)', WebkitBackdropFilter: 'blur(16px)',
      display: 'flex', alignItems: isMob ? 'flex-start' : 'center', justifyContent: 'center',
      padding: isMob ? 0 : 24, transition: 'background .3s',
      overflowY: 'auto',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%', maxWidth: 560,
        background: DR_BG2, border: isMob ? 'none' : `1px solid ${DR_LINE}`,
        padding: isMob ? '56px 20px 32px' : '48px 48px 40px', position: 'relative',
        minHeight: isMob ? '100vh' : 'auto',
        opacity: mounted ? 1 : 0,
        transform: mounted ? 'translateY(0)' : 'translateY(16px)',
        transition: 'opacity .4s, transform .5s cubic-bezier(.2,.7,.3,1)',
        boxShadow: isMob ? 'none' : '0 40px 80px -20px rgba(0,0,0,0.7)',
      }}>
        <button onClick={onClose} disabled={state === 'sending'} style={{
          position: 'absolute', top: 20, right: 20, background: 'transparent',
          border: `1px solid ${DR_LINE}`, cursor: 'pointer',
          fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase',
          color: DR_INK, padding: '6px 12px', borderRadius: 100, fontFamily: 'inherit',
          opacity: state === 'sending' ? 0.4 : 1,
        }}>Close</button>

        {state === 'sent' ? (
          <div style={{ textAlign: 'center', padding: '32px 0 8px' }}>
            <div style={{ fontFamily: '"Fraunces", serif', fontWeight: 300, fontStyle: 'italic', fontSize: 48, color: DR_ACCENT, letterSpacing: '-0.02em', marginBottom: 16 }}>
              Thank you.
            </div>
            <p style={{ color: DR_DIM, fontSize: 14, lineHeight: 1.7, maxWidth: 360, margin: '0 auto' }}>
              {isPrints
                ? 'Karl will be in touch within a few days. Prints are hand-made, so timelines vary a little with season.'
                : 'Karl will get back to you within a few days.'}
            </p>
          </div>
        ) : (
          <>
            {!isPrints && (
              <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 20 }}>
                <img src={srcV("img/karl-portrait.jpg")} alt="Karl Rauch" style={{
                  width: 56, height: 56, borderRadius: '50%', objectFit: 'cover',
                  border: `1px solid ${DR_LINE}`,
                  boxShadow: '0 4px 16px rgba(0,0,0,0.5)',
                }} />
                <div style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: DR_DIM }}>
                  Say hello
                </div>
              </div>
            )}
            {isPrints && (
              <div style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: DR_DIM, marginBottom: 12 }}>
                Enquire
              </div>
            )}
            <h2 style={{
              fontFamily: '"Fraunces", serif', fontWeight: 300, fontStyle: 'italic',
              fontSize: isMob ? 32 : 40, margin: '0 0 8px', letterSpacing: '-0.02em', color: DR_INK,
            }}>
              {isPrints ? 'About a print.' : 'Get in touch.'}
            </h2>
            <p style={{ color: DR_DIM, fontSize: 13, lineHeight: 1.7, margin: '0 0 32px' }}>
              {isPrints
                ? "Each print is hand-made on archival paper on request. Tell me what you're drawn to and I'll reply within a few days."
                : "Questions, hellos, commissions, or just something nice to say — all welcome."}
            </p>

            <form onSubmit={onSubmit}>
              <div style={{ display: 'grid', gridTemplateColumns: isMob ? '1fr' : '1fr 1fr', gap: 16, marginBottom: 16 }}>
                <div>
                  <label style={labelStyle}>Name</label>
                  <input required value={form.name} onChange={update('name')} style={inputStyle} />
                </div>
                <div>
                  <label style={labelStyle}>Email</label>
                  <input required type="email" value={form.email} onChange={update('email')} style={inputStyle} />
                </div>
              </div>
              {isPrints && (
                <>
                  <div style={{ marginBottom: 16 }}>
                    <label style={labelStyle}>Photograph{prefill ? '' : ' (optional)'}</label>
                    <input value={form.photo} onChange={update('photo')} placeholder="e.g. Storm over the Elks" style={inputStyle} />
                  </div>
                  <div style={{ marginBottom: 16 }}>
                    <label style={labelStyle}>Size</label>
                    <select value={form.size} onChange={update('size')} style={{ ...inputStyle, appearance: 'none', background: 'rgba(255,255,255,0.04) url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'10\' height=\'6\' viewBox=\'0 0 10 6\'><path d=\'M1 1l4 4 4-4\' stroke=\'%238a8578\' stroke-width=\'1.2\' fill=\'none\'/></svg>") no-repeat right 16px center' }}>
                      <option>8.5 × 11"</option>
                      <option>13 × 19"</option>
                      <option>Not sure yet</option>
                    </select>
                  </div>
                </>
              )}
              <div style={{ marginBottom: 24 }}>
                <label style={labelStyle}>Message</label>
                <textarea value={form.message} onChange={update('message')} rows={4}
                  placeholder={isPrints
                    ? "Anything helpful — the room it's for, timing, questions."
                    : "What's on your mind?"}
                  style={{ ...inputStyle, resize: 'vertical', minHeight: 90, fontFamily: 'inherit' }} />
              </div>

              {state === 'error' && (
                <div style={{ color: '#e08a6a', fontSize: 12, marginBottom: 16 }}>
                  Something went wrong. <a href="#" onClick={(e) => { e.preventDefault(); mailtoFallback(); }} style={{ color: DR_ACCENT }}>Email Karl directly.</a>
                </div>
              )}

              <button type="submit" disabled={state === 'sending'} style={{
                width: '100%', padding: '14px 20px',
                background: DR_ACCENT, color: DR_BG, border: 'none',
                fontSize: 11, letterSpacing: '0.18em', textTransform: 'uppercase',
                fontFamily: 'inherit', cursor: state === 'sending' ? 'wait' : 'pointer',
                borderRadius: 2, opacity: state === 'sending' ? 0.6 : 1,
                transition: 'opacity .2s',
              }}>
                {state === 'sending' ? 'Sending…' : (isPrints ? 'Send enquiry' : 'Send message')}
              </button>
            </form>
          </>
        )}
      </div>
    </div>
  );
}
