// Section View — opens when a profile is picked. Cinematic "show page".
// Hero banner + rows. Each row renders by its `kind`.

const NOTIFY_QUIPS = [
  "No new notifications. The bell just wanted screen time.",
  "Inbox zero. Even the spam ghosted.",
  "Crickets. Maybe send Batsal a message instead?",
  "Nothing to see here. The bell is doing breathing exercises.",
  "All quiet on the western front. And eastern. And the bell.",
  "Zero unread. The bell is meditating.",
  "Nope. The bell is on its lunch break.",
  "Empty. The bell just likes the attention, honestly.",
  "Nada. Try again after coffee.",
  "Notification void. Batsal is probably designing something.",
  "Silence. The bell is reviewing its life choices.",
];
const MANGA_NOTIFY_QUIPS = [
  "新着なし... 静かなコマです.",
  "通知ゼロ. 静寂のシーン.",
  "鈴は瞑想中. 何もなし.",
  "コマは空白. 鈴も休憩中.",
  "新着ゼロ. 鈴は注目が欲しいだけ.",
];

function SectionView({ section, onBack, onPickAnother }) {
  const { name, tagline, role, color, colorHex, accentInk, rating, runtime, synopsis, badges, avatarSeed, rows } = section;
  const stageRef = React.useRef(null);
  const rowsWrapRef = React.useRef(null);
  const endRef = React.useRef(null);
  const toastTimerRef = React.useRef(null);
  const toastCloseTimerRef = React.useRef(null);
  const toastRef = React.useRef(null);
  const lastQuipIdxRef = React.useRef(-1);
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [toast, setToast] = React.useState(null);
  const [toastClosing, setToastClosing] = React.useState(false);
  const [notificationsSeen, setNotificationsSeen] = React.useState(false);
  const [listed, setListed] = React.useState(() => {
    try {
      const stored = JSON.parse(localStorage.getItem('bns-my-list') || '[]');
      return Array.isArray(stored) && stored.includes(section.id);
    } catch {
      return false;
    }
  });

  // Lock scroll on body while modal open
  React.useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => {
      document.body.style.overflow = '';
      if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
      if (toastCloseTimerRef.current) clearTimeout(toastCloseTimerRef.current);
    };
  }, []);

  // Dismiss toast when clicking anywhere outside it (but not on the bell —
  // re-clicking the bell should replace the toast, not double-fire).
  React.useEffect(() => {
    if (!toast || toastClosing) return;
    const onDown = (e) => {
      if (toastRef.current && toastRef.current.contains(e.target)) return;
      if (e.target.closest && e.target.closest('[data-bell-trigger]')) return;
      dismissToast();
    };
    // Defer one tick so the click that *opened* the toast doesn't immediately close it.
    const attach = setTimeout(() => document.addEventListener('mousedown', onDown), 0);
    return () => {
      clearTimeout(attach);
      document.removeEventListener('mousedown', onDown);
    };
  }, [toast, toastClosing]);

  React.useEffect(() => {
    try {
      const stored = JSON.parse(localStorage.getItem('bns-my-list') || '[]');
      setListed(Array.isArray(stored) && stored.includes(section.id));
    } catch {
      setListed(false);
    }
  }, [section.id]);

  React.useEffect(() => {
    window.bnsMarkVisited?.(section.id);

    const root = stageRef.current;
    const end = endRef.current;
    if (!root || !end || !('IntersectionObserver' in window)) return;

    const observer = new IntersectionObserver((entries) => {
      if (!entries.some((entry) => entry.isIntersecting && entry.intersectionRatio >= 0.7)) return;
      window.bnsCompleteViewing?.(section.id);
      observer.disconnect();
    }, { root, threshold: [0.7] });

    observer.observe(end);
    return () => observer.disconnect();
  }, [section.id]);

  const playEpisode = () => {
    const stage = document.querySelector('.sv-stage');
    const firstRow = rowsWrapRef.current?.querySelector('.row');
    if (!stage || !firstRow) return;
    const top = firstRow.getBoundingClientRect().top + stage.scrollTop - 80;
    stage.scrollTo({ top, behavior: 'smooth' });
    firstRow.classList.remove('is-flash');
    // force reflow before re-adding class so animation replays
    void firstRow.offsetWidth;
    firstRow.classList.add('is-flash');
    setTimeout(() => firstRow.classList.remove('is-flash'), 1400);
  };

  const pickQuip = (pool) => {
    if (!pool || pool.length === 0) return "";
    if (pool.length === 1) return pool[0];
    let idx = Math.floor(Math.random() * pool.length);
    if (idx === lastQuipIdxRef.current) idx = (idx + 1) % pool.length;
    lastQuipIdxRef.current = idx;
    return pool[idx];
  };

  const dismissToast = () => {
    if (toastTimerRef.current) { clearTimeout(toastTimerRef.current); toastTimerRef.current = null; }
    setToastClosing(true);
    if (toastCloseTimerRef.current) clearTimeout(toastCloseTimerRef.current);
    toastCloseTimerRef.current = setTimeout(() => {
      setToast(null);
      setToastClosing(false);
      toastCloseTimerRef.current = null;
    }, 240);
  };

  const showToast = (kind) => {
    const isManga = document.body.classList.contains('theme-manga');
    let message;
    if (kind === 'notify') {
      message = pickQuip(isManga ? MANGA_NOTIFY_QUIPS : NOTIFY_QUIPS);
    } else {
      message = isManga
        ? "リスト入り! 次の章でまた会おう."
        : listed
          ? "Already on My List. The algorithm is nodding approvingly."
          : "Added to My List. The algorithm is now wearing sunglasses.";
    }

    // Cancel any in-flight close so the new toast appears cleanly
    if (toastCloseTimerRef.current) { clearTimeout(toastCloseTimerRef.current); toastCloseTimerRef.current = null; }
    setToastClosing(false);
    setToast({ kind, message, manga: isManga });
    if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
    toastTimerRef.current = setTimeout(() => dismissToast(), 4200);
  };

  const handleMyList = () => {
    try {
      const stored = JSON.parse(localStorage.getItem('bns-my-list') || '[]');
      const current = Array.isArray(stored) ? stored : [];
      const next = current.includes(section.id) ? current : [...current, section.id];
      localStorage.setItem('bns-my-list', JSON.stringify(next));
    } catch {}
    setListed(true);
    showToast('list');
  };

  const handleNotify = () => {
    setNotificationsSeen(true);
    showToast('notify');
  };

  return (
    <div className="sv-stage stage" ref={stageRef} style={{ ['--c']: colorHex, ['--c-ink']: accentInk }}>
      {/* nav bar */}
      <header className="sv-top">
        <button
          type="button"
          className="sv-menu-btn"
          aria-label="Open section menu"
          aria-expanded={menuOpen}
          onClick={() => setMenuOpen((open) => !open)}
        >
          <IconMenu size={18}/>
        </button>
        <button type="button" className="sv-back" onClick={onBack} aria-label="Back to profiles">
          <IconArrowLeft size={16}/> <span className="sv-back-label">Back to profiles</span>
        </button>
        <div className="sv-crumbs">
          <Wordmark size={28} color="var(--paper)"/>
          <span className="sv-crumb-sep">/</span>
          <span className="sv-crumb">{name}</span>
        </div>
        <div className="sv-controls">
          <button type="button" className="sv-control" aria-label="Search" onClick={() => window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }))}>
            <IconSearch size={16}/>
          </button>
          <button type="button" className="sv-control" aria-label="Notifications" data-bell-trigger onClick={handleNotify}>
            <IconBell size={16}/>
            {!notificationsSeen && <span className="sv-control-dot"/>}
          </button>
          <button type="button" className="sv-control sv-control--av" onClick={onPickAnother}>
            <Avatar seed={avatarSeed} color={colorHex} size={32} defaultExpression={section.defaultExpression}/>
          </button>
        </div>
        <div className={`sv-mobile-menu ${menuOpen ? 'is-open' : ''}`}>
          <button type="button" onClick={() => { setMenuOpen(false); window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true })); }}>
            <IconSearch size={15}/> Search
          </button>
          <button type="button" data-bell-trigger onClick={() => { setMenuOpen(false); handleNotify(); }}>
            <IconBell size={15}/> Notifications
          </button>
          <button type="button" onClick={() => { setMenuOpen(false); onPickAnother(); }}>
            <IconReplay size={15}/> Pick another
          </button>
        </div>
      </header>

      {toast && (
        <div
          ref={toastRef}
          className={`sv-toast ${toast.manga ? 'is-manga' : ''} ${toastClosing ? 'is-closing' : ''}`}
          role="status"
          aria-live="polite"
          onClick={dismissToast}
        >
          <div className="sv-toast-icon">
            {toast.kind === 'list' ? <IconCheck size={16}/> : <IconBell size={16}/>}
          </div>
          <div className="sv-toast-copy">{toast.message}</div>
          <button
            type="button"
            className="sv-toast-close"
            aria-label="Dismiss notification"
            onClick={(e) => { e.stopPropagation(); dismissToast(); }}
          >
            <IconClose size={12}/>
          </button>
        </div>
      )}

      {/* HERO */}
      <section className="sv-hero">
        <div className="sv-hero-bg"/>
        <div className="sv-hero-fade"/>
        {/* big floating avatar */}
        <div className="sv-hero-art">
          <Portrait seed={avatarSeed} color={colorHex} size={360} interactive defaultExpression={section.defaultExpression} allowPhoto={section.id === 'about'} />
          {/* sparkle decoration */}
          <div className="sv-hero-sparkles">
            <span style={{top:'10%', left:'-10%'}}>✦</span>
            <span style={{top:'70%', left:'-20%'}}>★</span>
            <span style={{top:'-5%', right:'-5%'}}>✦</span>
            <span style={{bottom:'10%', right:'-15%'}}>✺</span>
          </div>
        </div>

        <div className="sv-hero-text">
          <div className="sv-eyebrow">{role}</div>
          <h1 className="sv-title">{tagline}</h1>
          <div className="sv-meta">
            <Badge tone="paper">★ 9.4</Badge>
            <span className="sv-meta-pip">{rating}</span>
            <span className="sv-meta-pip">{runtime}</span>
            {badges.map(b => <Badge key={b}>{b}</Badge>)}
          </div>
          <p className="sv-synopsis">{synopsis}</p>
          <div className="sv-cta">
            <button type="button" className="sv-btn sv-btn--play" onClick={playEpisode}>
              <IconPlay size={16}/>
              Play Episode {String(section.episodeNum || 1).padStart(2,'0')}
            </button>
            <button type="button" className={`sv-btn sv-btn--ghost ${listed ? 'is-listed' : ''}`} onClick={handleMyList}>
              {listed ? <IconCheck size={16}/> : <IconPlus size={16}/>} {listed ? "Listed" : "My List"}
            </button>
            <button type="button" className="sv-btn sv-btn--ghost" onClick={playEpisode}>
              <IconInfo size={16}/> More info
            </button>
          </div>
        </div>
      </section>

      {/* ROWS */}
      <div className="sv-rows" ref={rowsWrapRef}>
        {rows.map((row, i) => (
          <Row key={i} row={row} section={section} index={i} />
        ))}

        {/* footer card: pick another */}
        <div className="sv-end" ref={endRef}>
          <div className="sv-end-text">Done with this episode?</div>
          <button type="button" className="sv-btn sv-btn--play" onClick={onPickAnother}>
            <span>↺</span> Pick another profile
          </button>
        </div>
      </div>

      <style>{`
        .sv-stage{
          position:fixed; inset:0; z-index:50; overflow-y:auto; overflow-x:hidden;
          background:
            radial-gradient(1200px 800px at 80% -10%, color-mix(in srgb, var(--c) 22%, transparent), transparent 70%),
            linear-gradient(180deg, var(--c-ink) 0%, #04061a 30%, #04061a 100%);
          color:var(--paper);
          animation: svIn .5s cubic-bezier(.2,.9,.3,1) both;
        }
        @keyframes svIn { from { opacity:0; transform: scale(.98); } to { opacity:1; transform: none; } }

        /* Top nav */
        .sv-top{
          position:sticky; top:0; z-index:10;
          display:flex; align-items:center; justify-content:space-between;
          padding: 18px 36px;
          background: linear-gradient(180deg, rgba(4,6,26,.85), rgba(4,6,26,0));
          backdrop-filter: blur(8px);
        }
        .sv-back{
          display:flex; align-items:center; gap:10px; white-space:nowrap;
          font:600 12px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
          color:var(--paper-dim); padding: 10px 16px; border-radius: 99px;
          border:1px solid var(--line);
        }
        .sv-back:hover{ color:var(--paper); border-color:var(--paper); background:rgba(244,241,232,.04); }
        .sv-menu-btn{
          display:none;
          width:42px; height:42px; border-radius:50%;
          align-items:center; justify-content:center;
          background:rgba(244,241,232,.08); border:1px solid var(--line);
          color:var(--paper);
        }
        .sv-crumbs{ display:flex; align-items:center; gap:10px; font:600 13px/1 var(--body); }
        .sv-crumb-sep{ opacity:.4; }
        .sv-crumb{ color:var(--c); }
        .sv-controls{ display:flex; align-items:center; gap:10px; }
        .sv-control{
          position:relative;
          width:36px; height:36px; border-radius:50%; display:flex; align-items:center; justify-content:center;
          background:rgba(244,241,232,.06); border:1px solid var(--line);
          color:var(--paper-dim);
          transition: all .2s ease;
        }
        .sv-control:hover{ background:rgba(244,241,232,.12); color:var(--paper); border-color: var(--paper-dim); }
        .sv-control--av{ padding:0; overflow:hidden; }
        .sv-control--av svg{ width:36px !important; height:36px !important; }
        .sv-control-dot{
          position:absolute; top:7px; right:7px;
          width:8px; height:8px; border-radius:50%;
          background: var(--c); border: 2px solid #04061a;
        }
        .sv-mobile-menu{
          display:none;
        }
        .sv-toast{
          position:fixed; top:82px; right:36px; z-index:90;
          display:flex; align-items:center; gap:12px;
          max-width:min(380px, calc(100vw - 32px));
          padding:12px 12px 12px 14px; border-radius:16px;
          background:rgba(4,6,26,.9); color:var(--paper);
          border:1px solid color-mix(in srgb, var(--c) 48%, var(--line));
          box-shadow:0 18px 48px rgba(0,0,0,.34), inset 0 1px 0 rgba(244,241,232,.08);
          backdrop-filter:blur(16px);
          transform-origin: top right;
          cursor: pointer;
          animation: toastIn .24s cubic-bezier(.2,.9,.3,1) both;
        }
        .sv-toast.is-closing{
          animation: toastOut .22s cubic-bezier(.4,.0,.6,1) both;
          pointer-events: none;
        }
        .sv-toast-close{
          display:grid; place-items:center;
          width:24px; height:24px; flex:0 0 auto;
          border-radius:50%; margin-left:auto;
          color: var(--paper-dim);
          background: transparent;
          transition: background .15s ease, color .15s ease;
        }
        .sv-toast-close:hover{
          background: rgba(244,241,232,.08);
          color: var(--paper);
        }
        .sv-toast-icon{
          width:32px; height:32px; border-radius:50%;
          display:flex; align-items:center; justify-content:center;
          background:var(--c); color:#04061a;
          flex:0 0 auto;
          box-shadow:2px 2px 0 #04061a;
        }
        .sv-toast-copy{
          font:700 13px/1.35 var(--body);
          color:var(--paper);
        }
        .sv-toast.is-manga{
          background:#efe6cc;
          color:#0a0908;
          border:3px solid #0a0908;
          border-radius:4px;
          box-shadow:6px 6px 0 #0a0908;
          backdrop-filter:none;
          transform:rotate(-1deg);
          animation:mangaToastIn .24s cubic-bezier(.2,.9,.3,1) both;
        }
        .sv-toast.is-manga .sv-toast-icon{
          background:#0a0908;
          color:#efe6cc;
          border-radius:3px;
          box-shadow:3px 3px 0 rgba(10,9,8,.18);
        }
        .sv-toast.is-manga .sv-toast-copy{
          color:#0a0908;
          font:800 13px/1.45 var(--mono);
          letter-spacing:.08em;
        }
        .sv-toast.is-manga::after{
          content:"";
          position:absolute;
          right:22px; bottom:-13px;
          width:22px; height:22px;
          background:#efe6cc;
          border-right:3px solid #0a0908;
          border-bottom:3px solid #0a0908;
          transform:rotate(45deg);
        }
        @keyframes toastIn{
          from{ opacity:0; transform:translateY(-8px) scale(.98); }
          to{ opacity:1; transform:none; }
        }
        @keyframes toastOut{
          /* Snap back toward the bell button — top-right + scale down */
          from{ opacity:1; transform:none; }
          to  { opacity:0; transform:translate(28px,-22px) scale(.85); }
        }
        @keyframes mangaToastIn{
          from{ opacity:0; transform:translateY(-8px) scale(.98) rotate(-1deg); }
          to{ opacity:1; transform:rotate(-1deg); }
        }
        .sv-toast.is-manga.is-closing{
          animation: mangaToastOut .22s cubic-bezier(.4,.0,.6,1) both;
        }
        @keyframes mangaToastOut{
          from{ opacity:1; transform:rotate(-1deg); }
          to  { opacity:0; transform:translate(28px,-22px) scale(.85) rotate(-3deg); }
        }

        /* Hero */
        .sv-hero{
          position:relative; min-height: 78vh; padding: 40px 56px 60px;
          display:grid; grid-template-columns: 1.3fr .9fr; gap: 40px; align-items:center;
          overflow:hidden;
        }
        @media (max-width: 900px){ .sv-hero{ grid-template-columns: 1fr; padding: 20px 24px 40px; } }

        .sv-hero-bg{
          position:absolute; inset:-10% -10% 0 -10%; pointer-events:none; z-index:0;
          background:
            radial-gradient(600px 600px at 70% 50%, color-mix(in srgb, var(--c) 14%, transparent), transparent 60%);
          mix-blend-mode: screen;
        }
        .sv-hero-fade{
          position:absolute; left:0; right:0; bottom:0; height:140px;
          background: linear-gradient(180deg, transparent, #04061a);
          pointer-events:none; z-index:1;
        }

        .sv-hero-text{ position:relative; z-index:2; max-width:640px;
          animation: heroIn .7s cubic-bezier(.2,.9,.3,1) .12s both; }
        @keyframes heroIn { from{ opacity:0; transform: translateX(-20px); } to{ opacity:1; transform:none; } }

        .sv-eyebrow{
          font:600 11px/1 var(--mono); letter-spacing:.36em; color:var(--c); margin-bottom:18px;
        }
        .sv-title{
          font:400 clamp(56px, 7.5vw, 112px)/.95 var(--display);
          margin:0 0 24px; letter-spacing:-.01em;
          text-shadow: 5px 6px 0 #000;
          color: var(--paper);
        }

        .sv-meta{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom: 22px; }
        .sv-meta-pip{
          font: 600 11px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
          color: var(--paper-dim);
        }

        .sv-synopsis{
          font:500 17px/1.55 var(--body); color:var(--paper-dim); margin: 0 0 28px;
          max-width: 540px;
        }

        .sv-cta{ display:flex; flex-wrap:wrap; gap:10px; }
        .sv-btn{
          display:inline-flex; align-items:center; gap:10px; white-space:nowrap;
          font:600 13px/1 var(--body); letter-spacing:.02em;
          padding: 14px 20px; border-radius: 99px;
          transition: all .2s ease;
        }
        .sv-btn--play{
          background: var(--paper); color:#04061a;
          box-shadow: 4px 4px 0 var(--c);
        }
        .sv-btn--play:hover{ transform: translate(-1px, -1px); box-shadow: 5px 5px 0 var(--c); }
        .sv-btn--ghost{
          background: rgba(244,241,232,.08); color: var(--paper); border:1px solid var(--line);
        }
        .sv-btn--ghost:hover{ background: rgba(244,241,232,.18); border-color: var(--paper-dim); }
        .sv-btn--ghost.is-listed{
          border-color:var(--c);
          color:var(--c);
          background:color-mix(in srgb, var(--c) 12%, rgba(244,241,232,.08));
        }

        .sv-hero-art{
          position:relative; z-index:2; display:flex; justify-content:center;
          animation: artIn .8s cubic-bezier(.3,1.4,.3,1) .2s both;
        }
        @keyframes artIn { from { opacity:0; transform: scale(.6) rotate(-8deg); } to { opacity:1; transform: none; } }
        .sv-hero-art > svg{ filter: drop-shadow(8px 12px 0 #04061a) drop-shadow(0 30px 60px color-mix(in srgb, var(--c) 40%, transparent)); }

        .sv-hero-sparkles{ position:absolute; inset:0; pointer-events:none; }
        .sv-hero-sparkles span{
          position:absolute; color:var(--c); font-size:32px; opacity:.7;
          animation: spinSp 5s ease-in-out infinite;
        }
        .sv-hero-sparkles span:nth-child(2){ animation-delay:.6s; font-size:24px; color:var(--paper); }
        .sv-hero-sparkles span:nth-child(3){ animation-delay:1.2s; font-size:28px; }
        .sv-hero-sparkles span:nth-child(4){ animation-delay:1.8s; font-size:20px; }
        @keyframes spinSp {
          0%,100% { transform: scale(1) rotate(0); }
          50%     { transform: scale(1.3) rotate(180deg); opacity:1; }
        }

        /* Rows section */
        .sv-rows{ padding: 30px 0 80px; display:flex; flex-direction:column; gap:48px; }

        /* End block */
        .sv-end{
          margin: 40px 56px 0; padding: 28px 36px;
          display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
          border:1px dashed var(--line); border-radius:24px;
          background: linear-gradient(135deg, color-mix(in srgb, var(--c) 14%, transparent), transparent);
        }
        .sv-end-text{ font:600 16px/1.3 var(--body); color: var(--paper); }
        @media (max-width: 900px){ .sv-end{ margin: 24px 24px 0; } }
        @media (max-width: 720px){
          .sv-top{
            display:grid; grid-template-columns:42px minmax(0,1fr) 42px;
            align-items:center;
            padding:12px 14px;
            gap:10px;
            background:linear-gradient(180deg, rgba(4,6,26,.92), rgba(4,6,26,.36));
          }
          .sv-controls{ display:none; }
          .sv-menu-btn{ display:flex; grid-column:3; grid-row:1; justify-self:end; }
          .sv-back{
            display:flex; grid-column:1; grid-row:1; justify-self:start;
            width:42px; height:42px; padding:0; gap:0; border-radius:50%;
            align-items:center; justify-content:center;
          }
          .sv-back-label{ display:none; }
          .sv-crumbs{
            grid-column:2; grid-row:1; justify-content:center; min-width:0; gap:8px;
          }
          .sv-crumbs .bns-mark{ font-size:34px; text-shadow:3px 3px 0 #000; }
          .sv-crumb{
            min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
            font:700 13px/1 var(--body);
          }
          .sv-mobile-menu{
            display:flex; position:absolute; top:62px; left:14px; right:14px;
            flex-direction:column; gap:8px;
            padding:10px; border-radius:16px;
            background:rgba(4,6,26,.94);
            border:1px solid var(--line);
            box-shadow:0 18px 50px rgba(0,0,0,.38);
            backdrop-filter:blur(16px);
            opacity:0; transform:translateY(-8px);
            pointer-events:none;
            transition:opacity .18s ease, transform .18s ease;
          }
          .sv-mobile-menu.is-open{
            opacity:1; transform:translateY(0); pointer-events:auto;
          }
          .sv-mobile-menu button{
            display:flex; align-items:center; gap:10px;
            min-height:42px; padding:0 12px; border-radius:12px;
            color:var(--paper); background:rgba(244,241,232,.06);
            border:1px solid rgba(244,241,232,.08);
            font:700 12px/1 var(--mono); letter-spacing:.12em; text-transform:uppercase;
          }
          .sv-toast{
            top:68px; left:14px; right:14px;
            max-width:none;
          }
        }
      `}</style>
    </div>
  );
}

