/* cover.jsx — Volume I masthead + Table of Contents */
/* global React, Bloom, Splatter, ColorBar, RegistrationMark, Burst, Arrow, Underline, CircledNumber, CHAPTERS, ENGAGEMENT_MODES */

const { useState, useEffect } = React;

function Cover({ setView }) {
  const year = new Date().getFullYear();
  const [easterOpen, setEasterOpen] = useState(false);
  /* "A career story—" supra link jumps to the Career Journey view. setView
     comes from app.jsx; safe-fallback to hash navigation if it isn't passed. */
  const goJourney = React.useCallback(() => {
    if (typeof setView === "function") setView("journey");
    else { window.location.hash = "journey"; }
  }, [setView]);

  /* Auto-open the "About this zine" modal on the user's first visit.
     The flag is persisted in localStorage so repeat visitors aren't interrupted. */
  useEffect(() => {
    let seen = false;
    try { seen = localStorage.getItem("vastola.seenIntro") === "1"; } catch (e) {}
    if (!seen) {
      const t = setTimeout(() => setEasterOpen(true), 700);
      try { localStorage.setItem("vastola.seenIntro", "1"); } catch (e) {}
      return () => clearTimeout(t);
    }
  }, []);

  /* ESC to close the easter-egg modal */
  useEffect(() => {
    if (!easterOpen) return;
    const onKey = (e) => { if (e.key === "Escape") setEasterOpen(false); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [easterOpen]);

  /* The "A digital hand-set zine." tagline moved to the global footer, but it
     still opens this "About this zine" modal — the footer dispatches this event
     and we listen for it here so the easter egg stays fully intact. */
  useEffect(() => {
    const onOpen = () => setEasterOpen(true);
    window.addEventListener("vastola.about.open", onOpen);
    return () => window.removeEventListener("vastola.about.open", onOpen);
  }, []);

  return (
    <section className="cover" data-screen-label="00 Cover">
      {/* Watercolor moments */}
      <Bloom color="var(--accent)" size={520} top={-120} left={-140} seed={3} opacity={0.6} />
      <Bloom color="var(--bloom)" size={420} top={"60%"} left={"55%"} seed={7} opacity={0.45} />
      <Splatter color="var(--ink)" size={300} seed={11} style={{ top: "20%", right: "5%" }} />

      {/* The site-wide masthead nav now lives in chapter-nav.jsx (SubNav) so the
          old `cover__chrome` strip is gone. A small "about this zine" tagline
          link still sits above the supra to keep the easter-egg surface. */}

      {/* Main masthead grid */}
      <div className="cover__main">
        <div className="cover__masthead">
          {/* All masthead content lives in a single shrink-to-fit block so the
              deck, byline, and availability strip share a left edge with the
              "V" of VASTOLA (rather than the cover gutter). The masthead is
              flex+align-items:center, so the block centers horizontally. */}
          <div className="cover__title-block">
            {/* Title row: title-stack (supra above VASTOLA) + Vol. I badge anchored
                to the top-right of the final "A", overlapping ~20% of its width. */}
            <div className="cover__title-row">
              <div className="cover__title-stack">
                {/* Eyebrow (page · tagline) — matches the About me eyebrow style. */}
                <button
                  type="button"
                  className="cover__supra"
                  onClick={goJourney}
                  aria-label="Jump to my career story">
                  Career story &middot; Two decades, in chapters
                </button>
                <h1 className="cover__title">
                  VAS<em>TO</em>LA
                </h1>
              </div>
              <button
                type="button"
                className="vol-badge"
                onClick={() => setEasterOpen(true)}
                aria-label="About this zine — Volume I">
                <Burst size={130} points={20} color="var(--accent)">
                  Vol. I<br />{year}
                </Burst>
              </button>
            </div>
            {/* Consolidated sub-header. The old "A digital hand-set zine."
                tagline + the byline credit line now live in the global footer
                (chapters-late.jsx); the tagline easter egg is still reachable
                from there via the `vastola.about.open` event, and from the
                Vol. badge above. */}
            <p className="cover__deck">
              Two decades of learning, growth, and curiosity-driven work across craft, scale, and complexity. Every chapter shaped the operator I am today.
            </p>
          </div>
        </div>

        {/* TOC slot — the ChapterNav (floating) anchors itself into this column
            initially, then animates out to the right rail as the user scrolls. */}
        <div className="cover__toc-slot" aria-hidden="true" />
      </div>

      {/* Bottom footer — grab target + colorbar only. Copyright moved to the
          global Footer; the "Connect on LinkedIn →" link was removed entirely
          since the masthead "Connect with me" CTA covers that route. */}
      <footer className="cover__footer">
        {/* The easter-egg colour picker (ColorBar) was removed from this
            top-of-page footer per request; the GrabTarget easter egg stays. */}
        <span style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <GrabTarget />
        </span>
      </footer>

      {/* ===== Easter-egg modal: "About this zine" =====
          Rendered via portal directly into <body> so it escapes the .page-host
          filter container — otherwise position:fixed would anchor to the page,
          not the viewport, and the card would land mid-document. */}
      {easterOpen && ReactDOM.createPortal(
        <div
          className="easter"
          role="dialog"
          aria-modal="true"
          aria-labelledby="easter-title"
          onMouseDown={(e) => { if (e.target === e.currentTarget) setEasterOpen(false); }}>
          <div className="easter__card">
            <button
              type="button"
              className="easter__close"
              onClick={() => setEasterOpen(false)}
              aria-label="Close">
              &times;
            </button>
            <span className="easter__tape">hello world</span>
            <h3 id="easter-title" className="easter__title">
              This is a <em>digital zine.</em>
            </h3>
            <p>
              The <em>visual concept</em> winks at where my career began: a branding firm with a real comping room and cutting room floor. Wireframes pinned next to four-color comps. That&rsquo;s where I fell in love with design, craft, and intention. This zine brings my whole creative practice together&mdash;<strong>artist, designer, builder</strong>&mdash;using the same layered, intentional thinking that started there.
            </p>
            <p>
              This is a <em>side project</em>, hand-built by <strong>Anastasia</strong> with <strong>Claude</strong> &mdash; an experiment in Claude Design and Claude Code, and a love letter to the format and my creative roots.
            </p>
            <p className="easter__signoff">&mdash; AV</p>

            {/* Right-brain / left-brain layout toggle. "YOUR CHOICE" sits inline
                on the dashed line with dashes flanking it on both sides. */}
            <div className="easter__toggle-block" aria-label="Layout preference">
              <div className="easter__toggle-divider" aria-hidden="true">
                <span>your choice</span>
              </div>
              <div className="easter__toggle" role="group" aria-label="View mode">
                <button
                  type="button"
                  className="easter__toggle-btn is-active"
                  aria-pressed="true"
                  data-mode="creative">
                  <span className="easter__toggle-label">Creative</span>
                  <span className="easter__toggle-sub">right brain</span>
                </button>
                <button
                  type="button"
                  className="easter__toggle-btn is-bounce"
                  aria-pressed="false"
                  data-mode="vanilla"
                  onClick={() => {
                    try { localStorage.setItem("vastola.viewPref", "vanilla"); } catch (e) {}
                    alert("Vanilla version is being built — peek back soon.");
                  }}>
                  <span className="easter__toggle-label">Vanilla</span>
                  <span className="easter__toggle-sub">left brain</span>
                </button>
              </div>
            </div>
          </div>
        </div>,
        document.body
      )}
    </section>
  );
}

/* ============================================================
   ABOUT-ZINE MODAL — extracted from <Cover> so the "About this zine"
   easter egg stays globally available now that the big cover no longer
   leads the Career story page. Mounted once per page (app.jsx /
   creative.jsx); auto-opens on first visit and opens whenever the footer
   tagline dispatches `vastola.about.open`.
   ============================================================ */
function AboutZineModal() {
  const [open, setOpen] = useState(false);
  /* Which volume is this page? Drives the volume toggle's active state — the
     main landing (/aworkinglife) defaults to "A Working Life". */
  const isCreative = /Creative/i.test(decodeURIComponent(window.location.pathname));

  useEffect(() => {
    let seen = false;
    try { seen = localStorage.getItem("vastola.seenIntro") === "1"; } catch (e) {}
    if (!seen) {
      const t = setTimeout(() => setOpen(true), 700);
      try { localStorage.setItem("vastola.seenIntro", "1"); } catch (e) {}
      return () => clearTimeout(t);
    }
  }, []);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open]);

  useEffect(() => {
    const onOpen = () => setOpen(true);
    window.addEventListener("vastola.about.open", onOpen);
    return () => window.removeEventListener("vastola.about.open", onOpen);
  }, []);

  if (!open) return null;
  return ReactDOM.createPortal(
    <div
      className="easter"
      role="dialog"
      aria-modal="true"
      aria-labelledby="about-zine-title"
      onMouseDown={(e) => { if (e.target === e.currentTarget) setOpen(false); }}>
      <div className="easter__card">
        <button type="button" className="easter__close" onClick={() => setOpen(false)} aria-label="Close">
          &times;
        </button>
        <span className="easter__tape">hello world</span>
        <h3 id="about-zine-title" className="easter__title">
          This is a <em>digital zine.</em>
        </h3>
        <p>
          The <em>visual concept</em> winks at where my career began: a branding firm with a real comping room and cutting room floor. Wireframes pinned next to four-color comps. That&rsquo;s where I fell in love with design, craft, and intention. This zine brings my whole creative practice together&mdash;<strong>artist, designer, builder</strong>&mdash;using the same layered, intentional thinking that started there.
        </p>
        <p>
          This is a <em>side project</em>, hand-built by <strong>Anastasia</strong> with <strong>Claude</strong> &mdash; an experiment in Claude Design and Claude Code, and a love letter to the format and my creative roots.
        </p>
        <p className="easter__signoff">&mdash; AV</p>

        {/* Volume toggle — two volumes of the zine. The current page's volume
            is selected (defaults to "A Working Life" on the main landing); the
            other links across. */}
        <div className="easter__toggle-block" aria-label="Choose a volume">
          <div className="easter__toggle-divider" aria-hidden="true">
            <span>two volumes</span>
          </div>
          <div className="easter__volumes" role="group" aria-label="Volume">
            <a
              href="/aworkinglife"
              className={`easter__vol${!isCreative ? " is-active" : ""}`}
              {...(!isCreative ? { "aria-current": "page" } : {})}>
              A Working Life
            </a>
            <span className="easter__vol-sep" aria-hidden="true">/</span>
            <a
              href="/acreativelife"
              className={`easter__vol${isCreative ? " is-active" : ""}`}
              {...(isCreative ? { "aria-current": "page" } : {})}>
              A Creative Life
            </a>
          </div>
        </div>

        {/* Theme toggle (Creative / Vanilla) + "your choice" divider — TEMPORARILY
            removed; the modal now ends at "— AV". Restore by removing `false &&`. */}
        {false && (
        <div className="easter__toggle-block" aria-label="Layout preference">
          <div className="easter__toggle-divider" aria-hidden="true">
            <span>your choice</span>
          </div>
          <div className="easter__toggle" role="group" aria-label="View mode">
            <button type="button" className="easter__toggle-btn is-active" aria-pressed="true" data-mode="creative">
              <span className="easter__toggle-label">Creative</span>
              <span className="easter__toggle-sub">right brain</span>
            </button>
            <button
              type="button"
              className="easter__toggle-btn is-bounce"
              aria-pressed="false"
              data-mode="vanilla"
              onClick={() => {
                try { localStorage.setItem("vastola.viewPref", "vanilla"); } catch (e) {}
                alert("Vanilla version is being built — peek back soon.");
              }}>
              <span className="easter__toggle-label">Vanilla</span>
              <span className="easter__toggle-sub">left brain</span>
            </button>
          </div>
        </div>
        )}
      </div>
    </div>,
    document.body
  );
}

