// Work page: list + detail.
// `status` is pulled from window.PROJECT_STATUS (data.js) so it stays in
// sync with the sidebar and home "Active roles" list. Do NOT hardcode
// status strings here.
const _PS = window.PROJECT_STATUS || {};
const WORK_DATA = [
  {
    id: 'kato', num: '01',
    title: 'Kato AI', em: null,
    role: 'Co-founder & CTO',
    status: _PS.kato?.caseLabel,
    years: '2025 → NOW',
    sector: 'EDTECH · LANGUAGE EDUCATION',
    badges: ['CEFR A1–C2', 'Multi-agent', 'Live pilots', 'GEC'],
    metrics: [
      { v: 'LIVE', l: 'in production' },
      { v: 'CEFR', l: 'aligned A1–C2' },
      { v: 'DCU', l: 'developed at' },
    ],
    narrative: [
      "AI platform for language schools: plan, generate, deliver and assess lessons with gamified live classroom delivery, automated writing correction, and CEFR-aligned student reports.",
      "Co-founded with <b>Mark Kelly</b> (CEO, ex-teacher and school operator) and <b>Matthew Conlan</b> (CPO, ex-teacher, MSc Computing). I lead engineering and the AI stack.",
      "Developed at DCU School of Computing and the ADAPT Research Centre. Part of the Guinness Enterprise Centre (GEC) community. Selected for TU Dublin's Postgraduate Diploma consulting project.",
    ],
    stack: ['Python · FastAPI', 'Next.js 14 · App Router · TS', 'PostgreSQL · Prisma · MongoDB', 'Tailwind · shadcn/ui', 'Multi-agent orchestration'],
    accent: '#7cffb2',
    signature: {
      title: 'pipeline · 5 stages',
      caption: 'live',
      bars: [80, 95, 90, 88, 75],
      labels: ['plan', 'gen', 'deliv', 'assess', 'rep'],
    },
  },
  {
    id: 'pilotpath', num: '02',
    title: 'PilotPath', em: 'PACIFIC',
    role: 'Fractional CTO',
    status: _PS.pilotpath?.caseLabel,
    years: '2026 → NOW',
    sector: 'AVIATION TRAINING · IE · UK · USA',
    badges: ['Regulated', 'Multi-jurisdiction', 'Sole trader'],
    metrics: [
      { v: '3', l: 'jurisdictions' },
      { v: '120–150', l: 'active leads' },
      { v: '300+', l: '2026 target' },
    ],
    narrative: [
      "Pilot training program management company operating across Ireland, UK, and USA. Currently 120–150 active leads; 2026 target is 300–350 leads with 20–25 monthly enrolments.",
      "Core deliverable is <b>PACIFIC</b>, the Pilot Acquisition & Training Hub: a unified system replacing a fragmented Retool / Sheets / GoCardless / Xero stack.",
      "As fractional CTO (sole trader) I lead engineering direction and architecture. The role is mostly translation: between regulators, founders, and engineers.",
    ],
    stack: ['Next.js · App Router · TS', 'PostgreSQL · Cloud SQL', 'Cloud Run · GCP', 'Prisma · NextAuth', 'Tailwind · shadcn/ui'],
    accent: '#5bb0ff',
    signature: {
      title: 'leads · 2026 target',
      caption: '→ 325',
      bars: [135, 325],
      labels: ['now', 'target'],
    },
  },
  {
    id: 'monisub', num: '03',
    title: 'MoniSub', em: null,
    role: 'Solo build',
    status: _PS.monisub?.caseLabel,
    years: '2024 →',
    sector: 'CONSUMER SAAS · PRIVACY-FIRST',
    badges: ['Privacy-first', 'Freemium', 'Web + Mobile'],
    metrics: [
      { v: 'Plaid', l: '+ TrueLayer' },
      { v: 'web', l: '+ mobile' },
      { v: 'email', l: 'parse fallback' },
    ],
    narrative: [
      "Privacy-first subscription tracking SaaS. Automated detection via Plaid/TrueLayer with email parsing as a backup, usage-vs-spend insight, renewal alerts, and ROI scoring.",
      "Web + mobile, freemium model. PRD and competitive positioning complete; the aim is a tool that helps you cancel things, not a dashboard that upsells a premium tier.",
    ],
    stack: ['Plaid · TrueLayer', 'Email parsing fallback', 'Renewal forecasting', 'Usage vs spend analytics', 'Freemium'],
    accent: '#ffb84d',
    signature: {
      title: 'detection sources',
      caption: '3 channels',
      bars: [90, 90, 50],
      labels: ['plaid', 'trulyr', 'email'],
    },
  },
  {
    id: 'bacore', num: '04',
    title: 'BACoRe', em: null,
    role: 'Research platform',
    status: _PS.bacore?.caseLabel,
    years: '2024 →',
    sector: 'BEHAVIOURAL ANALYTICS · RESEARCH',
    badges: ['TypeScript monorepo', 'pgvector', 'Android capture', 'Research'],
    metrics: [
      { v: 'B2C', l: '+ B2B portals' },
      { v: 'GPT-4o', l: 'Vision pipeline' },
      { v: 'PhD ext.', l: 'extension of' },
    ],
    narrative: [
      "Behavioural Analytics Cloud Research: a full-stack platform extending my PhD. TypeScript monorepo with Express, PostgreSQL + pgvector, Redis + BullMQ, MinIO, Docker Compose.",
      "Android capture app (Kotlin, CameraX) with location/motion/light-triggered capture and rich sensor metadata. GPT-4o Vision + Google Cloud Vision pipeline, text-embedding-3-small, K-Means / DBSCAN clustering.",
      "Dual portals: a B2C consumer dashboard and a B2B researcher portal for study management, journey maps, brand exposure, visual ethnography, and data export.",
    ],
    stack: ['TypeScript monorepo', 'Express · PostgreSQL · pgvector', 'Redis · BullMQ · MinIO', 'Kotlin · CameraX', 'GPT-4o Vision · embeddings'],
    accent: '#b59fff',
    signature: {
      title: 'data pipeline · 4 stages',
      caption: 'capture → view',
      bars: [70, 85, 95, 75],
      labels: ['capture', 'upload', 'analyse', 'view'],
    },
  },
  {
    id: 'memdic', num: '05',
    title: 'MEMDIC', em: null,
    role: 'Co-founder',
    status: _PS.memdic?.caseLabel,
    years: 'SFI-funded research',
    sector: 'CONSUMER ANALYTICS · WEARABLE',
    badges: ['Sensor-to-dashboard', 'TRL 6/7', 'Privacy-aware', 'SFI'],
    metrics: [
      { v: '10yr', l: 'SFI research' },
      { v: 'TRL', l: '6/7 prototype' },
      { v: 'IP', l: 'unencumbered' },
    ],
    narrative: [
      "Low-cost, privacy-aware, sensor-to-dashboard platform for observing real, uninhibited human behaviour, built for market research and FMCG. Co-founded with <b>Graham Healy</b> (PhD, Multimodal BCI) and <b>Cathal Gurrin</b> (PhD, Search Engines).",
      "The customer solution has two parts: a small wearable camera clipped to clothing that captures, anonymises and securely uploads behaviour data to our cloud, and a web platform that blends visual and multimodal AI to understand the footage, with an intuitive query system and a result-viewing dashboard.",
      "Market research firms and FMCG organisations buy the reusable sensor, recruit participants, and receive fully anonymised analytics: daily activities, brand interactions, behaviours. Faster and more cost-effective than traditional observation, because it removes the need for manual analysis.",
      "Foundational elements developed over a decade of SFI-funded research; IP is unencumbered. Prototypes reached TRL 6/7 (operating in a realistic setting), ahead of traditional market research methods at TRL 5.",
    ],
    stack: ['Wearable camera sensor', 'Anonymised cloud capture', 'Visual + multimodal AI', 'Query system + dashboard', 'Decade of SFI research'],
    accent: '#ffb84d',
    signature: {
      title: 'TRL · readiness scale',
      caption: 'peak 6/7',
      bars: [10, 20, 35, 50, 65, 85, 92, 55, 25],
      labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9'],
    },
  },
  {
    id: 'phd', num: '06',
    title: 'Usage Analytics', em: 'framework',
    role: 'PhD · Lero / DCU',
    status: _PS.phd?.caseLabel,
    years: '2016 → 2020',
    sector: 'RESEARCH · IBM COLLAB',
    badges: ['CHIRA', 'UKAIS', 'SMARTGREENS', 'Springer CCIS', 'IBM invention'],
    metrics: [
      { v: '85+', l: 'Scholar citations' },
      { v: '1', l: 'IBM invention' },
      { v: '3', l: 'awards' },
    ],
    narrative: [
      "PhD at DCU School of Computing, affiliated with <b>Lero</b> (SFI Research Centre for Software). Supervised by Prof. Markus Helfert, Dr. Marija Bezbradica, Dr. Duc-Tien Dang-Nguyen.",
      "Framework for moving software teams from raw telemetry to decision-grade product signal. Validated through industry case studies and collaboration with <b>IBM Research Labs Ireland</b>, which produced a recognised invention in the software analytics domain.",
      "Awards: DCU President's Commercialization 2017, Technology Ireland Industry Awards finalist 2018, Tech Excellence Awards finalist 2019. Published at CHIRA (Springer CCIS 654), UKAIS, SMARTGREENS.",
    ],
    stack: ['Cloud usage analytics', 'HCI research', 'Industry case studies', 'IBM Research collab', 'Peer-reviewed · Springer'],
    accent: '#7cffb2',
    signature: {
      title: 'papers · PhD years',
      caption: '2016–2020',
      bars: [1, 2, 3, 1, 0],
      labels: ['16', '17', '18', '19', '20'],
    },
  },
  {
    id: 'backdoor', num: '07',
    title: 'Live Backdoor', em: 'detection',
    role: 'MEng thesis · UL',
    status: _PS.backdoor?.caseLabel,
    years: '2015',
    sector: 'CLOUD SECURITY · DIGITAL FORENSICS',
    badges: ['Eucalyptus', 'Metasploit', 'Ngrep', 'Private cloud'],
    metrics: [
      { v: '3', l: 'phases' },
      { v: 'IaaS', l: 'private cloud' },
      { v: 'live', l: 'packet capture' },
    ],
    narrative: [
      "MEng thesis at the <b>University of Limerick</b>, submitted September 2015. The goal: detect a live backdoor root-access attack on a private cloud and forensically analyse the packet data between attacker and system after a successful compromise.",
      "I built both sides of the problem. First, a private cloud using <b>Eucalyptus</b> (IaaS, AWS-compatible API). Then, a real backdoor root-access attack using <b>Metasploit</b> targeting the Cloud Controller. Then, a forensic method using <b>Ngrep</b> to read live packet transmission and detect the shell-access signature in payload data.",
      "The novelty was the detection pattern: Linux commands in incoming traffic followed by immediate outgoing response to the same IP, the exact fingerprint of an attacker's interactive shell. Successfully identified and evidenced the live attack on captured traffic.",
    ],
    stack: ['Eucalyptus · private IaaS', 'Metasploit · offensive sim', 'Ngrep · packet analysis', 'Linux · cloud forensics', 'Payload signature detection'],
    accent: '#ff4545',
    signature: {
      title: 'thesis · 3 phases',
      caption: 'build → attack → detect',
      bars: [60, 90, 75],
      labels: ['build', 'attack', 'detect'],
    },
  },
];