// ─── Row component dispatches by kind ───────────────────────────────────
function Row({ row, section, index }) {
  const k = row.kind || "cards";
  const itemCount = (row.items || []).length;
  const rowMeta = row.meta || `${itemCount} item${itemCount !== 1 ? "s" : ""}`;

  return (
    <div className="row" style={{ animationDelay: `${0.3 + index*0.08}s` }}>
      <div className="row-head">
        <h3 className="row-title">{row.title}</h3>
        <div className="row-meta">{rowMeta}</div>
      </div>

      {k === "hero" && <HeroRow row={row} section={section}/>}
      {k === "cards" && <CardsRow row={row} section={section}/>}
      {k === "brands" && <BrandCreditsRow row={row} section={section}/>}
      {k === "stats" && <StatsRow row={row} section={section}/>}
      {k === "skillChips" && <ChipsRow row={row} section={section}/>}
      {k === "timeline" && <TimelineRow row={row} section={section}/>}
      {k === "channels" && <ChannelsRow row={row} section={section}/>}
      {k === "form" && <FormRow row={row} section={section}/>}
      {k === "downloads" && <DownloadsRow row={row} section={section}/>}
      {k === "resumeHi" && <ResumeHighlights row={row} section={section}/>}
      {k === "logoWall" && <LogoWallRow row={row} section={section}/>}
      {k === "projects" && <ProjectsRow row={row} section={section}/>}
      {k === "currently" && <CurrentlyRow row={row} section={section}/>}

      <style>{`
        .row{ padding: 0 56px; opacity:0; animation: rowIn .55s cubic-bezier(.2,.9,.3,1) both; }
        @media (max-width:900px){ .row{ padding: 0 24px; } }
        @keyframes rowIn { from { opacity:0; transform: translateY(20px); } to { opacity:1; transform: none; } }
        .row.is-flash{ animation: rowIn .55s cubic-bezier(.2,.9,.3,1) both, rowFlash 1.4s ease-out; }
        @keyframes rowFlash {
          0%   { box-shadow: 0 0 0 0 var(--c), inset 0 0 0 0 color-mix(in srgb, var(--c) 30%, transparent); border-radius:18px; }
          15%  { box-shadow: 0 0 30px 4px var(--c), inset 0 0 0 60px color-mix(in srgb, var(--c) 14%, transparent); }
          100% { box-shadow: 0 0 0 0 transparent, inset 0 0 0 0 transparent; }
        }
        .row-head{ display:flex; align-items:baseline; justify-content:space-between; margin-bottom: 18px; }
        .row-title{
          font: 700 22px/1 var(--body); letter-spacing:-.01em; color: var(--paper); margin:0;
        }
        .row-title::before{
          content:""; display:inline-block; width:6px; height:22px; border-radius:3px;
          background:var(--c); margin-right:12px; vertical-align: -3px;
        }
        .row-meta{ font: 500 11px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase; color: var(--paper-faint); }
      `}</style>
    </div>
  );
}