function smoothJump(e, anchor) {
  e.preventDefault();
  const el = document.querySelector(anchor);
  if (el) {
    window.scrollTo({ top: el.offsetTop - 20, behavior: "smooth" });
    history.replaceState(null, "", anchor);
  }
}

/* Page-turn divider used between major sections.
   When label === "INTERMISSION" it becomes a clickable easter egg that opens
   the Bali photo modal. Other labels render as before. */
function PageTurn({ label = "TURN THE PAGE" }) {
  const [baliOpen, setBaliOpen] = useState(false);
  const isIntermission = label === "INTERMISSION";

  useEffect(() => {
    if (!baliOpen) return;
    const onKey = (e) => { if (e.key === "Escape") setBaliOpen(false); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [baliOpen]);

  if (!isIntermission) {
    return (
      <div className="page-turn" aria-hidden="true">
        <span className="page-turn__mark">&mdash;&nbsp; {label} &nbsp;&mdash;</span>
      </div>);
  }

  return (
    <>
      <button
        type="button"
        className="page-turn page-turn--clickable"
        onClick={() => setBaliOpen(true)}
        aria-label="Intermission — see the Bali trip photos">
        <span className="page-turn__mark">&mdash;&nbsp; {label} &nbsp;&mdash;</span>
        <span className="page-turn__hint">click for a moment off-script &darr;</span>
      </button>
      {baliOpen && <BaliModal onClose={() => setBaliOpen(false)} />}
    </>);
}

/* ============================================================
   BALI EASTER-EGG MODAL — full-screen photo carousel.
   ============================================================ */
/* Photos are auto-discovered: probe uploads/bali-1.jpeg, bali-2.jpeg, ...
   up to BALI_MAX. Whichever load successfully become slides — drop in new
   files and they show up on next page load. Each is rendered full-width. */
const BALI_MAX = 30;

function BaliModal({ onClose }) {
  const [photos, setPhotos] = useState([]);
  const [idx, setIdx] = useState(0);

  /* Discover photos on mount */
  useEffect(() => {
    let cancelled = false;
    function probe(i) {
      return new Promise((resolve) => {
        const img = new Image();
        img.onload  = () => resolve(`uploads/bali-${i}.jpeg`);
        img.onerror = () => resolve(null);
        img.src = `uploads/bali-${i}.jpeg`;
      });
    }
    Promise.all(Array.from({ length: BALI_MAX }, (_, i) => probe(i + 1)))
      .then((results) => {
        if (cancelled) return;
        const found = results.filter(Boolean);
        /* Find the largest contiguous run from bali-1 forward (stop at first gap) */
        const ordered = [];
        for (let i = 1; i <= BALI_MAX; i++) {
          const url = `uploads/bali-${i}.jpeg`;
          if (found.includes(url)) ordered.push(url);
          else if (ordered.length === 0) continue; /* allow missing leading numbers */
          else break; /* stop at first gap after we've started collecting */
        }
        setPhotos(ordered.length ? ordered : found);
      });
    return () => { cancelled = true; };
  }, []);

  /* Arrow keys to navigate */
  useEffect(() => {
    const onKey = (e) => {
      if (!photos.length) return;
      if (e.key === "ArrowRight") setIdx((i) => (i + 1) % photos.length);
      if (e.key === "ArrowLeft")  setIdx((i) => (i - 1 + photos.length) % photos.length);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [photos.length]);

  return ReactDOM.createPortal(
    <div
      className="bali"
      role="dialog"
      aria-modal="true"
      aria-label="Bali trip photos"
      onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <button type="button" className="bali__close" onClick={onClose} aria-label="Close">&times;</button>

      <div className="bali__inner">
        <header className="bali__header">
          <h2 className="bali__title">rest &amp; <em>recharge.</em></h2>
        </header>

        {photos.length > 0 && (
          <div className="bali__photo-wrap is-single">
            <img
              key={photos[idx]}
              className="bali__photo"
              src={photos[idx]}
              alt={`Bali — photo ${idx + 1} of ${photos.length}`} />
          </div>
        )}

        <div className="bali__copy">
          <h3 className="bali__subtitle">Girls trip to explore Bali</h3>
          <p className="bali__deck">
            The space between roles is where perspective happens. Travel and exploration fill the creative well, sharpen how you see problems, and return you with energy and ideas. Balance isn&rsquo;t a luxury&mdash;it&rsquo;s how you sustain excellence. It&rsquo;s how you show up as your best self.
          </p>
        </div>

        {photos.length > 1 && (
          <div className="bali__dots" role="tablist" aria-label="Photo navigation">
            {photos.map((_, i) =>
              <button
                key={i}
                type="button"
                role="tab"
                aria-selected={i === idx}
                aria-label={`Photo ${i + 1}`}
                className={`bali__dot ${i === idx ? "is-active" : ""}`}
                onClick={() => setIdx(i)} />
            )}
          </div>
        )}
      </div>
    </div>,
    document.body
  );
}

/* ============================================================
   BRAIN SKETCH — faint pencil-style anatomical drawing that sits
   behind the "right brain / left brain" toggle. Two hemispheres,
   curving gyri, low opacity so it reads as a margin annotation.
   ============================================================ */
function BrainSketch() {
  return (
    <svg
      className="easter__brain"
      viewBox="0 0 320 200"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
      preserveAspectRatio="xMidYMid meet">
      <g
        fill="none"
        stroke="currentColor"
        strokeLinecap="round"
        strokeLinejoin="round">
        {/* Outer silhouette */}
        <path
          d="M 160 24 Q 96 20 60 64 Q 30 100 50 144 Q 70 174 110 178 Q 130 184 160 180 Q 190 184 210 178 Q 250 174 270 144 Q 290 100 260 64 Q 224 20 160 24 Z"
          strokeWidth="1.4" />
        {/* Brain stem hint at bottom */}
        <path d="M 148 178 Q 152 188 158 192 Q 164 195 172 192 Q 178 188 172 178"
              strokeWidth="1.1" />

        {/* Central longitudinal fissure */}
        <path d="M 160 26 Q 158 60 162 100 Q 158 140 160 178"
              strokeWidth="1.1" opacity="0.75" />

        {/* === LEFT HEMISPHERE GYRI === */}
        <path d="M 84 56 Q 110 70 100 96 Q 90 110 106 130" strokeWidth="0.95" />
        <path d="M 70 84 Q 100 90 92 116 Q 86 132 104 148" strokeWidth="0.85" />
        <path d="M 110 44 Q 134 64 122 88 Q 110 100 128 120" strokeWidth="0.9" />
        <path d="M 56 110 Q 84 118 78 138" strokeWidth="0.8" />
        <path d="M 124 100 Q 144 110 134 138" strokeWidth="0.85" />
        <path d="M 86 152 Q 110 160 130 154" strokeWidth="0.8" />
        <path d="M 130 70 Q 148 84 142 102" strokeWidth="0.8" />

        {/* === RIGHT HEMISPHERE GYRI === */}
        <path d="M 236 56 Q 210 70 220 96 Q 230 110 214 130" strokeWidth="0.95" />
        <path d="M 250 84 Q 220 90 228 116 Q 234 132 216 148" strokeWidth="0.85" />
        <path d="M 210 44 Q 186 64 198 88 Q 210 100 192 120" strokeWidth="0.9" />
        <path d="M 264 110 Q 236 118 242 138" strokeWidth="0.8" />
        <path d="M 196 100 Q 176 110 186 138" strokeWidth="0.85" />
        <path d="M 234 152 Q 210 160 190 154" strokeWidth="0.8" />
        <path d="M 190 70 Q 172 84 178 102" strokeWidth="0.8" />

        {/* A few short pencil-sketch ticks for "hand-drawn" feel */}
        <path d="M 78 70 L 82 74" strokeWidth="0.7" />
        <path d="M 238 70 L 242 74" strokeWidth="0.7" />
        <path d="M 120 152 L 124 156" strokeWidth="0.7" />
        <path d="M 196 152 L 200 156" strokeWidth="0.7" />
      </g>
    </svg>);
}

/* ============================================================
   GRAB TARGET — easter egg. Click the registration crosshair to
   enter "grab mode": cursor becomes a closed-fist emoji, every
   click drops a flower 🌸 wherever you click. Press Escape (or
   click the target again) to release.
   ============================================================ */
const GRAB_FLOWERS  = ["🌸", "🌺", "🌷", "🌼", "🌻", "💐", "🪷", "🪻", "🌹", "🏵️", "🌾"];
const GRAB_WEATHER  = ["⚡", "🌬️", "🌈", "💧", "❄️", "☁️", "☀️", "⛈️", "🌤️", "🌨️", "🌧️"];
const GRAB_ANIMALS  = ["🐶", "🐱", "🐰", "🐻", "🐼", "🦊", "🐨", "🐯", "🦁", "🐮", "🐷", "🐸", "🐵", "🦄", "🐙", "🦋", "🐢", "🦉", "🐧", "🦔", "🦦", "🐝"];

function GrabTarget({ color = "var(--ink)", size = 30, emojis = GRAB_FLOWERS, cursorClass = "is-grabbing" }) {
  const [grabbing, setGrabbing] = useState(false);
  const [flowers, setFlowers] = useState([]);
  const idRef = React.useRef(`grab-${Math.random().toString(36).slice(2)}`);

  /* Only one grab target can be active site-wide. When a new one starts,
     others listen for this event and release themselves. */
  useEffect(() => {
    function onOtherGrabStart(e) {
      if (e.detail !== idRef.current) setGrabbing(false);
    }
    window.addEventListener("vastola.grab.start", onOtherGrabStart);
    return () => window.removeEventListener("vastola.grab.start", onOtherGrabStart);
  }, []);

  useEffect(() => {
    if (!grabbing) return;
    document.body.classList.add(cursorClass);
    /* Announce so any other active grab target steps down */
    window.dispatchEvent(new CustomEvent("vastola.grab.start", { detail: idRef.current }));

    function onKey(e) {
      if (e.key === "Escape") setGrabbing(false);
    }
    function onClick(e) {
      /* Skip clicks on interactive elements so links/buttons keep working */
      if (e.target.closest("a, button, input, textarea, select, [role='button'], [contenteditable]")) return;
      const id = Date.now() + Math.random();
      const rot = (Math.random() - 0.5) * 120;
      const scale = 0.85 + Math.random() * 0.5;
      const emoji = emojis[Math.floor(Math.random() * emojis.length)];
      setFlowers((prev) => [...prev, { id, x: e.clientX, y: e.clientY, rot, scale, emoji }]);
      setTimeout(() => {
        setFlowers((prev) => prev.filter((f) => f.id !== id));
      }, 6000);
    }
    window.addEventListener("keydown", onKey);
    window.addEventListener("click", onClick);
    return () => {
      document.body.classList.remove(cursorClass);
      window.removeEventListener("keydown", onKey);
      window.removeEventListener("click", onClick);
    };
  }, [grabbing, cursorClass, emojis]);

  function handleTargetClick(e) {
    e.stopPropagation();
    setGrabbing((g) => !g);
  }

  return (
    <>
      <span className="grab-target-wrap">
        <button
          type="button"
          className={`grab-target ${grabbing ? "is-active" : ""}`}
          onClick={handleTargetClick}
          aria-label={grabbing ? "Drop flowers anywhere. Press Escape to stop." : "Pick up the target — easter egg"}
          title={grabbing ? "Click anywhere to drop a flower · Esc to release" : "grab me"}>
          <RegistrationMark color={grabbing ? "var(--accent)" : color} size={size} />
        </button>
        {grabbing && (
          <span className="grab-hint" aria-hidden="true">press <em>esc</em> to exit</span>
        )}
      </span>

      {flowers.length > 0 && ReactDOM.createPortal(
        <div className="flower-layer" aria-hidden="true">
          {flowers.map((f) =>
            <span
              key={f.id}
              className="flower-drop"
              style={{ left: `${f.x}px`, top: `${f.y}px` }}>
              <span
                className="flower-drop__inner"
                style={{ transform: `rotate(${f.rot}deg) scale(${f.scale})` }}>
                {f.emoji}
              </span>
            </span>
          )}
        </div>,
        document.body
      )}
    </>);
}

/* ============================================================
   LINKEDIN STAMP — postage-stamp styled link in the cover footer.
   Inline SVG with scalloped edges (computed path), greyscale
   LinkedIn logo inside, and a cancellation postmark overlay that
   gives it the "went through the post office" look.
   ============================================================ */
function LinkedInStamp() {
  /* Build a rectangular path with semicircular indents along each edge */
  const W = 100, H = 120, R = 5;
  const period = 2 * R;
  const top = W / period;     // 10 notches across top/bottom
  const side = H / period;    // 12 notches down each side
  let d = `M 0 0 `;
  for (let i = 0; i < top;  i++) d += `a ${R} ${R} 0 0 1 ${period} 0 `;
  for (let i = 0; i < side; i++) d += `a ${R} ${R} 0 0 1 0 ${period} `;
  for (let i = 0; i < top;  i++) d += `a ${R} ${R} 0 0 1 -${period} 0 `;
  for (let i = 0; i < side; i++) d += `a ${R} ${R} 0 0 1 0 -${period} `;
  d += `Z`;

  return (
    <a
      href="https://www.linkedin.com/in/avastola/"
      target="_blank"
      rel="noopener noreferrer"
      className="li-stamp"
      aria-label="Connect on LinkedIn">
      <svg className="li-stamp__svg" viewBox="-6 -6 112 132" aria-hidden="true">
        {/* The stamp paper — scalloped shape */}
        <path d={d} fill="#ece4cb" stroke="#2a2a2a" strokeWidth="0.6" />

        {/* Inner frame (decorative border inset from the perforation line) */}
        <rect x="6" y="6" width="88" height="108" fill="none" stroke="#2a2a2a" strokeWidth="0.8" />

        {/* LinkedIn logo (greyscale) */}
        <g transform="translate(26, 22)">
          <rect width="48" height="48" rx="3" fill="#2a2a2a" />
          {/* "i" */}
          <circle cx="11" cy="11" r="3.4" fill="#ece4cb" />
          <rect x="7.6" y="17.5" width="6.8" height="22" fill="#ece4cb" />
          {/* "n" — left bar */}
          <rect x="19" y="17.5" width="6.8" height="22" fill="#ece4cb" />
          {/* "n" — bend + right bar */}
          <path d="M 26 22 C 28 17.5 38 17 41 21 C 42.5 23 42.5 26 42.5 28.5 L 42.5 39.5 L 35.8 39.5 L 35.8 26.5 C 35.8 24 31 24 30 26.5 L 30 31 Z" fill="#ece4cb" />
        </g>

        {/* "POSTAGE" text */}
        <text x="50" y="85" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="6"
              letterSpacing="0.18em" fill="#2a2a2a" fontWeight="700">POSTAGE</text>
        <text x="50" y="93" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="4.5"
              letterSpacing="0.22em" fill="#2a2a2a" opacity="0.7">CONNECT · 2026</text>

        {/* Corner ornaments */}
        <g fill="#2a2a2a" opacity="0.55">
          <circle cx="10" cy="10" r="0.9" />
          <circle cx="90" cy="10" r="0.9" />
          <circle cx="10" cy="110" r="0.9" />
          <circle cx="90" cy="110" r="0.9" />
        </g>

        {/* === CANCELLATION POSTMARK — looks like it went through the post office === */}
        <g opacity="0.55" stroke="#1a1a1a" fill="none" strokeLinecap="round">
          {/* Wavy cancellation lines across the upper portion */}
          <path d="M -5 18 Q 15 13 35 18 Q 55 23 75 18 Q 95 13 110 18" strokeWidth="1.2" />
          <path d="M -5 24 Q 15 19 35 24 Q 55 29 75 24 Q 95 19 110 24" strokeWidth="1.2" />
          <path d="M -5 30 Q 15 25 35 30 Q 55 35 75 30 Q 95 25 110 30" strokeWidth="1.2" />
          {/* Partial circular postmark ring */}
          <circle cx="78" cy="72" r="16" strokeWidth="1.3" />
          <circle cx="78" cy="72" r="11" strokeWidth="0.8" />
        </g>
        <g opacity="0.55" fill="#1a1a1a">
          <text x="78" y="68" textAnchor="middle" fontFamily="var(--font-mono)"
                fontSize="3.6" letterSpacing="0.12em" fontWeight="700">DETROIT</text>
          <text x="78" y="73" textAnchor="middle" fontFamily="var(--font-mono)"
                fontSize="2.8" letterSpacing="0.1em">MI &middot; USA</text>
          <text x="78" y="78" textAnchor="middle" fontFamily="var(--font-mono)"
                fontSize="3.2" letterSpacing="0.12em" fontWeight="700">22 MAY 26</text>
        </g>
      </svg>
    </a>);
}

Object.assign(window, {
  Cover, AboutZineModal, PageTurn, smoothJump, BaliModal, BrainSketch, GrabTarget,
  GRAB_FLOWERS, GRAB_WEATHER, GRAB_ANIMALS, LinkedInStamp,
});