function WorkArt({ w }) {
  // Each project's signature is a small meaningful bar chart.
  // Bars + labels map to real aspects of that project — pipeline
  // stages, jurisdictions, research output, TRL levels, etc.
  const sig = w.signature || { title: w.id, bars: [40, 50, 40], labels: null };
  const bars = sig.bars;
  const max = Math.max(...bars, 1);
  const n = bars.length;
  const gap = 4;
  const vw = 240;
  const barW = (vw - gap * (n - 1)) / n;
  const vh = 64;
  const labelH = sig.labels ? 14 : 0;
  return (
    <div className="wd-art">
      <div style={{ display: 'flex', justifyContent: 'space-between' }}>
        <span className="art-title">▚ {sig.title}</span>
        <span style={{ color: 'var(--ink-dimmer)', fontSize: 10 }}>{sig.caption || `v${w.num}`}</span>
      </div>
      <svg viewBox={`0 0 ${vw} ${vh + labelH}`} preserveAspectRatio="none" style={{ width: '100%', height: 72 + labelH }}>
        {bars.map((v, i) => {
          const h = (v / max) * vh;
          return (
            <g key={i}>
              <rect x={i * (barW + gap)} y={vh - h} width={barW} height={h} fill={w.accent} opacity={0.4 + (i / n) * 0.5} rx="1.5" />
              {sig.labels && (
                <text x={i * (barW + gap) + barW / 2} y={vh + 10} textAnchor="middle" fontSize="8" fill="var(--ink-dimmer)" fontFamily="var(--f-mono)">
                  {sig.labels[i]}
                </text>
              )}
            </g>
          );
        })}
      </svg>
      <div className="kv"><span className="k">status</span><span className="v accent">{w.status}</span></div>
      <div className="kv"><span className="k">years</span><span className="v">{w.years}</span></div>
      <div className="kv"><span className="k">sector</span><span className="v" style={{ fontSize: 11 }}>{w.sector}</span></div>
      <div className="kv"><span className="k">role</span><span className="v">{w.role}</span></div>
      <div style={{ borderTop: '1px dashed var(--line)', margin: '8px 0' }} />
      <div style={{ fontSize: 10, color: 'var(--ink-dimmer)', letterSpacing: '.12em', textTransform: 'uppercase' }}>tags</div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
        {w.badges.map((b) => <span key={b} className="badge" style={{ borderColor: w.accent, color: w.accent }}>{b}</span>)}
      </div>
    </div>
  );
}