// ─── HeroRow: a single big "featured" card ──────────────────────────────
function HeroRow({ row, section }) {
  const it = row.items[0];
  return (
    <div className="hero-row">
      <div className="hero-row-card">
        <div className="hero-row-text">
          <div className="hero-row-tag">
            <span className="hero-row-dot" aria-hidden="true"/>
            {it.tag}
          </div>
          <h2 className="hero-row-title">{it.title}</h2>
          <p className="hero-row-sub">{it.sub}</p>
          {it.stat && <div className="hero-row-stat">{it.stat}</div>}
        </div>
        <div className="hero-row-art">
          <div className="hero-row-halo" aria-hidden="true"/>
          <Portrait seed={section.avatarSeed} color={section.colorHex} size={132} defaultExpression={section.defaultExpression} allowPhoto={section.id === 'about'}/>
        </div>
      </div>
      <style>{`
        .hero-row-card{
          position:relative; padding: 22px 26px; border-radius: 20px;
          background:
            linear-gradient(135deg, color-mix(in srgb, var(--c) 18%, transparent), rgba(244,241,232,.04));
          border:1px solid var(--line);
          overflow:hidden;
          display:flex; gap: 24px; align-items:center;
        }
        @media (max-width:700px){
          .hero-row-card{ flex-direction: column-reverse; padding: 20px 22px; gap: 16px; }
        }
        .hero-row-text{
          flex: 1 1 auto; min-width: 0;
          display:flex; flex-direction:column; gap: 10px;
        }
        .hero-row-tag{
          display:inline-flex; align-items:center; gap:8px;
          font:700 10px/1 var(--mono); letter-spacing:.3em; color: var(--c);
          text-transform:uppercase;
        }
        .hero-row-dot{
          display:block; width:7px; height:7px; border-radius:50%;
          background: var(--c);
          box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 28%, transparent);
          animation: hr-pulse 1.6s ease-in-out infinite;
        }
        @keyframes hr-pulse{
          0%,100%{ opacity:.55; transform:scale(.85); }
          50%    { opacity:1;   transform:scale(1); }
        }
        .hero-row-title{
          font: 700 26px/1.15 var(--body); letter-spacing:-.015em; margin: 0;
        }
        .hero-row-sub{
          font: 500 14px/1.55 var(--body); color: var(--paper-dim); margin: 0;
          max-width: 60ch;
        }
        .hero-row-stat{
          margin-top: 6px; align-self:flex-start;
          font: 400 26px/1 var(--display); color: var(--c);
          padding: 7px 12px; border-radius: 10px;
          background: #04061a; border: 2px solid var(--c);
          text-shadow: 2px 2px 0 #000;
        }
        .hero-row-art{
          flex: 0 0 auto;
          position: relative;
          width: 152px; height: 152px;
          display:flex; align-items:center; justify-content:center;
        }
        .hero-row-art > svg{ filter: drop-shadow(4px 6px 0 #04061a); position:relative; z-index:1; }
        .hero-row-halo{
          position:absolute; inset:-10px;
          border-radius:50%;
          background: radial-gradient(circle at center, color-mix(in srgb, var(--c) 26%, transparent), transparent 70%);
          z-index:0;
        }
        @media (max-width:700px){
          .hero-row-title{ font-size: 22px; }
          .hero-row-sub{ font-size: 13px; }
          .hero-row-art{ width: 116px; height: 116px; }
        }
      `}</style>
    </div>
  );
}

// ─── CardsRow: horizontal scrolling cards ───────────────────────────────
function CardsRow({ row, section }) {
  const trackRef = React.useRef(null);
  const [open, setOpen] = React.useState(null);
  const scroll = (dir) => {
    const t = trackRef.current; if (!t) return;
    t.scrollBy({ left: dir * 360, behavior: 'smooth' });
  };
  const iconFor = (key) => ({
    mountain: IconMountain, rocket: IconRocket, code: IconCode,
    bolt: IconBolt, sparkle: IconSparkle, star: IconStar, heart: IconHeart,
  })[key];

  return (
    <div className="cr">
      <button type="button" className="cr-arrow cr-arrow--l" onClick={()=>scroll(-1)} aria-label="Scroll left"><IconChevronLeft size={20}/></button>
      <button type="button" className="cr-arrow cr-arrow--r" onClick={()=>scroll(1)} aria-label="Scroll right"><IconChevronRight size={20}/></button>
      <div className="cr-track" ref={trackRef}>
        {row.items.map((it, i) => {
          const Ico = iconFor(it.icon);
          const expandable = !!it.details;
          return (
            <button
              type="button"
              key={i}
              className={`cr-card ${expandable ? 'is-expandable' : ''} ${open === i ? 'is-open' : ''}`}
              style={{['--c']: section.colorHex}}
              onClick={() => expandable && setOpen(open === i ? null : i)}
              aria-expanded={expandable ? open === i : undefined}
            >
              <div className="cr-card-thumb">
                <div className="cr-card-num">EP {String(i+1).padStart(2,'0')}</div>
                <div className="cr-card-icon">
                  {Ico ? <Ico size={56}/> : <span>{it.icon || '●'}</span>}
                </div>
                {it.stat && <div className="cr-card-stat">{it.stat}</div>}
              </div>
              <div className="cr-card-body">
                <div className="cr-card-title-row">
                  <div className="cr-card-title">{it.title}</div>
                  {expandable && <span className="cr-card-toggle" aria-hidden="true">{open === i ? "−" : "+"}</span>}
                </div>
                <div className="cr-card-sub">{it.sub}</div>
                {expandable && <div className="cr-card-details">{it.details}</div>}
              </div>
            </button>
          );
        })}
      </div>
      <style>{`
        .cr{ position:relative; }
        .cr-track{
          display:flex; gap:18px; overflow-x:auto; padding: 6px 6px 16px;
          scroll-snap-type: x mandatory; scrollbar-width:none;
        }
        .cr-track::-webkit-scrollbar{ display:none; }
        .cr-card{
          flex: 0 0 280px; scroll-snap-align:start;
          border-radius: 16px; overflow:hidden;
          background: rgba(244,241,232,.04); border:1px solid var(--line);
          text-align:left;
          transition:
            flex-basis .25s cubic-bezier(.2,.9,.3,1),
            transform .25s cubic-bezier(.3,1.4,.3,1),
            border-color .2s ease,
            background .2s ease;
          cursor:default;
        }
        .cr-card.is-expandable{ cursor:pointer; }
        .cr-card.is-open{
          flex-basis:360px;
          border-color:var(--c);
          background:rgba(244,241,232,.07);
        }
        .cr-card:hover{ transform: translateY(-6px) scale(1.02); border-color: var(--c); }
        .cr-card-thumb{
          height: 160px; position:relative;
          background: linear-gradient(135deg, color-mix(in srgb, var(--c) 26%, #04061a), #04061a);
          display:flex; align-items:center; justify-content:center;
        }
        .cr-card-num{
          position:absolute; top:12px; left:12px;
          font:700 10px/1 var(--mono); letter-spacing:.18em; color:var(--paper);
          padding: 4px 8px; border-radius: 4px; background:rgba(4,6,26,.6);
        }
        .cr-card-icon{
          font: 400 64px/1 var(--display); color: var(--paper);
          text-shadow: 3px 3px 0 #04061a;
          display:flex; align-items:center; justify-content:center;
        }
        .cr-card-icon svg{ filter: drop-shadow(3px 3px 0 #04061a); }
        .cr-card-stat{
          position:absolute; bottom:12px; right:12px;
          font: 600 12px/1 var(--mono); color: var(--c);
          padding: 5px 9px; border-radius:99px; background:#04061a; border:1px solid var(--c);
        }
        .cr-card-body{ padding: 14px 16px; }
        .cr-card-title-row{ display:flex; align-items:center; gap:10px; margin-bottom:4px; }
        .cr-card-title{ font:600 16px/1.2 var(--body); }
        .cr-card-toggle{
          display:grid; place-items:center;
          width:18px; height:18px; margin-left:auto; border-radius:50%;
          border:1px solid color-mix(in srgb, var(--c) 55%, transparent);
          color:var(--c); font:700 13px/1 var(--mono);
          flex:0 0 auto;
        }
        .cr-card-sub{ font: 500 12px/1.4 var(--body); color: var(--paper-dim); }
        .cr-card-details{
          max-height:0; opacity:0; transform:translateY(-4px);
          overflow:hidden;
          font:500 13px/1.45 var(--body);
          color:var(--paper-dim);
          transition:max-height .25s ease, opacity .2s ease, transform .2s ease, margin-top .2s ease;
        }
        .cr-card.is-open .cr-card-details{
          max-height:120px; opacity:1; transform:none; margin-top:12px;
        }

        .cr-arrow{
          position:absolute; top:50%; transform: translateY(-50%); z-index:5;
          width:42px; height:42px; border-radius:50%;
          background: var(--paper); color:#04061a;
          display:flex; align-items:center; justify-content:center;
          box-shadow: 0 6px 14px rgba(0,0,0,.4); opacity:0; transition: opacity .2s ease;
        }
        .cr:hover .cr-arrow{ opacity:1; }
        .cr-arrow--l{ left:-12px; } .cr-arrow--r{ right:-12px; }
      `}</style>
    </div>
  );
}

