// V4 — Hybrid: logo on top + editorial paper stack + scrape-to-reveal inside paper
// Background + stripes from V1 (beige + subtle red verticals)
// Logo (Anton + Pinyon Script) locked top-center, always visible
// Paper stack (from V2) sits in the middle — paperclip, hole-punches, rotation
// The top paper is a scrape-to-reveal canvas — drag to uncover paintings underneath

const v4Style = {
  wrap: {
    position: 'relative', width: '100%',
    minHeight: '100vh',
    background: '#EDE8DE',
    backgroundImage: 'repeating-linear-gradient(90deg,transparent,transparent 119px,rgba(140,10,10,0.18) 119px,rgba(140,10,10,0.18) 120px)',
    fontFamily: "'Space Grotesk', sans-serif",
    color: '#1A1A1A',
    overflowX: 'hidden',
  },
  nav: {
    position: 'absolute', top: 0, left: 0, right: 0, zIndex: 60,
    display: 'flex', justifyContent: 'space-between', alignItems: 'center',
    padding: '24px 44px',
  },
  navLogoSmall: {
    fontFamily: "'Anton', sans-serif",
    fontSize: 16, letterSpacing: '0.02em',
    color: '#C41E1E',
  },
  navLinks: {
    display: 'flex', gap: 26,
    fontFamily: "'Space Mono', monospace",
    fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase',
    color: '#1A1A1A',
  },
  heroWrap: {
    position: 'absolute',
    top: 78, left: 0, right: 0,
    zIndex: 50,
    textAlign: 'center',
    pointerEvents: 'none',
  },
  heroTitle1: {
    display: 'block',
    fontFamily: "'Anton', sans-serif",
    fontSize: 'clamp(48px, 13vw, 92px)', letterSpacing: '-0.01em',
    color: '#1A1A1A',
    lineHeight: 0.9,
  },
  heroTitle2: {
    display: 'inline-block',
    fontFamily: "'Pinyon Script', cursive",
    fontSize: 'clamp(56px, 15vw, 104px)', color: '#C41E1E',
    lineHeight: 0.85,
    marginTop: -14,
    transform: 'rotate(-3deg)',
    textShadow: '2px 3px 0 rgba(196,30,30,0.12)',
  },
  tagline: {
    marginTop: 8,
    fontFamily: "'Space Mono', monospace",
    fontSize: 10, letterSpacing: '0.28em', textTransform: 'uppercase',
    color: 'rgba(26,26,26,0.6)',
  },
  stage: {
    position: 'absolute',
    top: 300, left: 0, right: 0,
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    zIndex: 10,
  },
  paperStack: {
    position: 'relative',
    width: 840, height: 540,
    /* Scale from the top so the paper grows downward from the stage's
       top edge — keeps the gap to the hero logo intact at every scale.
       Without this, larger scales would push the paper upward into
       the hero text. */
    transformOrigin: 'top center',
    flexShrink: 0,
  },
  paper: (i, idx) => ({
    position: 'absolute',
    inset: 0,
    background: ['#e2dbc8', '#ece4cf', '#f4ecd6'][i],
    boxShadow: '0 16px 34px rgba(0,0,0,0.22), 0 5px 12px rgba(0,0,0,0.14)',
    transform: `rotate(${[-2.5, 1.2, 0][i]}deg) translate(${[-14, 10, 0][i]}px, ${[8, -4, 0][i]}px)`,
    transition: 'transform .4s cubic-bezier(.2,.8,.3,1)',
  }),
  punchHole: {
    position: 'absolute',
    left: 32, width: 16, height: 16, borderRadius: '50%',
    background: '#EDE8DE',
    boxShadow: 'inset 2px 2px 4px rgba(0,0,0,0.22)',
  },
  topSheet: {
    position: 'absolute',
    inset: 0,
    background: '#f4ecd6',
    boxShadow: '0 20px 40px rgba(0,0,0,0.25), 0 6px 14px rgba(0,0,0,0.15)',
    overflow: 'hidden',
    // Stop the browser from scrolling/zooming while the user drags
    // their finger across the sheet to scrape it.
    touchAction: 'none',
  },
  clip: {
    position: 'absolute',
    top: -30, left: '50%', transform: 'translateX(-50%) rotate(-4deg)',
    width: 52, height: 120, zIndex: 30,
    filter: 'drop-shadow(2px 4px 4px rgba(0,0,0,0.35))',
    pointerEvents: 'none',
  },
  paperMetaTL: {
    position: 'absolute', top: 24, left: 70,
    fontFamily: "'Space Mono', monospace",
    fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
    color: 'rgba(26,26,26,0.55)', lineHeight: 1.8,
    zIndex: 5,
  },
  paperMetaTR: {
    position: 'absolute', top: 24, right: 32,
    fontFamily: "'Space Mono', monospace",
    fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
    color: 'rgba(26,26,26,0.55)', textAlign: 'right', lineHeight: 1.8,
    zIndex: 5,
  },
  paperMetaBottom: {
    position: 'absolute', bottom: 18, left: 70, right: 32,
    display: 'flex', justifyContent: 'space-between',
    fontFamily: "'Space Mono', monospace",
    fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
    color: 'rgba(26,26,26,0.55)',
    zIndex: 5,
  },
  resetBtn: {
    position: 'absolute',
    bottom: 20, right: 44, zIndex: 55,
    padding: '10px 18px',
    background: '#1A1A1A', color: '#EDE8DE',
    border: 'none', cursor: 'pointer',
    fontFamily: "'Space Mono', monospace",
    fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase',
    boxShadow: '3px 3px 0 #C41E1E',
  },
  scrapeHint: {
    position: 'absolute', bottom: 20, left: 44, zIndex: 55,
    display: 'flex', alignItems: 'center', gap: 10,
    fontFamily: "'Space Mono', monospace",
    fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
    color: 'rgba(26,26,26,0.55)',
  },
};

