/* global React, ReactDOM, DesignCanvas, DCSection, DCArtboard, DCPostIt,
   InvestigationScreen, Timeline, WatsonRail, CommandSuggestions, TopBar,
   Card, Tag, Pin, WaxSeal, EVIDENCE, EVIDENCE_TWIST, HYPOTHESES, NARRATIVE, NARRATIVE_1PIN, NARRATIVE_3PIN,
   Pocket, HypothesisCard, Narrative,
   Themed, ThemeSwatch, VARIANT_THEMES,
   AlertsLedger, EntityPanel, DevicePanel, MitreGrid, RiskScore,
   CaseHeader, TimelineActions,
   recomputeHypotheses */

const { useState: us, useEffect: ue, useCallback: uc } = React;

// ── Watson narrative states - Marcus Chen incident ───────────────────
const NARRATIVE_B = `The 02:47 login from a corporate IP bears marking: an hour no calendar event explains, from a device that resolves as Marcus Chen's known machine. From there the account moves with patience. A query against the customers_pii columns of prod-db-01 returns four hundred and twelve thousand rows. An IAM key is minted. An upload commences toward a personal Dropbox tenant.\n\nA second hand on the same operator, or the operator himself? The new device fingerprint at 14:23 suggests the first; the cadence and target selection suggest the second.`;

// 1-pin state: only the 02:47 login pinned
const NARRATIVE_EARLY = `The pocket is empty. I am watching the ledger.\n\nThree disturbances draw my attention without yet asking for it: a login at 02:47 UTC that no schedule explains, a multi-factor prompt accepted after six rejections, and a query volume against prod-db-01 that is, by any honest reading, eight hundred and forty percent above Marcus Chen's thirty-day baseline.\n\nPin one of these and I will begin a draft.`;

// 3-pin state: login + MFA + PII query pinned
const NARRATIVE_MID = `Marcus Chen accepted a multi-factor prompt at 03:41 after five prior rejections within three minutes. The fatigue pattern is deliberate. Fifty-four minutes earlier, a login arrived at 02:47 from a corporate IP at an hour no calendar event explains.\n\nThis alone is not yet a story. But if the next pin is the 04:51 Dropbox upload, I will commit it to a draft.`;