// ─── BrandCreditsRow: worked-with poster carousel ───────────────────────
function BrandCreditsRow({ row, section }) {
  const trackRef = React.useRef(null);
  const scroll = (dir) => {
    const t = trackRef.current; if (!t) return;
    t.scrollBy({ left: dir * 380, behavior: 'smooth' });
  };

  return (
    <div className="bc">
      <button type="button" className="bc-arrow bc-arrow--l" onClick={()=>scroll(-1)} aria-label="Scroll brand credits left"><IconChevronLeft size={20}/></button>
      <button type="button" className="bc-arrow bc-arrow--r" onClick={()=>scroll(1)} aria-label="Scroll brand credits right"><IconChevronRight size={20}/></button>
      <div className="bc-track" ref={trackRef}>
        {row.items.map((it, i) => (
          <article key={i} className={`bc-card ${it.confidential ? 'is-confidential' : ''}`} style={{['--c']: section.colorHex}}>
            <div className="bc-poster">
              <div className="bc-industry">{it.industry}</div>
              <div className="bc-logo" aria-hidden="true">{it.logo}</div>
              {it.confidential && <div className="bc-lock">Confidential</div>}
            </div>
            <div className="bc-body">
              <div className="bc-name">{it.name}</div>
              <p className="bc-work">{it.work}</p>
              <div className="bc-result">{it.result}</div>
              <div className="bc-badges">
                {(it.badges || []).map((b) => <span key={b}>{b}</span>)}
              </div>
            </div>
          </article>
        ))}
      </div>
      <style>{`
        .bc{ position:relative; }
        .bc-track{
          display:flex; gap:18px; overflow-x:auto; padding: 6px 6px 18px;
          scroll-snap-type:x mandatory; scrollbar-width:none;
        }
        .bc-track::-webkit-scrollbar{ display:none; }
        .bc-card{
          flex:0 0 330px; scroll-snap-align:start;
          border-radius:18px; overflow:hidden;
          background:rgba(244,241,232,.045);
          border:1px solid var(--line);
          transition:transform .25s cubic-bezier(.3,1.4,.3,1), border-color .2s ease, background .2s ease;
        }
        .bc-card:hover{
          transform:translateY(-6px);
          border-color:var(--c);
          background:rgba(244,241,232,.07);
        }
        .bc-poster{
          position:relative; height:178px; overflow:hidden;
          display:flex; align-items:center; justify-content:center;
          background:
            radial-gradient(circle at 70% 20%, color-mix(in srgb, var(--c) 32%, transparent), transparent 42%),
            linear-gradient(135deg, color-mix(in srgb, var(--c) 24%, #04061a), #04061a 70%);
        }
        .bc-poster::after{
          content:""; position:absolute; inset:0; pointer-events:none;
          background:
            linear-gradient(90deg, rgba(244,241,232,.08) 1px, transparent 1px),
            linear-gradient(180deg, rgba(244,241,232,.08) 1px, transparent 1px);
          background-size:28px 28px;
          opacity:.14;
        }
        .bc-industry{
          position:absolute; top:12px; left:12px; z-index:1;
          font:700 10px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
          color:var(--paper);
          padding:5px 8px; border-radius:6px;
          background:rgba(4,6,26,.62); border:1px solid rgba(244,241,232,.12);
          backdrop-filter:blur(6px);
        }
        .bc-logo{
          position:relative; z-index:1;
          width:92px; height:92px; border-radius:24px;
          display:grid; place-items:center;
          background:var(--paper); color:#04061a;
          font:800 30px/1 var(--body); letter-spacing:-.06em;
          box-shadow:7px 7px 0 #04061a, 0 20px 50px color-mix(in srgb, var(--c) 26%, transparent);
          transform:rotate(-3deg);
        }
        .bc-lock{
          position:absolute; right:12px; bottom:12px; z-index:1;
          font:700 10px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
          color:#04061a; background:var(--c);
          padding:6px 9px; border-radius:99px;
          box-shadow:2px 2px 0 #04061a;
        }
        .bc-body{ padding:16px 16px 18px; }
        .bc-name{
          font:700 18px/1.15 var(--body); color:var(--paper);
          letter-spacing:-.01em; margin-bottom:8px;
        }
        .bc-work{
          min-height:62px; margin:0 0 14px;
          font:500 13px/1.45 var(--body); color:var(--paper-dim);
        }
        .bc-result{
          display:inline-flex; align-items:center;
          min-height:28px; padding:0 10px; margin-bottom:12px;
          border-radius:99px; background:#04061a; border:1px solid var(--c);
          color:var(--c); font:800 12px/1 var(--mono); letter-spacing:.08em;
          text-transform:uppercase;
        }
        .bc-badges{ display:flex; flex-wrap:wrap; gap:6px; }
        .bc-badges span{
          font:700 10px/1 var(--mono); letter-spacing:.12em; text-transform:uppercase;
          color:var(--paper-dim);
          padding:6px 8px; border-radius:99px;
          background:rgba(244,241,232,.06); border:1px solid var(--line);
        }
        .bc-card.is-confidential .bc-logo{
          background:linear-gradient(135deg, var(--paper), color-mix(in srgb, var(--c) 22%, var(--paper)));
        }
        .bc-arrow{
          position:absolute; top:50%; transform:translateY(-50%); z-index:5;
          width:42px; height:42px; border-radius:50%;
          background:var(--paper); color:#04061a;
          display:flex; align-items:center; justify-content:center;
          box-shadow:0 6px 14px rgba(0,0,0,.4); opacity:0; transition:opacity .2s ease;
        }
        .bc:hover .bc-arrow{ opacity:1; }
        .bc-arrow--l{ left:-12px; }
        .bc-arrow--r{ right:-12px; }
        @media (max-width:720px){
          .bc-card{ flex-basis:282px; }
          .bc-work{ min-height:auto; }
        }
      `}</style>
    </div>
  );
}

// ─── StatsRow: animated bars ────────────────────────────────────────────
function StatsRow({ row, section }) {
  return (
    <div className="stats-row">
      {row.items.map((it,i)=>(
        <div key={i} className="stat-row">
          <div className="stat-row-label">{it.title}</div>
          <Pct value={it.value} color={section.colorHex}/>
        </div>
      ))}
      <style>{`
        .stats-row{ display:grid; grid-template-columns: 1fr 1fr; gap: 12px 32px; padding: 8px 0; }
        @media (max-width:700px){ .stats-row{ grid-template-columns: 1fr; } }
        .stat-row{ display:flex; align-items:center; gap: 16px; padding: 14px 18px; border-radius:14px; background: rgba(244,241,232,.03); border:1px solid var(--line); }
        .stat-row-label{ font: 600 14px/1.2 var(--body); flex:1; min-width:0; }
        /* numbers align in a column on the right; the bar isn't used in this row */
        .stats-row .bns-pct{ flex:0 0 auto; }
        .stats-row .bns-pct-bar{ display:none; }
      `}</style>
    </div>
  );
}

// ─── ChipsRow: skill chips ──────────────────────────────────────────────
function ChipsRow({ row, section }) {
  const [open, setOpen] = React.useState(null);

  return (
    <div className="chips-row">
      {row.items.map((it,i)=>(
        <button
          type="button"
          key={i}
          className={`chip ${open === i ? 'is-open' : ''}`}
          onClick={() => setOpen(open === i ? null : i)}
          aria-expanded={open === i}
        >
          <div className="chip-bar" style={{ width: '100%', background: section.colorHex }}/>
          <div className="chip-top">
            <span className="chip-name">{it.title}</span>
            <span className="chip-toggle" aria-hidden="true">{open === i ? "−" : "+"}</span>
          </div>
          <div className="chip-desc">{it.desc}</div>
        </button>
      ))}
      <style>{`
        .chips-row{ display:flex; flex-wrap:wrap; align-items:flex-start; gap: 10px; }
        .chip{
          position:relative; padding: 10px 16px; border-radius: 99px;
          background: rgba(244,241,232,.06); border:1px solid var(--line);
          display:flex; flex-direction:column; align-items:stretch; gap: 0;
          min-height:42px; max-width:min(420px, 100%);
          overflow:hidden; text-align:left;
          cursor:pointer;
          transition:
            flex-basis .25s cubic-bezier(.2,.9,.3,1),
            border-radius .2s ease,
            background .2s ease,
            transform .2s ease,
            border-color .2s ease;
        }
        .chip:hover{ transform: translateY(-2px); border-color: var(--c); background: rgba(244,241,232,.08); }
        .chip:focus-visible{ outline:2px solid var(--c); outline-offset:4px; }
        .chip.is-open{
          flex: 1 1 360px;
          border-radius: 18px;
          border-color: var(--c);
          background: linear-gradient(135deg, color-mix(in srgb, var(--c) 12%, transparent), rgba(244,241,232,.06));
        }
        .chip-bar{ position:absolute; left:0; top:0; bottom:0; opacity:.26; pointer-events:none; }
        .chip-top{
          position:relative;
          display:flex; align-items:center; gap:12px;
        }
        .chip-name{ font: 600 14px/1 var(--body); color:var(--paper); }
        .chip-toggle{
          display:grid; place-items:center; margin-left:auto;
          width:18px; height:18px; border-radius:50%;
          border:1px solid color-mix(in srgb, var(--c) 55%, transparent);
          color:var(--c); font:700 13px/1 var(--mono);
        }
        .chip-desc{
          position:relative;
          max-height:0; opacity:0; transform:translateY(-4px);
          overflow:hidden;
          font:500 13px/1.45 var(--body);
          color:var(--paper-dim);
          transition:max-height .25s ease, opacity .2s ease, transform .2s ease, margin-top .2s ease;
        }
        .chip.is-open .chip-desc{
          max-height:90px; opacity:1; transform:none; margin-top:10px;
        }
        @media (max-width: 640px){
          .chip, .chip.is-open{ flex:1 1 100%; }
        }
      `}</style>
    </div>
  );
}