function V4Hybrid() {
  const canvasRef = React.useRef(null);
  const sheetRef = React.useRef(null);
  const lastPt = React.useRef(null);
  const isDown = React.useRef(false);
  const [cursor, setCursor] = React.useState({ x: -100, y: -100, show: false });
  const [hintVisible, setHintVisible] = React.useState(true);

  // Responsive layout: target a generous fraction of viewport width so the
  // paper actually fills the screen instead of leaving big empty bands.
  // The page is now scrollable, so we no longer have to make the paper
  // also fit the viewport height — if it ends up taller than the visible
  // area, the user can scroll down. We still cap the scale so it never
  // gets absurd on ultrawide 4K monitors.
  const [stackScale, setStackScale] = React.useState(1);
  const [stageTop, setStageTop] = React.useState(300);
  const [wrapMinHeight, setWrapMinHeight] = React.useState('100vh');
  const [paperOrigin, setPaperOrigin] = React.useState('center center');
  // On phones the 840×540 landscape paper is rotated 90° so it becomes
  // a portrait 540×840 — feels more natural on tall mobile screens.
  const [rotatePortrait, setRotatePortrait] = React.useState(false);
  const heroRef = React.useRef(null);
  // Re-render when the site language changes (the dispatch comes from
  // script.js setLang). Lets the localized stamp below switch instantly.
  const [, setLangTick] = React.useState(0);
  React.useEffect(() => {
    const onLang = () => setLangTick(t => t + 1);
    window.addEventListener('klevaas:langchange', onLang);
    return () => window.removeEventListener('klevaas:langchange', onLang);
  }, []);
  const lang = (typeof getLang === 'function')
    ? getLang()
    : (() => { try { return localStorage.getItem('klevaas_lang') || 'no'; } catch (e) { return 'no'; } })();
  const contemporaryLabel = lang === 'en' ? 'CONTEMPORARY ART — PAINTING' : 'SAMTIDSKUNST — MALERI';
  React.useEffect(() => {
    const compute = () => {
      const vw = window.innerWidth;
      const vh = window.innerHeight;
      const isPhone = vw < 600;
      // Flip the paper to portrait on phones — its effective bounding
      // box becomes 540 wide × 840 tall after the rotate(90deg).
      const rotate = isPhone;
      setRotatePortrait(rotate);
      const effW = rotate ? 540 : 840;
      const effH = rotate ? 840 : 540;
      // Space reserved above the paper = hero title height + a clear gap.
      // On phones we measure the actual rendered title (its font size
      // scales with viewport width) so the gap below it stays consistent
      // on every screen. Desktop keeps its fixed reserve.
      const heroTop = 78; // matches v4Style.heroWrap.top
      // Space between the hero title and the paper — measured from the
      // actual rendered title height so it's the same on every screen.
      const gap = 100;
      let heroBlock;
      if (heroRef.current) {
        heroBlock = heroTop + heroRef.current.offsetHeight + gap;
      } else {
        heroBlock = isPhone ? 256 : 335;
      }
      // On phones leave a margin on each side so the patterned background
      // shows beside the paper instead of it hugging the screen edges.
      const availW = isPhone ? vw - 48 : vw * 0.86;
      const sx = availW / effW;
      const s = Math.max(0.35, Math.min(2.2, sx));
      setStackScale(s);
      setStageTop(heroBlock);
      const reservedBottom = 50;
      const visualPaperH = effH * s;
      const fitsVh = visualPaperH <= (vh - heroBlock - reservedBottom);
      // Phones: always anchor the paper's top just below the title so the
      // gap is identical regardless of screen height. Desktop centers.
      setPaperOrigin(isPhone ? 'top center' : (fitsVh ? 'center center' : 'top center'));
      // Extra breathing room below the paper on phones so the Reset
      // button has clear separation below the (now portrait) paper.
      const bottomBuffer = isPhone ? 240 : 80;
      const required = heroBlock + visualPaperH + bottomBuffer;
      setWrapMinHeight(Math.max(vh, required) + 'px');
    };
    compute();
    // Re-measure once web fonts have loaded (title height affects the gap).
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(compute);
    window.addEventListener('resize', compute);
    return () => window.removeEventListener('resize', compute);
  }, []);

  // Pool of paintings to reveal — scattered inside the sheet. The
  // landscape (840×540) and portrait (540×840) layouts use different
  // positions because the canvases have very different shapes.
  const revealArtLandscape = [
    { src: 'images/leopard.jpg?v=1', x: 40,  y: 70,  w: 220, h: 260, rot: -4 },
    { src: 'images/oyne.jpg?v=1',    x: 300, y: 50,  w: 240, h: 180, rot: 2 },
    { src: 'images/lips.jpg?v=1',    x: 570, y: 80,  w: 230, h: 170, rot: -3 },
    { src: 'images/statue.jpg?v=1', x: 90,  y: 280, w: 200, h: 230, rot: 5 },
    { src: 'images/studio-1.jpg?v=1',x: 300, y: 260, w: 240, h: 180, rot: -2 },
    { src: 'images/blaatt-bord.jpg?v=1', x: 580, y: 270, w: 210, h: 220, rot: 4 },
  ];
  const revealArtPortrait = [
    { src: 'images/leopard.jpg?v=1',     x: 30,  y: 60,  w: 230, h: 200, rot: -4 },
    { src: 'images/oyne.jpg?v=1',        x: 280, y: 80,  w: 230, h: 170, rot: 2 },
    { src: 'images/lips.jpg?v=1',        x: 60,  y: 290, w: 220, h: 200, rot: -3 },
    { src: 'images/statue.jpg?v=1',      x: 290, y: 290, w: 210, h: 240, rot: 5 },
    { src: 'images/studio-1.jpg?v=1',    x: 30,  y: 560, w: 240, h: 180, rot: -2 },
    { src: 'images/blaatt-bord.jpg?v=1', x: 280, y: 580, w: 230, h: 200, rot: 4 },
  ];
  const revealArt = rotatePortrait ? revealArtPortrait : revealArtLandscape;

  function initCover() {
    const c = canvasRef.current;
    if (!c) return;
    const r = sheetRef.current.getBoundingClientRect();
    // Use layout (unscaled) size, not rect (which reflects CSS zoom from DC)
    const w = sheetRef.current.clientWidth;
    const h = sheetRef.current.clientHeight;
    c.width = w;
    c.height = h;
    c.style.width = w + 'px';
    c.style.height = h + 'px';
    const ctx = c.getContext('2d');
    // Soft paper fill
    ctx.fillStyle = '#f4ecd6';
    ctx.fillRect(0, 0, c.width, c.height);
    // Subtle paper noise via tiny specks
    for (let i = 0; i < 400; i++) {
      ctx.fillStyle = `rgba(${140 + Math.random()*40},${120 + Math.random()*30},${80 + Math.random()*30},${Math.random()*0.08})`;
      ctx.fillRect(Math.random()*c.width, Math.random()*c.height, 1, 1);
    }
    // Center hint stamp
    ctx.save();
    ctx.translate(c.width/2, c.height/2);
    ctx.rotate(-0.04);
    ctx.fillStyle = 'rgba(196,30,30,0.18)';
    ctx.font = "700 18px 'Space Mono', monospace";
    ctx.textAlign = 'center';
    ctx.fillText('SCRAPE TO REVEAL', 0, -6);
    ctx.font = "400 11px 'Space Mono', monospace";
    ctx.fillStyle = 'rgba(26,26,26,0.45)';
    // Stamp outline
    ctx.strokeStyle = 'rgba(196,30,30,0.28)';
    ctx.lineWidth = 2;
    ctx.strokeRect(-140, -36, 280, 68);
    ctx.restore();
  }

  React.useEffect(() => {
    initCover();
    const ro = new ResizeObserver(initCover);
    if (sheetRef.current) ro.observe(sheetRef.current);
    return () => ro.disconnect();
    // eslint-disable-next-line
  }, []);

  function scrape(x0, y0, x1, y1) {
    const ctx = canvasRef.current.getContext('2d');
    ctx.save();
    ctx.globalCompositeOperation = 'destination-out';
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    // Main stroke
    ctx.lineWidth = 58;
    ctx.beginPath();
    ctx.moveTo(x0, y0);
    const cx = (x0 + x1) / 2 + (Math.random() - 0.5) * 3;
    const cy = (y0 + y1) / 2 + (Math.random() - 0.5) * 3;
    ctx.quadraticCurveTo(cx, cy, x1, y1);
    ctx.stroke();
    // Feather
    ctx.lineWidth = 78;
    ctx.globalAlpha = 0.3;
    ctx.stroke();
    ctx.restore();
  }

  function localPt(e) {
    // Use the actual sheet element's bounding rect + account for any
    // CSS transform scaling applied by the parent. Works for both
    // landscape (840×540) and portrait (540×840) layouts because the
    // canvas internal size always matches the sheet's layout box.
    const el = sheetRef.current;
    const r = el.getBoundingClientRect();
    const scaleX = r.width / el.clientWidth;
    const scaleY = r.height / el.clientHeight;
    return {
      x: (e.clientX - r.left) / scaleX,
      y: (e.clientY - r.top) / scaleY,
    };
  }

  function onMove(e) {
    const p = localPt(e);
    setCursor({ x: p.x, y: p.y, show: true });
    // Scrape continuously as long as pointer is inside the sheet (no click needed)
    if (lastPt.current) {
      scrape(lastPt.current.x, lastPt.current.y, p.x, p.y);
      if (hintVisible) setHintVisible(false);
    }
    lastPt.current = p;
  }

  function onLeave() {
    setCursor(c => ({ ...c, show: false }));
    lastPt.current = null;
  }

  // For touch we need to call preventDefault so the page doesn't scroll
  // while the finger drags across the sheet.
  function onPointerDown(e) {
    if (e.pointerType !== 'mouse') {
      // Capture so subsequent pointermove events keep firing on this element
      // even if the finger drifts slightly outside it.
      try { e.currentTarget.setPointerCapture(e.pointerId); } catch {}
    }
    onMove(e);
  }
  function onPointerMove(e) {
    if (e.pointerType !== 'mouse') {
      // For touch, only scrape while the finger is pressed down
      if (e.buttons === 0 && e.pressure === 0) return;
    }
    onMove(e);
  }
  function onPointerUp(e) {
    if (e.pointerType !== 'mouse') {
      try { e.currentTarget.releasePointerCapture(e.pointerId); } catch {}
      lastPt.current = null;
      setCursor(c => ({ ...c, show: false }));
    }
  }

  function reset() {
    initCover();
    lastPt.current = null;
    setHintVisible(true);
  }

  return (
    <div style={{...v4Style.wrap, minHeight: wrapMinHeight}}>
      {/* Nav is rendered by index.html (plain HTML) so that script.js
          can inject the cart icon and the mobile dropdown works. */}

      {/* Hero logo (always visible) */}
      <div style={v4Style.heroWrap} ref={heroRef}>
        <span style={v4Style.heroTitle1}>K.KLEVAAS</span>
        <br/>
        <span style={v4Style.heroTitle2}>Art studios</span>
      </div>

      {/* Paper stack with scrape-to-reveal sheet on top */}
      <div style={{...v4Style.stage, top: stageTop}}>
        <div style={{
            ...v4Style.paperStack,
            width: rotatePortrait ? 540 : 840,
            height: rotatePortrait ? 840 : 540,
            transform: `scale(${stackScale})`,
            transformOrigin: paperOrigin,
        }}>
          {/* Back papers (from V2) */}
          <div style={v4Style.paper(0)} />
          <div style={v4Style.paper(1)} />

          {/* Top sheet = interactive (mouse + touch via pointer events) */}
          <div
            style={v4Style.topSheet}
            ref={sheetRef}
            onMouseMove={onMove}
            onMouseLeave={onLeave}
            onPointerDown={onPointerDown}
            onPointerMove={onPointerMove}
            onPointerUp={onPointerUp}
            onPointerCancel={onPointerUp}
          >
            {/* Hole-punch column */}
            <div style={{...v4Style.punchHole, top: 70}} />
            <div style={{...v4Style.punchHole, top: 260}} />
            <div style={{...v4Style.punchHole, top: 450}} />

            {/* Reveal layer — paintings positioned absolutely */}
            {revealArt.map((a, i) => (
              <img key={i}
                   src={a.src}
                   alt=""
                   draggable={false}
                   style={{
                     position: 'absolute',
                     left: a.x, top: a.y,
                     width: a.w, height: a.h,
                     objectFit: 'cover',
                     transform: `rotate(${a.rot}deg)`,
                     boxShadow: '0 6px 14px rgba(0,0,0,0.18)',
                     background: '#fff',
                     pointerEvents: 'none',
                     userSelect: 'none',
                   }}
              />
            ))}

            {/* Cover canvas on top */}
            <canvas
              ref={canvasRef}
              style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}
            />

            {/* Paper meta (sits above canvas so always readable) */}
            <div style={v4Style.paperMetaTL}>
              ISSUE 01 / 2025<br/>
              K.KLEVAAS ART STUDIOS<br/>
              OSLO · NORWAY
            </div>
            <div style={v4Style.paperMetaTR}>
              ARTWORKS : 40+<br/>
              COMMISSIONS : OPEN<br/>
              EST. 2023
            </div>
            <div style={v4Style.paperMetaBottom}>
              <span></span>
              <span>{contemporaryLabel}</span>
              <span>PG. 01 / 04</span>
            </div>

            {/* Custom cursor (red scraper dot) */}
            {cursor.show && (
              <div style={{
                position: 'absolute',
                left: cursor.x - 22, top: cursor.y - 22,
                width: 44, height: 44, borderRadius: '50%',
                border: '2px solid rgba(196,30,30,0.85)',
                background: 'radial-gradient(circle, rgba(196,30,30,0.12), transparent 70%)',
                pointerEvents: 'none',
                zIndex: 100,
                mixBlendMode: 'multiply',
              }} />
            )}
          </div>

          {/* Paperclip over everything */}
          <svg style={v4Style.clip} viewBox="0 0 52 120">
            <defs>
              <linearGradient id="v4clip" x1="0" y1="0" x2="1" y2="0">
                <stop offset="0%" stopColor="#f4f4f4"/>
                <stop offset="40%" stopColor="#c8c8c8"/>
                <stop offset="60%" stopColor="#8a8a8a"/>
                <stop offset="100%" stopColor="#d0d0d0"/>
              </linearGradient>
            </defs>
            <path d="M 26 8 Q 8 8 8 34 L 8 96 Q 8 114 24 114 Q 40 114 40 96 L 40 34 Q 40 22 30 22 Q 20 22 20 34 L 20 86"
                  fill="none" stroke="url(#v4clip)" strokeWidth="4.5" strokeLinecap="round"/>
          </svg>
        </div>
      </div>

      <button style={v4Style.resetBtn} onClick={reset}>↺ Reset</button>
    </div>
  );
}

window.V4Hybrid = V4Hybrid;