// ── Pinning animation strip - three stills ──────────────────────────
function PinFrame({ stage }) {
  const stages = {
    1: { brush: [0.154, 0.202], copy: 'Drag-select: 03:41 MFA accept through 04:51 Dropbox upload' },
    2: { brush: [0.154, 0.202], copy: 'Watson lifts the region toward the pocket' },
    3: { brush: null, copy: 'Sealed. H1 Insider exfiltration climbs +18 pts.' },
  };
  const s = stages[stage] || stages[1];
  return (
    <div style={{ position: 'relative', width: '100%', height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--parchment)' }}>
      <div style={{ padding: '14px 18px 10px', borderBottom: '1px solid var(--rule)', display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
        <span className="serif" style={{ fontSize: 14, fontStyle: 'italic', color: 'var(--ink)' }}>Frame {stage} of 3</span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--ink-mute)' }}>pin animation - Marcus Chen case</span>
      </div>
      <div style={{ flex: 1, padding: 16, overflow: 'hidden', position: 'relative' }}>
        <Timeline mode="area" brush={s.brush} pinned={stage === 3 ? [[0.154, 0.202]] : []} width={520} height={170} hideAxis />
        {stage === 2 && (
          <div style={{
            position: 'absolute', left: 188, top: 78,
            padding: '6px 10px', background: 'var(--wax-wash)', border: '1px solid var(--wax-soft)',
            font: '500 11px/1 var(--mono)', color: 'var(--wax)',
            display: 'flex', alignItems: 'center', gap: 8,
            transform: 'rotate(-3deg)',
          }}>
            <Pin size={11} /> 03:41 to 04:51 - MFA to Dropbox
          </div>
        )}
        {stage === 3 && (
          <div style={{
            position: 'absolute', right: 16, top: 12,
            padding: '6px 10px', background: 'var(--paper)', border: '1px solid var(--plum-soft)',
            font: '500 10.5px/1 var(--mono)', color: 'var(--plum)',
          }}>
            up +18 H1 - Insider exfiltration
          </div>
        )}
      </div>
      <div style={{ padding: '12px 18px', borderTop: '1px solid var(--rule)' }}>
        <span className="serif" style={{ fontSize: 13, fontStyle: 'italic', color: 'var(--ink-soft)' }}>{s.copy}</span>
      </div>
    </div>
  );
}

// ── Hover chip on timeline event ────────────────────────────────────
function HoverChip() {
  return (
    <div style={{ width: '100%', height: '100%', padding: 16, background: 'var(--parchment)', display: 'flex', flexDirection: 'column', gap: 12 }}>
      <div style={{ position: 'relative' }}>
        <Timeline mode="area" hoverDay={0.172} pinned={[]} width={520} height={170} hideAxis />
        <div style={{
          position: 'absolute', left: 280, top: 22,
          background: 'var(--paper)', border: '1px solid var(--rule)',
          padding: '10px 12px', minWidth: 220,
        }}>
          <div className="mono num" style={{ fontSize: 10.5, color: 'var(--brick)', marginBottom: 4 }}>04:08 UTC - 5 Mar 2026</div>
          <div style={{ font: '500 12.5px/1.3 var(--sans)', color: 'var(--ink)' }}>
            DB query spike - customers_pii - 412 198 rows
          </div>
          <div className="mono" style={{ fontSize: 10, color: 'var(--ink-mute)', marginTop: 6 }}>
            prod-db-01 / customers_pii.* - m.chen
          </div>
          <div style={{ display: 'flex', gap: 6, marginTop: 8 }}>
            <Tag tone="brick" solid>SEV-1</Tag>
            <Tag tone="ink">T1213</Tag>
            <Tag tone="plum">pin to pocket</Tag>
          </div>
        </div>
      </div>
      <div className="serif" style={{ fontSize: 12.5, fontStyle: 'italic', color: 'var(--ink-mute)', lineHeight: 1.5 }}>
        Hover any event to read its testimony. Pin it, and Watson re-weighs the case.
      </div>
    </div>
  );
}

// ── Watson rail framed in a card ────────────────────────────────────
function RailCard({ children, sub }) {
  return (
    <div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--parchment-2)' }}>
      <div style={{ padding: '12px 16px', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
        <span className="smallcaps" style={{ color: 'var(--plum)' }}>Watson</span>
        <span className="mono" style={{ fontSize: 9.5, color: 'var(--ink-mute)' }}>{sub}</span>
      </div>
      <div style={{ flex: 1, minHeight: 0 }}>{children}</div>
    </div>
  );
}

// ── Default clue IDs: first 3 clues (early investigation state) ──────
const DEFAULT_CLUE_IDS = new Set();

// ── Live product mockup ─────────────────────────────────────────────
function LiveMockup() {
  const [clueIds, setClueIds]             = us(() => new Set(DEFAULT_CLUE_IDS));
  const [timelineMode, setTimelineMode]   = us('bars');
  const [showCompare, setShowCompare]     = us(false);
  const [commandValue, setCommandValue]   = us('');
  const [suggestionsOpen, setSuggestionsOpen] = us(false);

  // Live brush state (pointer-driven in Timeline)
  const [brush, setBrush] = us(null);

  // Pinned timeline regions: Array of [startDay, endDay]
  const [pinnedRegions, setPinnedRegions] = us([]);

  // Set body background
  ue(() => {
    document.body.style.background = '#0F1525';
    document.body.style.margin = '0';
    document.body.style.padding = '0';
    document.body.style.overflow = 'hidden';
    return () => {
      document.body.style.background = '';
      document.body.style.overflow = '';
    };
  }, []);

  // Derive clues array from clueIds, preserving insertion order
  const allClues = [...EVIDENCE, ...EVIDENCE_TWIST];
  const clues = allClues.filter(c => clueIds.has(c.id));

  // Recompute hypothesis ranking from clues
  const ranked = recomputeHypotheses(clues, HYPOTHESES);

  function handleCommand(raw) {
    const v = raw.toLowerCase();
    let newMode = timelineMode;
    let newCompare = showCompare;

    if (v.includes('two lanes') || v.includes('lanes'))   newMode = 'lanes';
    else if (v.includes('bars'))                           newMode = 'bars';
    else if (v.includes('line') || v.includes('area'))    newMode = 'area';

    if (v.includes('compare')) newCompare = true;
    if (v.includes('no compare') || v.includes('hide compare')) newCompare = false;

    setTimelineMode(newMode);
    setShowCompare(newCompare);
    setCommandValue(raw);
    setSuggestionsOpen(true);
    setTimeout(() => setSuggestionsOpen(false), 2400);
  }

  // Timeline brush callbacks
  const handleBrushChange = uc((b) => {
    setBrush(b);
  }, []);

  const handlePinRegion = uc((region) => {
    const [start, end] = region;
    // Pin every clue whose .day falls within the brushed region
    const matched = allClues.filter(c => c.day != null && c.day >= start && c.day <= end);
    const matchedIds = matched.map(c => c.id);
    if (matchedIds.length > 0) {
      setClueIds(prev => {
        const next = new Set(prev);
        matchedIds.forEach(id => next.add(id));
        return next;
      });
    }
    // Stash the matched IDs on the region so unpin can reverse
    setPinnedRegions(prev => [...prev, [start, end, matchedIds]]);
    setBrush(null);
  }, [allClues]);

  const handleUnpinRegion = uc((idx) => {
    setPinnedRegions(prev => {
      const region = prev[idx];
      const idsToRemove = region && region[2] ? region[2] : [];
      if (idsToRemove.length > 0) {
        setClueIds(prevSet => {
          const next = new Set(prevSet);
          idsToRemove.forEach(id => next.delete(id));
          return next;
        });
      }
      return prev.filter((_, i) => i !== idx);
    });
  }, []);

  const handleResizeRegion = uc((idx, which, day) => {
    setPinnedRegions(prev => prev.map((r, i) => {
      if (i !== idx) return r;
      const [a, b, ids] = r;
      const next = which === 'start'
        ? [Math.min(day, b - 0.01), b]
        : [a, Math.max(day, a + 0.01)];
      // Recompute matched clues for new range
      const matched = allClues.filter(c => c.day != null && c.day >= next[0] && c.day <= next[1]);
      const newIds = matched.map(c => c.id);
      // Reconcile clueIds: remove old set, add new set
      setClueIds(prevSet => {
        const result = new Set(prevSet);
        (ids || []).forEach(id => { if (!newIds.includes(id)) result.delete(id); });
        newIds.forEach(id => result.add(id));
        return result;
      });
      return [next[0], next[1], newIds];
    }));
  }, [allClues]);

  // Alert row click: find matching clue entry by time and add to clueIds
  const handlePinAlert = uc((alertObj) => {
    const match = allClues.find(e => e.t === alertObj.t);
    const idToAdd = match ? match.id : alertObj.id;
    setClueIds(prev => new Set([...prev, idToAdd]));
  }, [allClues]);

  // Remove a clue by id (trash button in Pocket)
  const handleUnpin = uc((id) => {
    setClueIds(prev => {
      const next = new Set(prev);
      next.delete(id);
      return next;
    });
  }, []);

  // Focus a pocket clue: highlight the corresponding day on the timeline
  const handleFocus = uc((pin) => {
    if (pin.day != null) {
      const halfHour = 0.5 / 24;
      setBrush([pin.day - halfHour, pin.day + halfHour]);
      setTimeout(() => setBrush(null), 1800);
    }
  }, []);

  return (
    <div style={{ width: '100vw', height: '100vh', overflow: 'hidden', position: 'relative' }}>
      <Themed themeKey="evening">
        <InvestigationScreen
          variant="A"
          pins={clues}
          ranked={ranked}
          brush={brush}
          pinned={pinnedRegions}
          timelineMode={timelineMode}
          showCompare={showCompare}
          commandValue={commandValue}
          suggestionsOpen={suggestionsOpen}
          onCommand={handleCommand}
          onBrushChange={handleBrushChange}
          onPinRegion={handlePinRegion}
          onUnpinRegion={handleUnpinRegion}
          onResizeRegion={handleResizeRegion}
          onPinAlert={handlePinAlert}
          onUnpin={handleUnpin}
          onFocus={handleFocus}
          onTimelineModeChange={setTimelineMode}
        />
      </Themed>
    </div>
  );
}

// ── Design canvas view (preserved, accessible via ?canvas=1) ────────
function DesignCanvasView() {
  return (
    <DesignCanvas>
      <DCSection id="overview" title="Sherlock - Incident Investigation"
        subtitle="A SOC console where the analyst is Sherlock and Watson is a smart pocket. Evening study direction across the hero screens.">

        <DCArtboard id="A" label="A - Library, full case ledger" width={1440} height={900}>
          <Themed themeKey="evening">
            <InvestigationScreen variant="A" />
          </Themed>
        </DCArtboard>

        <DCArtboard id="B" label="B - Library, mid-investigation, command bar live" width={1440} height={900}>
          <Themed themeKey="evening">
            <InvestigationScreen
              variant="A"
              pins={EVIDENCE.slice(0, 3)}
              ranked={recomputeHypotheses(EVIDENCE.slice(0, 3), HYPOTHESES)}
              brush={[0.172, 0.221]}
              pinned={[[0.116, 0.172]]}
              commandValue="show me logins from Bucharest in the last 72h"
              suggestionsOpen
            />
          </Themed>
        </DCArtboard>

        <DCArtboard id="C" label="C - After agentic command: switch timeline to two lanes" width={1440} height={900}>
          <Themed themeKey="evening">
            <InvestigationScreen
              variant="A"
              pins={EVIDENCE.slice(0, 4)}
              ranked={recomputeHypotheses(EVIDENCE.slice(0, 4), HYPOTHESES)}
              pinned={[[0.116, 0.172], [0.172, 0.221]]}
              timelineMode="lanes"
              showCompare
            />
          </Themed>
        </DCArtboard>

      </DCSection>

      <DCSection id="timeline" title="Timeline component"
        subtitle="The hero widget. Brush-select to pin a region; agentic commands reshape it.">

        <DCArtboard id="t-default" label="Default - area" width={720} height={380}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', padding: 22 }}>
              <div className="smallcaps" style={{ marginBottom: 8 }}>Timeline - default</div>
              <Timeline mode="area" width={672} height={300} />
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="t-brush" label="Brush selecting - 02:47 to 05:17 attack window" width={720} height={380}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', padding: 22 }}>
              <div className="smallcaps" style={{ marginBottom: 8 }}>Brush selecting - 02:47 UTC to 05:17 UTC (5 Mar 2026)</div>
              <Timeline mode="area" brush={[0.116, 0.222]} width={672} height={300} />
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="t-pinned" label="Pinned regions - login + exfil chain" width={720} height={380}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', padding: 22 }}>
              <div className="smallcaps" style={{ marginBottom: 8 }}>Two regions pinned: login window + device/geo twist (Day 1)</div>
              <Timeline mode="area" pinned={[[0.116, 0.222], [1.58, 1.68]]} width={672} height={300} />
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="t-bars" label="Command applied - bars" width={720} height={380}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', padding: 22 }}>
              <div className="smallcaps" style={{ marginBottom: 8 }}>
                Watson - "switch timeline to bars"
              </div>
              <Timeline mode="bars" pinned={[[0.116, 0.222]]} width={672} height={300} />
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="t-lanes" label="Command - split into two lanes" width={720} height={380}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', padding: 22 }}>
              <div className="smallcaps" style={{ marginBottom: 8 }}>
                Watson - "split into auth + data lanes"
              </div>
              <Timeline mode="lanes" width={672} height={300} />
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="t-compare" label="Command - compare to last week" width={720} height={380}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', padding: 22 }}>
              <div className="smallcaps" style={{ marginBottom: 8 }}>
                Watson - "compare to last week"
              </div>
              <Timeline mode="area" showCompare width={672} height={300} />
            </div>
          </Themed>
        </DCArtboard>

      </DCSection>

      <DCSection id="watson" title="Watson - the smart pocket"
        subtitle="Pocket / hypotheses / live narrative. Watson rewrites the top hypothesis as evidence pins; lower hypotheses keep their own draft.">

        <DCArtboard id="w-empty" label="1-pin - 02:47 login only" width={340} height={780}>
          <Themed themeKey="evening">
            <RailCard sub="02:47 UTC - case opened">
              <WatsonRail
                pins={EVIDENCE.slice(0, 1)}
                hypos={HYPOTHESES.map(h => ({ ...h, conf: h.conf * 0.40, delta: 0, evidence: 1 }))}
                narrative={NARRATIVE_EARLY}
                writing={false}
                narrativeHeight={170}
              />
            </RailCard>
          </Themed>
        </DCArtboard>

        <DCArtboard id="w-one" label="3-pin - login + MFA + PII query" width={340} height={780}>
          <Themed themeKey="evening">
            <RailCard sub="04:08 UTC - 81 min elapsed">
              <WatsonRail
                pins={EVIDENCE.slice(0, 3)}
                hypos={[
                  { ...HYPOTHESES[0], conf: 0.54, delta: +0.14, evidence: 3 },
                  { ...HYPOTHESES[1], conf: 0.28, delta: +0.06, evidence: 1 },
                  { ...HYPOTHESES[2], conf: 0.12, delta: -0.02, evidence: 0 },
                ]}
                narrative={NARRATIVE_MID}
                writing={true}
                narrativeHeight={170}
              />
            </RailCard>
          </Themed>
        </DCArtboard>

        <DCArtboard id="w-many" label="6-pin - full exfil chain - twist markers" width={340} height={900}>
          <Themed themeKey="evening">
            <RailCard sub="16:05 UTC - 13h 18m elapsed">
              <WatsonRail
                pins={[...EVIDENCE, ...EVIDENCE_TWIST]}
                hypos={HYPOTHESES}
                narrative={NARRATIVE}
                writing={true}
                narrativeHeight={200}
              />
            </RailCard>
          </Themed>
        </DCArtboard>

        <DCArtboard id="w-pin-anim" label="Pinning - 3 frames" width={620} height={780}>
          <Themed themeKey="evening">
            <div style={{ height: '100%', display: 'grid', gridTemplateRows: '1fr 1fr 1fr', background: 'var(--parchment)' }}>
              <div style={{ borderBottom: '1px solid var(--rule)' }}><PinFrame stage={1} /></div>
              <div style={{ borderBottom: '1px solid var(--rule)' }}><PinFrame stage={2} /></div>
              <div><PinFrame stage={3} /></div>
            </div>
          </Themed>
        </DCArtboard>
      </DCSection>

      <DCSection id="interactions" title="Interactions and micro-states"
        subtitle="Command-bar suggestions, hover-on-event, hypothesis-rerank moment.">

        <DCArtboard id="i-cmd" label="Command bar - suggestions open" width={720} height={460}>
          <Themed themeKey="evening">
            <div style={{ background: 'var(--parchment)', height: '100%', position: 'relative', overflow: 'hidden' }}>
              <TopBar suggestionsOpen />
              <div style={{ padding: 24, opacity: 0.5, pointerEvents: 'none' }}>
                <Timeline mode="area" width={620} height={220} />
              </div>
              <div style={{ position: 'absolute', left: 90, top: 50 }}>
                <CommandSuggestions />
              </div>
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="i-hover" label="Hover on event - testimony chip" width={620} height={420}>
          <Themed themeKey="evening">
            <HoverChip />
          </Themed>
        </DCArtboard>

        <DCArtboard id="i-rerank" label="Hypothesis rerank - before / after pin" width={720} height={460}>
          <Themed themeKey="evening">
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', height: '100%', background: 'var(--parchment)' }}>
              <div style={{ padding: 18, borderRight: '1px solid var(--rule)' }}>
                <div className="smallcaps" style={{ marginBottom: 8 }}>Before pin</div>
                {[
                  { ...HYPOTHESES[0], conf: 0.56, delta: 0, evidence: 3 },
                  { ...HYPOTHESES[1], conf: 0.50, delta: 0, evidence: 2 },
                  { ...HYPOTHESES[2], conf: 0.18, delta: 0, evidence: 0 },
                ].map((h, i) => <HypothesisCard key={h.id} h={h} rank={i + 1} top={false} />)}
              </div>
              <div style={{ padding: 18, background: 'var(--paper)' }}>
                <div className="smallcaps" style={{ color: 'var(--plum)', marginBottom: 8 }}>
                  After pin - 04:08 PII query
                </div>
                {HYPOTHESES.map((h, i) => <HypothesisCard key={h.id} h={h} rank={i + 1} top={i === 0} />)}
              </div>
            </div>
          </Themed>
        </DCArtboard>

        <DCArtboard id="i-narrative" label="Narrative - self-revising" width={620} height={460}>
          <Themed themeKey="evening">
            <div style={{ height: '100%', background: 'var(--paper)', padding: 22, display: 'flex', flexDirection: 'column', gap: 14 }}>
              <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
                <div className="serif" style={{ fontSize: 16, fontStyle: 'italic', color: 'var(--ink)' }}>Watson's draft, in revision</div>
                <span className="mono" style={{ fontSize: 10, color: 'var(--plum)' }}>
                  <span className="wax-dot" style={{ display: 'inline-block', verticalAlign: 'middle', marginRight: 6, background: 'var(--plum)', width: 5, height: 5 }} /> revising paragraph 2
                </span>
              </div>
              <p className="serif" style={{ fontSize: 13.5, lineHeight: 1.6, color: 'var(--ink-soft)', margin: 0 }}>
                At forty-seven minutes past two this morning, Marcus Chen, Senior Database Administrator and privileged operator on prod-db-01, authenticated to the corporate network from an IP address associated with his known device. The hour is unusual. No on-call rotation, no scheduled maintenance window, no approval chain.
              </p>
              <p className="serif" style={{ fontSize: 13.5, lineHeight: 1.6, color: 'var(--ink-soft)', margin: 0 }}>
                <span style={{ background: 'var(--plum-wash)', borderBottom: '1px dashed var(--plum)' }}>From that foothold the account proceeded with patience.</span>{' '}
                <span style={{ color: 'var(--ink-faint)', textDecoration: 'line-through' }}>The sequence that followed reads as opportunistic.</span>
              </p>
              <p className="serif" style={{ fontSize: 13.5, lineHeight: 1.6, color: 'var(--ink-soft)', margin: 0 }}>
                A query against the customers_pii columns of prod-db-01 returned four hundred and twelve thousand rows. <span style={{ display: 'inline-block', width: 6, height: 14, background: 'var(--plum)', verticalAlign: '-2px', animation: 'cursor-blink 1s steps(2) infinite' }} />
              </p>
            </div>
          </Themed>
        </DCArtboard>

      </DCSection>

      <DCSection id="styles" title="Style explorations"
        subtitle="Same screen, different surface treatments. Wrappers swap design tokens without touching the layout.">

        {['vellum', 'bold', 'evening', 'foolscap'].map((key) => {
          const t = VARIANT_THEMES[key];
          return (
            <DCArtboard key={key} id={'st-' + key} label={t.label + ' - ' + t.sub} width={1440} height={900}>
              <Themed themeKey={key}>
                <InvestigationScreen
                  variant="A"
                  pins={EVIDENCE.slice(0, 3)}
                  ranked={recomputeHypotheses(EVIDENCE.slice(0, 3), HYPOTHESES)}
                  pinned={[[0.116, 0.172]]}
                />
              </Themed>
            </DCArtboard>
          );
        })}

        <DCArtboard id="st-swatches" label="Swatch comparison" width={620} height={900}>
          <div style={{ height: '100%', background: '#F4EFE6', padding: 28, display: 'flex', flexDirection: 'column', gap: 22, fontFamily: 'var(--sans)' }}>
            <div className="serif" style={{ fontSize: 22, color: '#1B2238' }}>Token swatches</div>
            <div style={{ fontSize: 12, color: '#6B6F82', marginTop: -16 }}>parchment - paper - ink - brick - mustard - teal - plum - wax</div>
            {['original', 'vellum', 'bold', 'evening', 'foolscap'].map((key) => {
              const isOg = key === 'original';
              const t = isOg
                ? { label: 'Original - Library', sub: 'Baseline Victorian pastel.' }
                : VARIANT_THEMES[key];
              return (
                <div key={key} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                  <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
                    <span className="serif" style={{ fontSize: 15, color: '#1B2238', fontStyle: 'italic' }}>{t.label}</span>
                    <span className="mono" style={{ fontSize: 10, color: '#8E8597', letterSpacing: '.08em', textTransform: 'uppercase' }}>{key}</span>
                  </div>
                  <div style={{ fontSize: 11.5, color: '#6B6F82', lineHeight: 1.4 }}>{t.sub}</div>
                  {!isOg && <ThemeSwatch themeKey={key} />}
                  {isOg && (
                    <div style={{ display: 'flex' }}>
                      {['#F4EFE6', '#FBF8F1', '#1B2238', '#C56B5C', '#C9A24A', '#6E9D9C', '#8E6E94', '#9C3A2A'].map(c =>
                        <div key={c} style={{ width: 22, height: 22, background: c, border: '1px solid rgba(0,0,0,0.05)' }} />
                      )}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </DCArtboard>

      </DCSection>
    </DesignCanvas>
  );
}

// ── Root App: branch on ?canvas=1 ──────────────────────────────────
function App() {
  const isCanvas = new URLSearchParams(window.location.search).get('canvas') === '1';
  if (isCanvas) return <DesignCanvasView />;
  return <LiveMockup />;
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