// ─── TimelineRow: chronological cards ───────────────────────────────────
function TimelineRow({ row, section }) {
  const [open, setOpen] = React.useState(null);

  return (
    <div className="tl">
      <div className="tl-spine"/>
      {row.items.map((it,i)=>{
        const roles = it.roles && it.roles.length ? it.roles : null;
        const isOpen = open === i;
        return (
          <div key={i} className="tl-item">
            <div className="tl-marker"><span/></div>
            <button
              type="button"
              className={`tl-content ${isOpen ? 'is-open' : ''}`}
              onClick={() => setOpen(isOpen ? null : i)}
              aria-expanded={isOpen}
            >
              <div className="tl-era">{it.era}{it.duration ? ` · ${it.duration}` : ''}</div>
              <div className="tl-title-row">
                <h4 className="tl-title">{roles ? it.company : it.title}</h4>
                <span className="tl-toggle" aria-hidden="true">{isOpen ? "−" : "+"}</span>
              </div>
              <div className="tl-meta">
                {roles && it.employmentType && <span className="tl-meta-bit">{it.employmentType}</span>}
                {it.location && <span className="tl-meta-bit">{it.location}</span>}
                {!roles && it.company && <span className="tl-meta-bit">{it.company}</span>}
                {roles && <span className="tl-meta-bit">{roles.length} role{roles.length>1?'s':''}</span>}
              </div>

              {/* Expandable body */}
              <div className="tl-body">
                {roles ? (
                  <ul className="tl-roles">
                    {roles.map((r, j) => (
                      <li key={j} className="tl-role">
                        <div className="tl-role-bullet" aria-hidden="true"/>
                        <div className="tl-role-main">
                          <div className="tl-role-title">{r.title}</div>
                          <div className="tl-role-era">
                            {r.era}{r.duration ? ` · ${r.duration}` : ''}
                          </div>
                          {r.bullets && r.bullets.length > 0 && (
                            <ul className="tl-role-list">
                              {r.bullets.map((b, k) => <li key={k}>{b}</li>)}
                            </ul>
                          )}
                        </div>
                      </li>
                    ))}
                  </ul>
                ) : (
                  <ul className="tl-list">
                    {(it.bullets || []).map((b,j)=><li key={j}>{b}</li>)}
                  </ul>
                )}
              </div>
            </button>
          </div>
        );
      })}
      <style>{`
        .tl{ position:relative; padding-left: 36px; }
        .tl-spine{ position:absolute; left:14px; top:8px; bottom:8px; width:2px; background: linear-gradient(180deg, var(--c), transparent); }
        .tl-item{ position:relative; margin-bottom: 24px; }
        .tl-item:last-child{ margin-bottom: 0; }
        .tl-marker{
          position:absolute; left:-36px; top: 6px;
          width: 30px; height:30px; border-radius:50%;
          background:#04061a; border: 3px solid var(--c);
          display:flex; align-items:center; justify-content:center;
        }
        .tl-marker span{ width:8px; height:8px; border-radius:50%; background: var(--c); }
        .tl-content{
          display:block; width:100%; text-align:left;
          padding: 18px 22px; border-radius:16px;
          background: rgba(244,241,232,.04); border:1px solid var(--line);
          cursor:pointer;
          transition:border-color .2s ease, background .2s ease, transform .2s ease;
        }
        .tl-content:hover{ border-color:var(--c); background:rgba(244,241,232,.06); transform:translateY(-2px); }
        .tl-content:focus-visible{ outline:2px solid var(--c); outline-offset:4px; }
        .tl-content.is-open{
          border-color:var(--c);
          background:linear-gradient(135deg, color-mix(in srgb, var(--c) 14%, transparent), rgba(244,241,232,.04));
        }
        .tl-era{
          font: 700 11px/1 var(--mono); letter-spacing:.2em; color: var(--c); margin-bottom: 8px; text-transform:uppercase;
        }
        .tl-title-row{ display:flex; align-items:flex-start; gap:12px; }
        .tl-title{ font: 700 20px/1.2 var(--body); margin: 0 0 4px; }
        .tl-toggle{
          display:grid; place-items:center;
          width:22px; height:22px; margin-left:auto; border-radius:50%;
          border:1px solid color-mix(in srgb, var(--c) 55%, transparent);
          color:var(--c); font:700 14px/1 var(--mono);
          flex:0 0 auto;
        }
        .tl-meta{
          display:flex; flex-wrap:wrap; gap: 6px 14px;
          font: 500 13px/1.2 var(--body); color: var(--paper-dim);
        }
        .tl-meta-bit{ position:relative; }
        .tl-meta-bit + .tl-meta-bit::before{
          content:"·"; margin-right:14px; margin-left:-8px; color: var(--paper-faint);
        }
        .tl-body{
          max-height:0; opacity:0; transform:translateY(-4px);
          overflow:hidden;
          transition:max-height .3s ease, opacity .22s ease, transform .22s ease, margin-top .22s ease;
        }
        .tl-content.is-open .tl-body{
          max-height: 720px; opacity:1; transform:none; margin-top: 14px;
        }
        .tl-list{
          margin: 0; padding-left: 18px;
          color: var(--paper-dim); font: 500 14px/1.6 var(--body);
        }

        /* LinkedIn-style nested role list */
        .tl-roles{
          list-style:none; margin:0; padding:0;
          position:relative;
        }
        .tl-roles::before{
          content:""; position:absolute;
          left: 5px; top: 8px; bottom: 8px;
          width: 1.5px;
          background: color-mix(in srgb, var(--c) 35%, transparent);
        }
        .tl-role{
          position:relative;
          padding: 4px 0 14px 22px;
        }
        .tl-role:last-child{ padding-bottom: 2px; }
        .tl-role-bullet{
          position:absolute; left:0; top: 8px;
          width: 12px; height: 12px; border-radius:50%;
          background: #04061a;
          border: 2px solid var(--c);
        }
        .tl-role-title{
          font: 700 14px/1.25 var(--body); color: var(--paper);
          margin: 0 0 2px;
        }
        .tl-role-era{
          font: 500 11px/1.2 var(--mono); letter-spacing:.08em;
          color: var(--paper-dim);
          text-transform: uppercase;
          margin-bottom: 6px;
        }
        .tl-role-list{
          margin: 6px 0 0; padding-left: 18px;
          color: var(--paper-dim); font: 500 13px/1.55 var(--body);
        }
        .tl-role-list li{ margin-bottom: 3px; }
      `}</style>
    </div>
  );
}

// ─── ChannelsRow: contact methods ───────────────────────────────────────
function ChannelsRow({ row, section }) {
  const [copied, setCopied] = React.useState(null);
  const handle = (it) => {
    if (it.action === 'Copy') {
      navigator.clipboard?.writeText(it.sub);
      setCopied(it.title); setTimeout(()=>setCopied(null), 1400);
    }
  };
  const iconFor = (key) => ({
    at: IconAt, calendar: IconCalendar, linkedin: IconLinkedIn, instagram: IconInstagram,
    phone: IconPhone, github: IconGitHub,
  })[key] || IconSparkle;
  return (
    <div className="ch-row">
      {row.items.map((it,i)=>{
        const Ico = iconFor(it.icon);
        const content = (
          <>
            <div className="ch-icon"><Ico size={22}/></div>
            <div className="ch-mid">
              <div className="ch-title">{it.title}</div>
              <div className="ch-sub">{it.sub}</div>
            </div>
            <div className="ch-act">{copied === it.title ? "Copied ✓" : it.action}</div>
          </>
        );
        if (it.href) {
          const external = /^https?:\/\//.test(it.href);
          return (
            <a
              key={i}
              className="ch"
              href={it.href}
              target={external ? "_blank" : undefined}
              rel={external ? "noreferrer" : undefined}
            >
              {content}
            </a>
          );
        }
        return (
          <button key={i} type="button" className="ch" onClick={()=>handle(it)}>
            {content}
          </button>
        );
      })}
      <style>{`
        .ch-row{ display:grid; grid-template-columns: 1fr 1fr; gap: 14px; }
        @media (max-width: 700px){ .ch-row{ grid-template-columns: 1fr; } }
        .ch{
          display:flex; align-items:center; gap:18px; padding: 16px 20px;
          border-radius: 16px; background: rgba(244,241,232,.04); border:1px solid var(--line);
          color:inherit; text-decoration:none;
          text-align:left; transition: all .2s ease;
        }
        .ch:hover{ transform: translateY(-2px); border-color: var(--c); background: rgba(244,241,232,.07); }
        .ch-icon{
          width: 48px; height:48px; border-radius:14px;
          background: var(--c); color:#04061a;
          display:flex; align-items:center; justify-content:center;
          box-shadow: 3px 3px 0 #04061a;
        }
        .ch-icon svg{ stroke-width: 2.4; }
        .ch-mid{ flex:1; min-width:0; }
        .ch-title{ font: 600 15px/1.2 var(--body); }
        .ch-sub{ font: 500 13px/1 var(--mono); color: var(--paper-dim); margin-top: 4px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
        .ch-act{
          font: 600 11px/1 var(--mono); letter-spacing:.18em; text-transform:uppercase;
          padding: 8px 12px; border-radius: 99px; border:1px solid var(--line); color: var(--paper-dim);
        }
        .ch:hover .ch-act{ color: var(--c); border-color: var(--c); }
      `}</style>
    </div>
  );
}

// ─── FormRow: inline message form ───────────────────────────────────────
// Themed custom dropdown — keeps a hidden <input> for native form submission
function ThemedSelect({ name, options, placeholder, required }) {
  const [value, setValue] = React.useState("");
  const [open, setOpen] = React.useState(false);
  const [activeIdx, setActiveIdx] = React.useState(-1);
  const wrapRef = React.useRef(null);
  const btnRef = React.useRef(null);

  React.useEffect(() => {
    if (!open) return;
    const onDown = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    const onKey = (e) => {
      if (e.key === 'Escape') { setOpen(false); btnRef.current?.focus(); }
      if (e.key === 'ArrowDown') { e.preventDefault(); setActiveIdx(i => Math.min(options.length - 1, i + 1)); }
      if (e.key === 'ArrowUp')   { e.preventDefault(); setActiveIdx(i => Math.max(0, i - 1)); }
      if (e.key === 'Enter' && activeIdx >= 0) {
        e.preventDefault();
        setValue(options[activeIdx]); setOpen(false); btnRef.current?.focus();
      }
    };
    document.addEventListener('mousedown', onDown);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('mousedown', onDown);
      document.removeEventListener('keydown', onKey);
    };
  }, [open, activeIdx, options]);

  const choose = (opt) => { setValue(opt); setOpen(false); btnRef.current?.focus(); };

  return (
    <div className="ts" ref={wrapRef}>
      <button
        ref={btnRef}
        type="button"
        className={`ts-btn ${open ? 'is-open' : ''} ${!value ? 'is-empty' : ''}`}
        onClick={() => { setActiveIdx(options.indexOf(value)); setOpen(o => !o); }}
        aria-haspopup="listbox"
        aria-expanded={open}
      >
        <span className="ts-value">{value || placeholder}</span>
        <svg className="ts-chev" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <polyline points="6 9 12 15 18 9"/>
        </svg>
      </button>
      {open && (
        <ul className="ts-menu" role="listbox">
          {options.map((opt, i) => (
            <li key={i}>
              <button
                type="button"
                role="option"
                aria-selected={value === opt}
                className={`ts-opt ${value === opt ? 'is-selected' : ''} ${activeIdx === i ? 'is-active' : ''}`}
                onMouseEnter={() => setActiveIdx(i)}
                onClick={() => choose(opt)}
              >
                <span className="ts-opt-mark" aria-hidden="true">{value === opt ? '✓' : ''}</span>
                <span>{opt}</span>
              </button>
            </li>
          ))}
        </ul>
      )}
      <input type="hidden" name={name} value={value} required={required}/>
    </div>
  );
}