function PageWork() {
  const [sel, setSel] = React.useState(0);
  const w = WORK_DATA[sel];

  return (
    <div className="page" data-page="work" data-screen-label="02 Work">
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14 }}>
        <div>
          <div style={{ fontSize: 10, color: 'var(--ink-dimmer)', letterSpacing: '.18em', textTransform: 'uppercase' }}>⦿ 02 · selected work</div>
          <h2 style={{ fontFamily: 'var(--f-display)', fontSize: 40, fontWeight: 800, letterSpacing: '-.03em', margin: '8px 0 0', color: 'var(--ink)' }}>
            Things shipped, in order of <span style={{ fontFamily: 'var(--f-serif)', fontStyle: 'italic', color: 'var(--accent-amber)', fontWeight: 400 }}>weight.</span>
          </h2>
        </div>
        <div style={{ color: 'var(--ink-dim)', fontSize: 11 }}>index · {sel + 1} / {WORK_DATA.length}</div>
      </div>

      <div className="work-wrap">
        <div className="work-list">
          {WORK_DATA.map((d, i) => (
            <div
              key={d.id}
              className={`work-row ${i === sel ? 'active' : ''}`}
              onClick={() => setSel(i)}
              data-hover-label={`▸ ${d.title}`}
            >
              <div className="wr-num">{d.num}</div>
              <div>
                <div className="wr-title">
                  {d.title}{d.em && <> <em style={{ fontFamily: 'var(--f-serif)', fontStyle: 'italic', fontWeight: 400, color: 'var(--accent-amber)' }}>{d.em}</em></>}
                </div>
                <div className="wr-role">{d.role} · {d.years}</div>
              </div>
              <div className="wr-arrow">
                <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 11L11 3M11 3H4M11 3V10" stroke="currentColor" strokeWidth="1.4"/></svg>
              </div>
            </div>
          ))}

          <div className="panel" style={{ marginTop: 14 }}>
            <div className="panel-head"><span style={{ display: 'flex', alignItems: 'center', gap: 8 }}><span className="ph-dot" /><span className="ph-title">LEGEND</span></span></div>
            <div className="panel-body" style={{ fontSize: 11, color: 'var(--ink-dim)', display: 'flex', flexDirection: 'column', gap: 6 }}>
              <div>▸ filter by sector, stack, role · soon</div>
              <div>▸ full archive at github.com/chintu0019</div>
            </div>
          </div>
        </div>

        <div className="work-detail">
          <div className="wd-head">
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 10, color: 'var(--ink-dimmer)', letterSpacing: '.14em', textTransform: 'uppercase' }}>
                <span>case / {w.num}</span>
                <span className="badge live" style={{ borderColor: w.accent, color: w.accent }}>{w.status}</span>
              </div>
              <h2 style={{ marginTop: 10 }}>
                {w.title}{w.em && <> <em>{w.em}</em></>}
              </h2>
              <div className="wd-badges">
                {w.badges.map((b) => <span key={b} className="badge">{b}</span>)}
              </div>
            </div>
            <div className="wd-metrics">
              {w.metrics.map((m, i) => (
                <div key={i} className="m">
                  <div className={`v ${i === 0 ? 'accent' : ''}`} style={{ color: i === 0 ? w.accent : undefined }}>{m.v}</div>
                  <div className="l">{m.l}</div>
                </div>
              ))}
            </div>
          </div>

          <div className="wd-body">
            <div className="wd-narr">
              {w.narrative.map((p, i) => (
                <p key={i} dangerouslySetInnerHTML={{ __html: p.replace(/<b>(.*?)<\/b>/g, '<b>$1</b>') }} />
              ))}
              <div style={{ fontSize: 10, color: 'var(--ink-dimmer)', letterSpacing: '.14em', textTransform: 'uppercase', marginTop: 14 }}>Stack · what's inside</div>
              <div className="wd-stack-list">
                {w.stack.map((s) => <div key={s} className="s"><span>{s}</span><span style={{ color: 'var(--ink-dimmer)' }}>◦</span></div>)}
              </div>
            </div>
            <WorkArt w={w} />
          </div>
        </div>
      </div>
    </div>
  );
}
Object.assign(window, { PageWork });