function FormRow({ row, section }) {
  const [sent, setSent] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState('');
  const to = row.to || 'batsalr0@gmail.com';

  const submitForm = async (e) => {
    e.preventDefault();
    const formEl = e.currentTarget;
    setError('');
    setSending(true);
    // Netlify Forms: POST url-encoded to the site root with form-name=contact
    const body = new URLSearchParams(new FormData(formEl)).toString();
    try {
      const res = await fetch('/', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body,
      });
      if (res.ok) {
        setSent(true);
        window.bnsTrackEvent?.('contact_form_submit', { section: section.id });
        formEl.reset();
      } else {
        setError('Could not send right now. You can email me directly below.');
      }
    } catch (err) {
      setError('Network blocked the send. You can email me directly below.');
    } finally {
      setSending(false);
    }
  };

  const vibeOptions = [
    "Ads / Performance Marketing",
    "Website / Landing Page Build",
    "UI/UX Design",
    "Brand Identity",
    "Just saying hi",
  ];

  return (
    <div className="fm-shell">
    <form
      className="fm"
      name="contact"
      method="POST"
      data-netlify="true"
      netlify-honeypot="bot-field"
      onSubmit={submitForm}
    >
      <input type="hidden" name="form-name" value="contact"/>
      <p hidden><label>Don't fill this out: <input name="bot-field"/></label></p>
      <div className="fm-row">
        <label className="fm-field">
          <span>Your name</span>
          <input name="name" type="text" placeholder="Ada Lovelace" required/>
        </label>
        <label className="fm-field">
          <span>Email</span>
          <input name="email" type="email" placeholder="you@company.com" required/>
        </label>
      </div>
      <label className="fm-field">
        <span>Project / Vibe</span>
        <ThemedSelect name="project_vibe" placeholder="Pick a flavor" options={vibeOptions} required/>
      </label>
      <label className="fm-field">
        <span>What's on your mind?</span>
        <textarea name="message" rows={4} placeholder="Tell me everything — goals, budget, timeline, vibes." required/>
      </label>
      <button className="sv-btn sv-btn--play fm-submit" type="submit" disabled={sending || sent}>
        {sent ? "Sent ✓ — talk soon!" : sending ? "Sending…" : "Send message"}
      </button>
      {error && (
        <div className="fm-error" role="alert">
          {error} <a href={`mailto:${to}`}>Email {to} directly →</a>
        </div>
      )}
      <div className="fm-note">
        <span className="fm-note-dot" aria-hidden="true"/>
        {sent ? <>Message sent to <strong>{to}</strong></> : <>Submits directly to <strong>{to}</strong></>}
      </div>
      <style>{`
        .fm{ display:flex; flex-direction:column; gap: 16px; max-width: 720px; }
        .fm-row{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
        @media (max-width:700px){ .fm-row{ grid-template-columns:1fr; } }
        .fm-field{ display:flex; flex-direction:column; gap:8px; }
        .fm-field > span{ font: 700 11px/1 var(--mono); letter-spacing:.2em; text-transform:uppercase; color:var(--paper-dim); }
        .fm-field input, .fm-field textarea{
          background: rgba(244,241,232,.04); border:1.5px solid var(--line); color:var(--paper);
          padding: 13px 15px; border-radius: 12px; font: 500 14px/1.4 var(--body);
          transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
        }
        .fm-field input::placeholder, .fm-field textarea::placeholder{ color: var(--paper-faint); }
        .fm-field input:focus, .fm-field textarea:focus{
          outline:none; border-color: var(--c); background: rgba(244,241,232,.07);
          box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 22%, transparent);
        }
        .fm-field textarea{ resize: vertical; min-height: 110px; }

        /* Themed select */
        .ts{ position: relative; }
        .ts-btn{
          width: 100%; display:flex; align-items:center; justify-content:space-between; gap: 12px;
          background: rgba(244,241,232,.04); border:1.5px solid var(--line); color:var(--paper);
          padding: 13px 15px; border-radius: 12px; font: 500 14px/1.4 var(--body); text-align:left;
          cursor:pointer;
          transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
        }
        .ts-btn:hover{ border-color: color-mix(in srgb, var(--c) 50%, var(--line)); }
        .ts-btn.is-open{
          border-color: var(--c); background: rgba(244,241,232,.07);
          box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 22%, transparent);
        }
        .ts-btn.is-empty .ts-value{ color: var(--paper-faint); }
        .ts-chev{ color: var(--paper-dim); transition: transform .2s ease, color .2s ease; flex:0 0 auto; }
        .ts-btn.is-open .ts-chev{ transform: rotate(-180deg); color: var(--c); }
        .ts-menu{
          position:absolute; top: calc(100% + 6px); left:0; right:0; z-index: 10;
          list-style:none; margin:0; padding:6px;
          background: linear-gradient(180deg, #0a0e2e, #04061a);
          border: 1.5px solid var(--c); border-radius: 14px;
          box-shadow: 0 16px 36px rgba(0,0,0,.45);
          max-height: 280px; overflow:auto;
          animation: ts-in .14s ease-out;
        }
        @keyframes ts-in{
          from{ opacity:0; transform: translateY(-4px); }
          to  { opacity:1; transform: none; }
        }
        .ts-opt{
          width:100%; display:flex; align-items:center; gap: 10px;
          padding: 11px 12px; border-radius: 9px;
          font: 500 14px/1.3 var(--body); color: var(--paper);
          text-align:left; cursor:pointer;
          transition: background .12s ease, color .12s ease;
        }
        .ts-opt-mark{
          display:grid; place-items:center;
          width: 18px; height: 18px; flex:0 0 auto;
          font: 700 12px/1 var(--mono); color: var(--c);
        }
        .ts-opt.is-active{
          background: color-mix(in srgb, var(--c) 16%, transparent);
        }
        .ts-opt.is-selected{
          color: var(--c); font-weight: 600;
        }

        .fm-submit{ align-self:flex-start; margin-top:8px; }
        .fm-submit:disabled{ opacity:.7; cursor:default; }
        .fm-error{
          font:500 13px/1.5 var(--body); color:#ffb4b4;
          background: rgba(255,77,141,.10); border:1px solid rgba(255,77,141,.35);
          padding:10px 14px; border-radius:12px;
        }
        .fm-error a{ color: var(--paper); text-decoration: underline; white-space:nowrap; }
        .fm-note{
          display:inline-flex; align-items:center; gap:8px;
          font:500 12px/1.4 var(--body);
          color:var(--paper-dim);
          letter-spacing: 0;
          text-transform: none;
        }
        .fm-note strong{ color: var(--paper); font-weight: 600; }
        .fm-note-dot{
          display:inline-block; width:7px; height:7px; border-radius:50%;
          background: var(--c);
          box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 25%, transparent);
        }
      `}</style>
    </form>

    {/* Sidebar — fills the empty right column with something useful */}
    <aside className="fm-aside" aria-label="What to expect">
      <div className="fm-aside-card fm-aside-status">
        <div className="fm-aside-pulse" aria-hidden="true">
          <span/><span/>
        </div>
        <div className="fm-aside-status-text">
          <div className="fm-aside-status-line">Currently taking briefs</div>
          <div className="fm-aside-status-sub">Reply within 24 hours · Kathmandu (UTC +5:45)</div>
        </div>
      </div>

      <div className="fm-aside-card">
        <div className="fm-aside-eyebrow">What helps me reply faster</div>
        <ul className="fm-aside-list">
          <li>
            <span className="fm-aside-num">01</span>
            <div>
              <div className="fm-aside-title">A line about the project</div>
              <div className="fm-aside-sub">Company, brand, or what you're building.</div>
            </div>
          </li>
          <li>
            <span className="fm-aside-num">02</span>
            <div>
              <div className="fm-aside-title">Rough timeline</div>
              <div className="fm-aside-sub">This week, this quarter, or no rush — all fine.</div>
            </div>
          </li>
          <li>
            <span className="fm-aside-num">03</span>
            <div>
              <div className="fm-aside-title">Budget range, if you have one</div>
              <div className="fm-aside-sub">Helps me suggest the right shape of project.</div>
            </div>
          </li>
          <li>
            <span className="fm-aside-num">04</span>
            <div>
              <div className="fm-aside-title">Links worth peeking at</div>
              <div className="fm-aside-sub">Deck, brand, last campaign — whatever's relevant.</div>
            </div>
          </li>
        </ul>
      </div>

      <div className="fm-aside-quote">
        <div className="fm-aside-quote-mark" aria-hidden="true">"</div>
        <p>No template replies. Every message gets read and answered by Batsal — usually within the day.</p>
      </div>

      <style>{`
        .fm-shell{
          display: grid;
          grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
          gap: 28px;
          align-items: start;
        }
        @media (max-width: 900px){
          .fm-shell{ grid-template-columns: 1fr; gap: 22px; }
        }
        .fm-aside{
          display:flex; flex-direction:column; gap: 14px;
          min-width: 0;
        }
        .fm-aside-card{
          padding: 18px 20px;
          border-radius: 18px;
          background:
            linear-gradient(155deg, color-mix(in srgb, var(--c) 9%, transparent) 0%, transparent 60%),
            rgba(244,241,232,.04);
          border: 1px solid var(--line);
        }
        .fm-aside-status{
          display:flex; align-items:center; gap: 14px;
        }
        .fm-aside-pulse{
          position: relative;
          width: 12px; height: 12px; flex: 0 0 auto;
        }
        .fm-aside-pulse span{
          position:absolute; inset:0;
          border-radius:50%;
          background: var(--c);
        }
        .fm-aside-pulse span:nth-child(2){
          animation: fmPulse 1.8s ease-out infinite;
          opacity:.7;
        }
        @keyframes fmPulse{
          0%   { transform: scale(1); opacity:.7; }
          70%  { transform: scale(3); opacity:0; }
          100% { transform: scale(3); opacity:0; }
        }
        .fm-aside-status-line{
          font: 700 13px/1.2 var(--body); color: var(--paper);
          letter-spacing: .01em;
        }
        .fm-aside-status-sub{
          font: 500 11.5px/1.4 var(--body); color: var(--paper-dim); margin-top: 3px;
        }
        .fm-aside-eyebrow{
          font: 700 10.5px/1 var(--mono); letter-spacing: .22em; text-transform: uppercase;
          color: var(--c);
          margin-bottom: 14px;
        }
        .fm-aside-list{
          list-style: none; margin: 0; padding: 0;
          display: flex; flex-direction: column; gap: 14px;
        }
        .fm-aside-list li{
          display:flex; gap: 14px; align-items:flex-start;
        }
        .fm-aside-num{
          flex: 0 0 auto;
          width: 30px; height: 30px;
          display:grid; place-items:center;
          border-radius: 8px;
          background: color-mix(in srgb, var(--c) 14%, rgba(244,241,232,.04));
          border: 1px solid color-mix(in srgb, var(--c) 38%, transparent);
          font: 700 11px/1 var(--mono); letter-spacing: .04em;
          color: var(--c);
        }
        .fm-aside-title{
          font: 600 13.5px/1.3 var(--body); color: var(--paper);
        }
        .fm-aside-sub{
          font: 500 12px/1.45 var(--body); color: var(--paper-dim); margin-top: 2px;
        }
        .fm-aside-quote{
          position: relative;
          padding: 18px 20px 18px 44px;
          border-radius: 18px;
          background: rgba(244,241,232,.03);
          border: 1px solid var(--line);
          border-left: 3px solid var(--c);
        }
        .fm-aside-quote p{
          margin: 0;
          font: italic 500 13px/1.55 var(--body);
          color: var(--paper-dim);
        }
        .fm-aside-quote-mark{
          position:absolute; top: 6px; left: 16px;
          font: 700 44px/1 var(--display-alt);
          color: var(--c);
          opacity: .85;
        }
      `}</style>
    </aside>
    </div>
  );
}

// ─── DownloadsRow ───────────────────────────────────────────────────────
function DownloadsRow({ row, section }) {
  return (
    <div className="dl-row">
      {row.items.map((it,i)=>(
        <div key={i} className="dl">
          <div className="dl-ext">{it.ext}</div>
          <div className="dl-mid">
            <div className="dl-title">{it.title}</div>
            <div className="dl-sub">{it.sub}</div>
          </div>
          {it.href ? (
            <a className="dl-btn" href={it.href} download={it.file || true}
              onClick={() => window.bnsTrackEvent?.('file_download', { file: it.file || it.title, section: section.id })}>
              <IconDownload size={14}/> {it.action}
            </a>
          ) : (
            <button className="dl-btn" disabled title="Coming soon">
              <IconDownload size={14}/> {it.action}
            </button>
          )}
        </div>
      ))}
      <style>{`
        .dl-row{ display:grid; grid-template-columns: 1fr 1fr; gap: 14px; }
        @media (max-width: 700px){ .dl-row{ grid-template-columns: 1fr; } }
        .dl{
          display:flex; align-items:center; gap:18px; padding: 18px 20px;
          border-radius: 16px; background: rgba(244,241,232,.04); border:1px solid var(--line);
          transition: border-color .2s ease;
        }
        .dl:hover{ border-color: var(--c); }
        .dl-ext{
          width: 56px; height: 56px; border-radius: 12px;
          background: #04061a; border: 2px solid var(--c); color: var(--c);
          font: 700 11px/1 var(--mono); letter-spacing:.1em;
          display:flex; align-items:center; justify-content:center;
        }
        .dl-mid{ flex:1; }
        .dl-title{ font:600 15px/1.2 var(--body); }
        .dl-sub{ font:500 12px/1 var(--mono); color:var(--paper-dim); margin-top:5px; }
        .dl-btn{
          display:inline-flex; align-items:center; gap:7px; white-space:nowrap;
          font: 600 12px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
          padding: 10px 16px; border-radius: 99px; text-decoration:none;
          background: var(--c); color:#04061a; box-shadow: 3px 3px 0 #04061a;
          transition: transform .2s ease;
        }
        a.dl-btn:hover{ transform: translate(-1px,-1px); box-shadow: 4px 4px 0 #04061a; }
        .dl-btn:disabled{ opacity:.4; cursor:not-allowed; box-shadow:2px 2px 0 #04061a; }
      `}</style>
    </div>
  );
}

// ─── ResumeHighlights: scannable highlights ─────────────────────────────
function ResumeHighlights({ row, section }) {
  const HI = (row.items && row.items.length) ? row.items : [
    { n: "20%", l: "Sales growth (Ashley e-commerce)" },
    { n: "15%", l: "Customer reach lift (Ashley campaigns)" },
    { n: "100+", l: "Social posts designed & shipped" },
    { n: "4", l: "Hats worn at Ashley Furniture" },
    { n: "9+", l: "Languages in the dev toolbox" },
    { n: "1", l: "Reply needed to start" },
  ];
  return (
    <div className="rh-row">
      {HI.map((it,i)=>(
        <div key={i} className="rh">
          <div className="rh-bar" aria-hidden="true"/>
          <div className="rh-n">{it.n}</div>
          <div className="rh-l">{it.l}</div>
        </div>
      ))}
      <style>{`
        .rh-row{ display:grid; grid-template-columns: repeat(3,1fr); gap: 14px; }
        @media (max-width:700px){ .rh-row{ grid-template-columns: 1fr 1fr; } }
        @media (max-width:480px){ .rh-row{ grid-template-columns: 1fr; } }
        .rh{
          position: relative;
          padding: 22px 22px 20px;
          border-radius: 16px;
          background:
            linear-gradient(155deg, color-mix(in srgb, var(--c) 10%, transparent) 0%, transparent 55%),
            rgba(244,241,232,.04);
          border: 1px solid var(--line);
          overflow: hidden;
          transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
        }
        .rh:hover{
          border-color: var(--c);
          transform: translateY(-2px);
          box-shadow: 0 12px 24px rgba(0,0,0,.25);
        }
        .rh-bar{
          position:absolute; top:0; left:0; bottom:0;
          width: 4px;
          background: linear-gradient(180deg, var(--c), color-mix(in srgb, var(--c) 30%, transparent));
          border-radius: 16px 0 0 16px;
        }
        .rh-n{
          font: 400 46px/1 var(--display-alt);
          color: var(--c);
          letter-spacing: -.01em;
          margin-bottom: 8px;
          padding-left: 8px;
          line-height: 1.05;
          /* No multi-color font here — Bagel Fat One stays crisp */
        }
        .rh-l{
          font: 500 13px/1.45 var(--body);
          color: var(--paper);
          opacity: .82;
          padding-left: 8px;
          max-width: 22ch;
        }
      `}</style>
    </div>
  );
}

// ─── LogoWallRow: client/brand logo grid ────────────────────────────────
function LogoWallRow({ row, section }) {
  const [open, setOpen] = React.useState(null);
  const items = row.items || [];
  const featured = items
    .filter((it) => it.featured)
    .slice()
    .sort((a, b) => (a.featureRank || 99) - (b.featureRank || 99));
  const wall = items.filter((it) => !it.featured);

  const toggle = (key, expandable) => {
    if (!expandable) return;
    setOpen(open === key ? null : key);
  };

  const Logo = ({ item, className = "" }) => (
    <img
      className={`lw-logo ${className}`}
      src={item.src}
      alt=""
      loading="lazy"
      draggable={false}
    />
  );

  return (
    <div className="lw-showcase">
      {featured.length > 0 && (
        <div className="lw-feature-grid" aria-label="Featured brand work">
          {featured.map((it, i) => {
            const key = `feature-${it.name}`;
            const expandable = !!(it.details || it.work);
            const isOpen = open === key;
            return (
              <button
                type="button"
                key={key}
                className={`lw-feature-card ${i === 0 ? 'is-lead' : ''} ${expandable ? 'is-expandable' : ''} ${isOpen ? 'is-open' : ''}`}
                style={{['--c']: section.colorHex}}
                onClick={() => toggle(key, expandable)}
                aria-expanded={expandable ? isOpen : undefined}
                aria-label={`${it.name}${it.work ? ` - ${it.work}` : ''}`}
                title={it.name}
              >
                <div className="lw-feature-frame">
                  <Logo item={it} className="lw-logo--feature"/>
                </div>
                <div className="lw-feature-copy">
                  <div className="lw-feature-kicker">{it.featureTag || "Featured work"}</div>
                  <div className="lw-feature-name-row">
                    <h4 className="lw-feature-name">{it.name}</h4>
                    {expandable && <span className="lw-toggle lw-toggle--feature" aria-hidden="true">{isOpen ? '−' : '+'}</span>}
                  </div>
                  {it.work && <p className="lw-feature-work">{it.work}</p>}
                  {expandable && <div className="lw-details lw-details--feature">{it.details || it.work}</div>}
                </div>
              </button>
            );
          })}
        </div>
      )}

      {wall.length > 0 && (
        <div className="lw-wall">
          <div className="lw-wall-head">
            <span>Logo index</span>
            <span>{wall.length} more brands</span>
          </div>
          <div className="lw-compact-grid">
            {wall.map((it) => {
              const key = `wall-${it.name}`;
              const expandable = !!(it.details || it.work);
              const isOpen = open === key;
              return (
                <button
                  type="button"
                  key={key}
                  className={`lw-mini-tile ${expandable ? 'is-expandable' : ''} ${isOpen ? 'is-open' : ''}`}
                  style={{['--c']: section.colorHex}}
                  onClick={() => toggle(key, expandable)}
                  aria-expanded={expandable ? isOpen : undefined}
                  aria-label={`${it.name}${it.work ? ` - ${it.work}` : ''}`}
                  title={it.name}
                >
                  <div className="lw-mini-frame">
                    <Logo item={it} className="lw-logo--mini"/>
                  </div>
                  <div className="lw-mini-copy">
                    <div className="lw-name-row">
                      <div className="lw-name">{it.name}</div>
                      {expandable && <span className="lw-toggle" aria-hidden="true">{isOpen ? '−' : '+'}</span>}
                    </div>
                    {it.work && <div className="lw-work">{it.work}</div>}
                    {expandable && <div className="lw-details">{it.details || it.work}</div>}
                  </div>
                </button>
              );
            })}
          </div>
        </div>
      )}
      <style>{`
        .lw-showcase{
          display:flex;
          flex-direction:column;
          gap: 26px;
        }
        .lw-feature-grid{
          display:grid;
          grid-template-columns: repeat(5, minmax(0, 1fr));
          gap: 16px;
          align-items: stretch;
        }
        .lw-feature-card,
        .lw-mini-tile{
          color:inherit; font:inherit;
          text-align:left;
          background: rgba(244,241,232,.06);
          border:1px solid var(--line);
          transition: transform .22s ease, border-color .22s ease, background .22s ease, box-shadow .22s ease;
        }
        .lw-feature-card{
          position:relative;
          grid-column: span 1;
          min-height: 286px;
          display:flex;
          flex-direction:column;
          gap:14px;
          padding: 18px;
          border-radius: 20px;
          overflow:hidden;
        }
        .lw-feature-card.is-lead{
          background:
            linear-gradient(145deg, color-mix(in srgb, var(--c) 14%, transparent), rgba(244,241,232,.065) 58%),
            rgba(244,241,232,.05);
        }
        .lw-feature-card::before{
          content:"";
          position:absolute;
          inset:0 0 auto 0;
          height:3px;
          background: var(--c);
          opacity:.9;
        }
        .lw-feature-card.is-expandable,
        .lw-mini-tile.is-expandable{ cursor:pointer; }
        .lw-feature-card:hover,
        .lw-mini-tile:hover{
          transform: translateY(-3px);
          border-color: var(--c);
          background: rgba(244,241,232,.10);
        }
        .lw-feature-card.is-open,
        .lw-mini-tile.is-open{
          border-color: var(--c);
          background: rgba(244,241,232,.10);
          box-shadow: 0 0 0 1px var(--c), 0 12px 32px rgba(0,0,0,.25);
        }
        .lw-feature-frame{
          height: 132px;
          display:flex; align-items:center; justify-content:center;
          padding: 16px;
          background: #f4f1e8;
          border-radius:14px;
          overflow:hidden;
        }
        .lw-feature-copy{
          display:flex;
          flex-direction:column;
          gap:8px;
          min-width:0;
          flex:1;
        }
        .lw-feature-kicker{
          align-self:flex-start;
          padding: 6px 8px;
          border-radius: 999px;
          background: color-mix(in srgb, var(--c) 16%, transparent);
          border: 1px solid color-mix(in srgb, var(--c) 36%, transparent);
          color: var(--c);
          font: 700 10px/1 var(--mono);
          letter-spacing: .1em;
          text-transform: uppercase;
        }
        .lw-feature-name-row{
          display:flex;
          align-items:center;
          gap:10px;
        }
        .lw-feature-name{
          margin:0;
          color: var(--paper);
          font: 800 15px/1.12 var(--body);
          letter-spacing:.04em;
          text-transform:uppercase;
        }
        .lw-feature-work{
          margin:0;
          color: var(--paper-dim);
          font: 600 12px/1.45 var(--body);
        }
        .lw-wall{
          display:flex;
          flex-direction:column;
          gap: 12px;
        }
        .lw-wall-head{
          display:flex;
          align-items:center;
          justify-content:space-between;
          gap:16px;
          padding: 0 2px;
          font: 700 10px/1 var(--mono);
          letter-spacing:.18em;
          text-transform:uppercase;
          color: var(--paper-faint);
        }
        .lw-compact-grid{
          display:grid;
          grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
          gap: 14px;
          align-items:start;
        }
        .lw-mini-tile{
          display:grid;
          grid-template-columns: 96px minmax(0, 1fr);
          gap: 14px;
          padding: 14px;
          border-radius: 16px;
          align-items:center;
        }
        .lw-mini-frame{
          height: 82px;
          display:flex; align-items:center; justify-content:center;
          padding: 8px;
          background: #f4f1e8;
          border-radius:10px;
          overflow:hidden;
        }
        .lw-logo{
          max-width:100%; max-height:100%;
          width:auto; height:auto;
          object-fit: contain;
          display:block;
          user-select:none;
          transition: transform .22s ease, filter .22s ease;
        }
        .lw-feature-card:hover .lw-logo,
        .lw-feature-card.is-open .lw-logo,
        .lw-mini-tile:hover .lw-logo,
        .lw-mini-tile.is-open .lw-logo{ transform: scale(1.05); }
        .lw-mini-copy{
          display:flex; flex-direction:column; gap:6px;
          min-width:0;
        }
        .lw-name-row{
          display:flex; align-items:center; justify-content:space-between; gap:8px;
          position:relative;
          min-width:0;
        }
        .lw-name{
          font: 700 12px/1.25 var(--body);
          letter-spacing: .06em;
          color: var(--paper);
          text-transform: uppercase;
          min-width:0;
        }
        .lw-toggle{
          display:grid; place-items:center;
          width:18px; height:18px; border-radius:50%;
          border:1px solid color-mix(in srgb, var(--c) 55%, transparent);
          color:var(--c); font:700 13px/1 var(--mono);
          flex:0 0 auto;
        }
        .lw-toggle--feature{ margin-left:auto; }
        .lw-work{
          font: 500 11px/1.4 var(--body);
          color: var(--paper-dim);
          letter-spacing: .01em;
        }
        .lw-details{
          grid-column: 1 / -1;
          max-height:0; opacity:0; transform:translateY(-4px);
          overflow:hidden;
          font: 500 12px/1.5 var(--body);
          color: var(--paper-dim);
          text-align:left;
          padding: 0 2px;
          border-top: 1px dashed transparent;
          transition: max-height .25s ease, opacity .2s ease, transform .2s ease, margin-top .2s ease, padding-top .2s ease, border-color .2s ease;
        }
        .lw-feature-card.is-open .lw-details,
        .lw-mini-tile.is-open .lw-details{
          max-height: 220px; opacity:1; transform:none;
          margin-top: 8px; padding-top: 10px;
          border-top-color: color-mix(in srgb, var(--c) 45%, transparent);
        }
        .lw-details--feature{
          margin-top:auto;
        }
        @media (max-width: 1180px){
          .lw-feature-grid{ grid-template-columns: repeat(3, minmax(0, 1fr)); }
        }
        @media (max-width: 820px){
          .lw-feature-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
          .lw-feature-card{ min-height: 270px; }
          .lw-compact-grid{ grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
        }
        @media (max-width: 560px){
          .lw-showcase{ gap:18px; }
          .lw-feature-grid{ grid-template-columns: 1fr; gap:12px; }
          .lw-feature-card{ min-height:auto; padding:14px; border-radius:16px; }
          .lw-feature-frame{ height:112px; padding:12px; }
          .lw-compact-grid{ grid-template-columns: 1fr; }
          .lw-mini-tile{ grid-template-columns: 76px minmax(0, 1fr); }
          .lw-wall-head{ align-items:flex-start; flex-direction:column; gap:6px; }
          .lw-name{ font-size: 11px; }
          .lw-work{ font-size: 10px; }
          .lw-details{ font-size: 11px; }
        }
      `}</style>
    </div>
  );
}

// ─── CurrentlyRow: live "what I'm up to" strip ──────────────────────────
function CurrentlyRow({ row, section }) {
  return (
    <div className="cu-row">
      {row.items.map((it, i) => (
        <div key={i} className="cu-chip">
          <span className="cu-live" aria-hidden="true"><span/></span>
          <span className="cu-text">{it.text}</span>
        </div>
      ))}
      <style>{`
        .cu-row{ display:flex; flex-wrap:wrap; gap:12px; }
        .cu-chip{
          display:inline-flex; align-items:center; gap:10px;
          padding: 12px 18px 12px 14px;
          border-radius: 99px;
          background:
            linear-gradient(135deg, color-mix(in srgb, var(--c) 12%, transparent), rgba(244,241,232,.04));
          border: 1px solid color-mix(in srgb, var(--c) 35%, var(--line));
          font: 600 13px/1.2 var(--body); color: var(--paper);
          transition: transform .2s ease, border-color .2s ease;
        }
        .cu-chip:hover{ transform: translateY(-2px); border-color: var(--c); }
        .cu-live{
          position:relative; flex:0 0 auto;
          width:10px; height:10px;
        }
        .cu-live::before{
          content:""; position:absolute; inset:0; border-radius:50%;
          background: var(--c);
        }
        .cu-live span{
          position:absolute; inset:0; border-radius:50%;
          background: var(--c);
          animation: cuPing 1.8s cubic-bezier(0,.5,.5,1) infinite;
        }
        @keyframes cuPing{
          0%   { transform: scale(1); opacity:.7; }
          70%  { transform: scale(2.6); opacity:0; }
          100% { transform: scale(2.6); opacity:0; }
        }
        @media (max-width: 700px){
          .cu-row{ flex-direction:column; align-items:flex-start; }
        }
      `}</style>
    </div>
  );
}

// ─── ProjectsRow: developer project showcase ────────────────────────────
function ProjectsRow({ row, section }) {
  const [open, setOpen] = React.useState(null);
  const logoFor = (key) => ({
    gym: IconLogoGym,
    cloudmeet: IconLogoCloudMeet,
    llm: IconLogoLLM,
    analyzer: IconLogoAnalyzer,
    finance: IconLogoFinance,
  })[key] || IconCode;

  return (
    <div className="pr-grid">
      {row.items.map((it, i) => {
        const Logo = logoFor(it.logo);
        const isOpen = open === i;
        const expandable = !!(it.details || (it.features && it.features.length));
        return (
          <div key={i} className={`pr-card ${isOpen ? 'is-open' : ''}`}>
            <div className="pr-head">
              <div className="pr-logo-frame">
                <Logo size={44}/>
              </div>
              <div className="pr-head-meta">
                <div className="pr-num">EP {String(i+1).padStart(2,'0')}</div>
                {it.year && <div className="pr-year">{it.year}</div>}
              </div>
            </div>

            <div className="pr-body">
              <h4 className="pr-title">{it.title}</h4>
              {it.sub && <p className="pr-sub">{it.sub}</p>}

              {it.tech && it.tech.length > 0 && (
                <ul className="pr-tech" aria-label="Tech stack">
                  {it.tech.map((t, j) => <li key={j} className="pr-tech-chip">{t}</li>)}
                </ul>
              )}

              {expandable && (
                <div className="pr-details">
                  {it.details && <p className="pr-details-text">{it.details}</p>}
                  {it.features && it.features.length > 0 && (
                    <>
                      <div className="pr-details-label">Features</div>
                      <ul className="pr-features">
                        {it.features.map((f, j) => <li key={j}>{f}</li>)}
                      </ul>
                    </>
                  )}
                </div>
              )}
            </div>

            <div className="pr-foot">
              {it.github && (
                <a
                  className="pr-gh"
                  href={it.github}
                  target="_blank"
                  rel="noreferrer"
                  onClick={(e) => e.stopPropagation()}
                >
                  <IconGitHub size={15}/>
                  <span className="pr-gh-label">View on GitHub</span>
                  <span className="pr-gh-arrow" aria-hidden="true">↗</span>
                </a>
              )}
              {expandable && (
                <button
                  type="button"
                  className="pr-toggle-btn"
                  onClick={() => setOpen(isOpen ? null : i)}
                  aria-expanded={isOpen}
                  aria-label={isOpen ? "Collapse details" : "Expand details"}
                >
                  <span>{isOpen ? "Less" : "More"}</span>
                  <span className="pr-toggle-mark" aria-hidden="true">{isOpen ? "−" : "+"}</span>
                </button>
              )}
            </div>
          </div>
        );
      })}
      <style>{`
        .pr-grid{
          display:grid;
          grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
          gap: 18px;
          align-items: stretch;
        }
        .pr-card{
          --c: ${section.colorHex};
          display:flex; flex-direction:column;
          background: rgba(244,241,232,.04);
          border: 1px solid var(--line);
          border-radius: 20px;
          overflow: hidden;
          transition: transform .22s ease, border-color .22s ease, background .22s ease, box-shadow .22s ease;
        }
        .pr-card:hover{
          transform: translateY(-4px);
          border-color: var(--c);
          background: rgba(244,241,232,.07);
        }
        .pr-card.is-open{
          border-color: var(--c);
          background: rgba(244,241,232,.08);
          box-shadow: 0 0 0 1px var(--c), 0 18px 40px rgba(0,0,0,.28);
        }

        .pr-head{
          position: relative;
          display:flex; align-items:center; justify-content:space-between;
          padding: 16px 18px;
          background: linear-gradient(135deg, color-mix(in srgb, var(--c) 22%, #04061a), #04061a);
          border-bottom: 1px solid color-mix(in srgb, var(--c) 30%, transparent);
        }
        .pr-logo-frame{
          width: 64px; height: 64px;
          display: grid; place-items: center;
          border-radius: 14px;
          background: var(--c); color: #04061a;
          box-shadow: 3px 3px 0 #04061a;
        }
        .pr-head-meta{
          display:flex; flex-direction:column; align-items:flex-end; gap: 5px;
        }
        .pr-num{
          font:700 10px/1 var(--mono); letter-spacing:.18em;
          color: var(--paper);
          padding: 4px 8px; border-radius: 4px;
          background: rgba(4,6,26,.6);
        }
        .pr-year{
          font:500 11px/1 var(--mono); color: var(--paper-dim); letter-spacing: .1em;
        }

        .pr-body{
          padding: 16px 18px 8px;
          display:flex; flex-direction:column; gap: 10px;
          flex: 1 1 auto;
        }
        .pr-title{
          font: 700 18px/1.2 var(--body); margin: 0; color: var(--paper);
        }
        .pr-sub{
          font: 500 13px/1.55 var(--body); color: var(--paper-dim); margin: 0;
        }

        .pr-tech{
          display:flex; flex-wrap:wrap; gap: 6px;
          margin: 4px 0 0; padding: 0; list-style:none;
        }
        .pr-tech-chip{
          font: 600 10.5px/1 var(--mono); letter-spacing:.04em;
          padding: 6px 9px;
          border-radius: 99px;
          background: rgba(244,241,232,.07);
          border: 1px solid color-mix(in srgb, var(--c) 35%, transparent);
          color: var(--paper);
        }

        .pr-details{
          max-height: 0; opacity: 0; overflow: hidden;
          transition: max-height .3s ease, opacity .22s ease, margin-top .22s ease, padding-top .22s ease, border-color .22s ease;
          border-top: 1px dashed transparent;
        }
        .pr-card.is-open .pr-details{
          max-height: 520px; opacity: 1;
          margin-top: 12px; padding-top: 12px;
          border-top-color: color-mix(in srgb, var(--c) 40%, transparent);
        }
        .pr-details-text{
          font: 500 13px/1.55 var(--body); color: var(--paper-dim); margin: 0 0 10px;
        }
        .pr-details-label{
          font: 700 10px/1 var(--mono); letter-spacing:.2em; text-transform: uppercase;
          color: var(--c); margin-bottom: 6px;
        }
        .pr-features{
          margin: 0; padding-left: 18px;
          font: 500 13px/1.55 var(--body); color: var(--paper-dim);
        }
        .pr-features li{ margin-bottom: 2px; }

        .pr-foot{
          display:flex; align-items:center; justify-content: space-between; gap: 10px;
          padding: 12px 18px 16px;
          margin-top: auto;
        }
        .pr-gh{
          display:inline-flex; align-items:center; gap: 7px;
          font: 600 12px/1 var(--body); letter-spacing:.02em;
          color: var(--paper);
          text-decoration: none;
          padding: 8px 10px;
          border-radius: 99px;
          background: rgba(244,241,232,.06);
          border: 1px solid var(--line);
          transition: border-color .18s ease, background .18s ease, color .18s ease;
        }
        .pr-gh:hover{
          border-color: var(--c);
          color: var(--c);
          background: rgba(244,241,232,.10);
        }
        .pr-gh-arrow{ font-weight: 700; opacity: .8; }
        .pr-toggle-btn{
          display:inline-flex; align-items:center; gap: 6px;
          font: 700 11px/1 var(--mono); letter-spacing:.12em; text-transform: uppercase;
          color: var(--c);
          padding: 8px 10px;
          border-radius: 99px;
          background: rgba(4,6,26,.4);
          border: 1px solid color-mix(in srgb, var(--c) 45%, transparent);
        }
        .pr-toggle-btn:hover{ background: rgba(4,6,26,.6); }
        .pr-toggle-mark{
          display:grid; place-items:center;
          width: 16px; height: 16px; border-radius:50%;
          border:1px solid var(--c); font:700 12px/1 var(--mono);
        }

        @media (max-width: 700px){
          .pr-grid{ grid-template-columns: 1fr; gap: 14px; }
          .pr-logo-frame{ width: 56px; height: 56px; }
          .pr-title{ font-size: 17px; }
          .pr-gh-label{ display: none; }
        }
      `}</style>
    </div>
  );
}

window.SectionView = SectionView;
