// Loop MVP — Today modules (orchestrated by the AI coach layer)
// Each module is a self-contained card. The orchestrator on HomeScreen
// decides which to show, in what order, ranked by relevance to the day.

const Dm = () => window.LOOP_DATA;

// ─────────────────────────────────────────────────────────────
// ModuleFrame — common chrome: agent attribution + dismiss
// ─────────────────────────────────────────────────────────────
function ModuleFrame({ agent, children, style = {}, onDismiss }) {
  return (
    <div style={{ marginBottom: 4 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '0 4px 8px' }}>
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <div style={{ width: 18, height: 18, borderRadius: '50%', background: 'var(--ink)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="sparkles" size={11} color="var(--canvas)" />
          </div>
          <span style={{ fontSize: 11, fontWeight: 500, letterSpacing: '0.04em',
            textTransform: 'uppercase', color: 'var(--slate)' }}>
            {agent}
          </span>
        </div>
        {onDismiss && (
          <button onClick={onDismiss} style={{ background: 'transparent', border: 'none',
            cursor: 'pointer', color: 'var(--slate)', padding: 4 }}>
            <Icon name="x" size={14} color="var(--slate)" />
          </button>
        )}
      </div>
      <div style={style}>{children}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// InsightsModule — people / company / industry insights with CTAs
// ─────────────────────────────────────────────────────────────
function InsightsModule({ persona }) {
  const list = Dm().insights[persona];
  return (
    <Section eyebrow="Today's signals" title="What changed since you slept"
      action={<Chip tone="success"><Dot tone="success" size={6} /> Live</Chip>}>
      <div style={{ display: 'flex', gap: 12, overflowX: 'auto', margin: '0 -22px',
        scrollSnapType: 'x mandatory', scrollPaddingLeft: 22 }}>
        {/* Leading spacer aligns the first card with the section title left edge */}
        <div style={{ flexShrink: 0, width: 22 }} aria-hidden="true" />
        {list.map(i => (
          <div key={i.id} style={{ minWidth: 300, scrollSnapAlign: 'start' }}>
            <InsightCard insight={i} />
          </div>
        ))}
        {/* Trailing spacer gives the last card breathing room on the right */}
        <div style={{ flexShrink: 0, width: 22 }} aria-hidden="true" />
      </div>
    </Section>
  );
}

function InsightCard({ insight }) {
  const [drafting, setDrafting] = React.useState(false);
  const [draft, setDraft] = React.useState(insight.draft || '');
  const [sent, setSent] = React.useState(false);
  const [shared, setShared] = React.useState(false);

  const signalColor = { high: 'var(--loop-orange)', med: 'var(--loop-orange-light)', low: 'var(--dust)' }[insight.signal];

  const handleCTA = () => {
    if (insight.draft) setDrafting(true);
    else if (insight.shareTo) setShared(true);
    else setSent(true);
  };

  return (
    <Card style={{ padding: '20px 20px 20px 24px', position: 'relative', overflow: 'hidden' }}>
      <div style={{ position: 'absolute', left: 10, top: 14, bottom: 14, width: 3, borderRadius: 2, background: signalColor }} />
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
        <Chip tone={insight.signal === 'high' ? 'warning' : 'default'}>{insight.eyebrow}</Chip>
        {insight.person && (
          <Avatar initials={insight.person.name.split(' ').map(w => w[0]).join('').slice(0, 2)}
            tint="var(--ink)" size={22} photo={insight.person.photo} />
        )}
      </div>
      <div style={{ fontSize: 16, fontWeight: 500, letterSpacing: '-0.01em', lineHeight: 1.3,
        marginBottom: 8 }}>{insight.headline}</div>
      <div style={{ fontSize: 13, color: 'var(--slate)', lineHeight: 1.4, marginBottom: 16 }}>{insight.body}</div>

      {!drafting && !sent && !shared && (
        <button onClick={handleCTA} style={{
          display: 'inline-flex', alignItems: 'center', gap: 8,
          padding: '8px 14px', borderRadius: 999,
          background: 'var(--ink)', color: 'var(--canvas)', border: 'none',
          fontSize: 12, fontWeight: 500, cursor: 'pointer', fontFamily: 'var(--font-sans)',
        }}>
          <Icon name={insight.ctaIcon || 'arrow-right'} size={14} color="var(--canvas)" />
          {insight.cta}
        </button>
      )}

      {drafting && (
        <div style={{ marginTop: 4 }}>
          <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
            textTransform: 'uppercase', color: 'var(--slate)', marginBottom: 6 }}>
            Draft · in your voice
          </div>
          <textarea value={draft} onChange={(e) => setDraft(e.target.value)} rows={5}
            style={{ width: '100%', padding: 12, borderRadius: 16,
              border: '1px solid rgba(20,20,19,0.18)', background: 'var(--canvas)',
              fontFamily: 'var(--font-sans)', fontSize: 13, lineHeight: 1.45,
              resize: 'none', outline: 'none', boxSizing: 'border-box' }} />
          <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
            <button onClick={() => setDrafting(false)} style={{
              padding: '8px 12px', borderRadius: 999, background: 'transparent',
              border: '1.5px solid var(--ink)', cursor: 'pointer',
              fontSize: 12, fontWeight: 500, fontFamily: 'var(--font-sans)', color: 'var(--ink)',
            }}>Cancel</button>
            <button onClick={() => { setDrafting(false); setSent(true); }} style={{
              flex: 1, padding: '8px 12px', borderRadius: 999,
              background: 'var(--loop-orange)', color: 'var(--white)', border: 'none',
              cursor: 'pointer', fontSize: 12, fontWeight: 500, fontFamily: 'var(--font-sans)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
            }}>
              <Icon name="send" size={14} color="var(--white)" /> Send
            </button>
          </div>
        </div>
      )}

      {sent && (
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8,
          padding: '8px 14px', borderRadius: 999,
          background: 'rgba(31,122,77,0.12)', color: 'var(--success)',
          fontSize: 12, fontWeight: 500 }}>
          <Icon name="check-circle" size={14} color="var(--success)" /> Sent · tracked in your CRM
        </div>
      )}

      {shared && insight.shareTo && (
        <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8,
          padding: '8px 14px', borderRadius: 999,
          background: 'rgba(31,122,77,0.12)', color: 'var(--success)',
          fontSize: 12, fontWeight: 500 }}>
          <Icon name="share-2" size={14} color="var(--success)" /> Shared with {insight.shareTo.join(', ')}
        </div>
      )}
    </Card>
  );
}
// ─────────────────────────────────────────────────────────────
// WeatherModule — weather + outfit recommendation (FULL — for solo use)
// ─────────────────────────────────────────────────────────────
function WeatherModule({ persona }) {
  const w = Dm().weather[persona];
  return (
    <Section eyebrow="Weather · outfit" title="">
      <Card style={{ padding: 22, position: 'relative', overflow: 'hidden' }}>
        <div style={{ position: 'absolute', right: -30, top: -30, width: 140, height: 140,
          borderRadius: '50%', background: 'rgba(243,115,56,0.06)' }} />
        <div style={{ position: 'relative' }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
            <div>
              <Eyebrow>{w.city}</Eyebrow>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginTop: 10 }}>
                <div style={{ fontSize: 52, fontWeight: 500, letterSpacing: '-0.03em', lineHeight: 1 }}>
                  {w.tempF}°
                </div>
                <div style={{ fontSize: 13, color: 'var(--slate)' }}>
                  H {w.hi}° · L {w.lo}°
                </div>
              </div>
              <div style={{ marginTop: 8, fontSize: 14, color: 'var(--ink)' }}>{w.summary}</div>
            </div>
            <div style={{ width: 64, height: 64, borderRadius: '50%', background: 'var(--canvas-whisper)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon name={w.icon} size={30} />
            </div>
          </div>

          {/* Hourly */}
          <div style={{ display: 'flex', gap: 14, marginTop: 18, overflowX: 'auto',
            borderTop: '1px solid rgba(20,20,19,0.08)', paddingTop: 16 }}>
            {w.hours.map(h => (
              <div key={h.t} style={{ flexShrink: 0, textAlign: 'center', minWidth: 36 }}>
                <div style={{ fontSize: 11, color: 'var(--slate)', fontWeight: 500 }}>{h.t}</div>
                <Icon name={h.icon} size={20} style={{ margin: '6px 0' }} />
                <div style={{ fontSize: 13, fontWeight: 500 }}>{h.temp}°</div>
              </div>
            ))}
          </div>

          {/* Outfit suggestion */}
          <div style={{ marginTop: 18, padding: 16, borderRadius: 18, background: 'var(--canvas-whisper)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
              <Icon name="shirt" size={16} />
              <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.06em',
                textTransform: 'uppercase', color: 'var(--ink)' }}>What to wear</span>
            </div>
            <div style={{ fontSize: 14, fontWeight: 500, lineHeight: 1.35 }}>{w.outfit.headline}</div>
            <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {w.outfit.items.map((it, i) => <Chip key={i}>{it}</Chip>)}
            </div>
            <div style={{ marginTop: 10, fontSize: 12, color: 'var(--slate)', lineHeight: 1.4 }}>
              {w.outfit.reason}
            </div>
          </div>
        </div>
      </Card>
    </Section>
  );
}

// ─────────────────────────────────────────────────────────────
// BriefingPair — compact 2-col layout combining weather + health
// Used when both modules are enabled (default). Each tile expands
// inline on tap to reveal the full content beneath the row.
// ─────────────────────────────────────────────────────────────
function BriefingPair({ persona }) {
  const w = Dm().weather[persona];
  const h = Dm().health[persona];
  const [expanded, setExpanded] = React.useState(null); // 'weather' | 'health' | null

  return (
    <Section eyebrow="Briefing · this morning" title="">
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <WeatherTile w={w} active={expanded === 'weather'}
          onClick={() => setExpanded(expanded === 'weather' ? null : 'weather')} />
        <HealthTile h={h} active={expanded === 'health'}
          onClick={() => setExpanded(expanded === 'health' ? null : 'health')} />
      </div>

      {/* Expanded panel — slides in below */}
      {expanded === 'weather' && <WeatherExpanded w={w} onClose={() => setExpanded(null)} />}
      {expanded === 'health' && <HealthExpanded h={h} onClose={() => setExpanded(null)} />}
    </Section>
  );
}

function WeatherTile({ w, active, onClick }) {
  return (
    <button onClick={onClick} style={{
      textAlign: 'left', padding: 16, borderRadius: 22,
      background: active ? 'var(--ink)' : 'var(--canvas-lifted)',
      color: active ? 'var(--canvas)' : 'var(--ink)',
      border: 'none', cursor: 'pointer', fontFamily: 'var(--font-sans)',
      display: 'flex', flexDirection: 'column', gap: 6, minHeight: 130,
      transition: 'background 200ms',
    }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8 }}>
        <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
          textTransform: 'uppercase', color: active ? 'rgba(252,251,250,0.6)' : 'var(--slate)' }}>
          {w.city.split(' · ')[0]}
        </div>
        <Icon name={w.icon} size={22} color={active ? 'var(--canvas)' : 'var(--ink)'} />
      </div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginTop: 'auto' }}>
        <div style={{ fontSize: 36, fontWeight: 500, letterSpacing: '-0.025em', lineHeight: 1 }}>
          {w.tempF}°
        </div>
        <div style={{ fontSize: 11, color: active ? 'rgba(252,251,250,0.6)' : 'var(--slate)' }}>
          H{w.hi} · L{w.lo}
        </div>
      </div>
      <div style={{ fontSize: 12, lineHeight: 1.3,
        color: active ? 'rgba(252,251,250,0.85)' : 'var(--ink)',
        overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box',
        WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' }}>{w.summary}</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 5,
        fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
        textTransform: 'uppercase',
        color: active ? 'var(--loop-orange-light)' : 'var(--loop-orange)' }}>
        <Icon name="shirt" size={11}
          color={active ? 'var(--loop-orange-light)' : 'var(--loop-orange)'} />
        Outfit ready
      </div>
    </button>
  );
}

function HealthTile({ h, active, onClick }) {
  const ringR = 18, ringC = 2 * Math.PI * ringR;
  const fill = (h.readiness / 100) * ringC;
  return (
    <button onClick={onClick} style={{
      textAlign: 'left', padding: 16, borderRadius: 22,
      background: active ? 'var(--ink)' : 'var(--canvas-lifted)',
      color: active ? 'var(--canvas)' : 'var(--ink)',
      border: 'none', cursor: 'pointer', fontFamily: 'var(--font-sans)',
      display: 'flex', flexDirection: 'column', gap: 6, minHeight: 130,
      transition: 'background 200ms',
    }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8 }}>
        <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
          textTransform: 'uppercase', color: active ? 'rgba(252,251,250,0.6)' : 'var(--slate)' }}>
          Health · coach
        </div>
        <svg width="48" height="48" viewBox="0 0 48 48">
          <circle cx="24" cy="24" r={ringR} fill="none"
            stroke={active ? 'rgba(252,251,250,0.18)' : 'rgba(20,20,19,0.08)'} strokeWidth="4" />
          <circle cx="24" cy="24" r={ringR} fill="none"
            stroke="var(--loop-orange)" strokeWidth="4" strokeLinecap="round"
            strokeDasharray={`${fill} ${ringC}`}
            transform="rotate(-90 24 24)" />
          <text x="24" y="28" textAnchor="middle" fontSize="13" fontWeight="500"
            fill={active ? 'var(--canvas)' : 'var(--ink)'}
            fontFamily="Sofia Sans, -apple-system, sans-serif">{h.readiness}</text>
        </svg>
      </div>
      <div style={{ fontSize: 13, fontWeight: 500, marginTop: 'auto', letterSpacing: '-0.01em', lineHeight: 1.25,
        overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box',
        WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' }}>
        {h.recovery.charAt(0).toUpperCase() + h.recovery.slice(1)} recovery
      </div>
      <div style={{ display: 'flex', gap: 10, fontSize: 11,
        color: active ? 'rgba(252,251,250,0.7)' : 'var(--slate)' }}>
        <span><strong style={{ color: active ? 'var(--canvas)' : 'var(--ink)', fontWeight: 500 }}>{h.sleep.hours}h</strong> sleep</span>
        <span>·</span>
        <span><strong style={{ color: active ? 'var(--canvas)' : 'var(--ink)', fontWeight: 500 }}>{h.actions.length}</strong> actions</span>
      </div>
    </button>
  );
}

function WeatherExpanded({ w, onClose }) {
  return (
    <Card style={{ marginTop: 10, padding: 18, position: 'relative' }}>
      <button onClick={onClose} style={{ position: 'absolute', top: 14, right: 14,
        width: 28, height: 28, borderRadius: '50%', background: 'var(--canvas-whisper)',
        border: 'none', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
        <Icon name="x" size={14} />
      </button>
      <Eyebrow>{w.city}</Eyebrow>

      {/* Hourly */}
      <div style={{ display: 'flex', gap: 12, marginTop: 12, overflowX: 'auto',
        paddingBottom: 14, borderBottom: '1px solid rgba(20,20,19,0.06)' }}>
        {w.hours.map(hr => (
          <div key={hr.t} style={{ flexShrink: 0, textAlign: 'center', minWidth: 32 }}>
            <div style={{ fontSize: 10, color: 'var(--slate)', fontWeight: 500 }}>{hr.t}</div>
            <Icon name={hr.icon} size={18} style={{ margin: '4px 0' }} />
            <div style={{ fontSize: 12, fontWeight: 500 }}>{hr.temp}°</div>
          </div>
        ))}
      </div>

      {/* Outfit */}
      <div style={{ marginTop: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
          <Icon name="shirt" size={14} />
          <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.06em',
            textTransform: 'uppercase', color: 'var(--ink)' }}>What to wear</span>
        </div>
        <div style={{ fontSize: 13, fontWeight: 500, lineHeight: 1.35 }}>{w.outfit.headline}</div>
        <div style={{ marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5 }}>
          {w.outfit.items.map((it, i) => <Chip key={i}>{it}</Chip>)}
        </div>
        <div style={{ marginTop: 8, fontSize: 11, color: 'var(--slate)', lineHeight: 1.4 }}>
          {w.outfit.reason}
        </div>
      </div>
    </Card>
  );
}

function HealthExpanded({ h, onClose }) {
  const [done, setDone] = React.useState({});
  const toggle = (id) => setDone(d => ({ ...d, [id]: !d[id] }));
  return (
    <Card style={{ marginTop: 10, padding: 18, position: 'relative' }}>
      <button onClick={onClose} style={{ position: 'absolute', top: 14, right: 14,
        width: 28, height: 28, borderRadius: '50%', background: 'var(--canvas-whisper)',
        border: 'none', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
        <Icon name="x" size={14} />
      </button>
      <Eyebrow>Health · coach</Eyebrow>

      <div style={{ marginTop: 10, fontSize: 13, fontWeight: 500, lineHeight: 1.4, paddingRight: 30 }}>
        {h.headline}
      </div>

      {/* Vitals strip */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6,
        padding: '12px 0', marginTop: 8,
        borderTop: '1px solid rgba(20,20,19,0.06)',
        borderBottom: '1px solid rgba(20,20,19,0.06)' }}>
        {[{ label: 'Sleep', value: `${h.sleep.hours}h` }, ...h.vitals].map((v, i) => (
          <div key={i}>
            <div style={{ fontSize: 9, color: 'var(--slate)', textTransform: 'uppercase',
              letterSpacing: '0.04em', fontWeight: 700 }}>{v.label}</div>
            <div style={{ fontSize: 14, fontWeight: 500, marginTop: 2, letterSpacing: '-0.01em' }}>{v.value}</div>
          </div>
        ))}
      </div>

      {/* Actions */}
      <div style={{ marginTop: 4 }}>
        {h.actions.map((a, i) => (
          <div key={a.id} style={{ display: 'flex', alignItems: 'center', gap: 10,
            padding: '10px 0',
            borderBottom: i < h.actions.length - 1 ? '1px solid rgba(20,20,19,0.04)' : 'none' }}>
            <button onClick={() => toggle(a.id)} style={{
              width: 18, height: 18, borderRadius: '50%',
              background: done[a.id] ? 'var(--ink)' : 'transparent',
              border: '1.5px solid var(--ink)', cursor: 'pointer', flexShrink: 0,
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: 0,
            }}>
              {done[a.id] && <Icon name="check" size={10} color="var(--canvas)" />}
            </button>
            <div style={{ flex: 1, fontSize: 12, lineHeight: 1.35,
              textDecoration: done[a.id] ? 'line-through' : 'none',
              color: done[a.id] ? 'var(--slate)' : 'var(--ink)' }}>
              {a.body}
            </div>
            <span style={{ fontSize: 10, color: 'var(--slate)',
              textTransform: 'uppercase', letterSpacing: '0.04em', flexShrink: 0 }}>{a.when}</span>
          </div>
        ))}
      </div>
    </Card>
  );
}

// ─────────────────────────────────────────────────────────────
// SpotsModule — AI-recommended places near your day
// ─────────────────────────────────────────────────────────────
function SpotsModule({ persona }) {
  const s = Dm().spots[persona];
  return (
    <Section eyebrow="Places · today" title="Recommended near your day">
      <div style={{ fontSize: 12, color: 'var(--slate)', marginBottom: 14, padding: '0 4px' }}>
        {s.context}
      </div>
      <div style={{ display: 'flex', gap: 12, overflowX: 'auto', padding: '0 22px 4px', margin: '0 -22px' }}>
        {s.items.map(it => (
          <div key={it.id} style={{ minWidth: 240, flexShrink: 0,
            borderRadius: 24, overflow: 'hidden', background: 'var(--canvas-lifted)' }}>
            <div style={{ height: 140, backgroundImage: `url(${it.photo})`,
              backgroundSize: 'cover', backgroundPosition: 'center', position: 'relative' }}>
              <div style={{ position: 'absolute', top: 12, left: 12 }}>
                <Chip style={{ background: 'rgba(252,251,250,0.92)', color: 'var(--ink)' }}>{it.distance}</Chip>
              </div>
            </div>
            <div style={{ padding: 16 }}>
              <div style={{ fontSize: 15, fontWeight: 500, letterSpacing: '-0.01em' }}>{it.name}</div>
              <div style={{ fontSize: 12, color: 'var(--slate)', marginTop: 2 }}>{it.kind}</div>
              <div style={{ fontSize: 12, color: 'var(--ink)', marginTop: 8, lineHeight: 1.4 }}>{it.detail}</div>
              <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                {it.tags.map((t, i) => (
                  <span key={i} style={{ fontSize: 10, fontWeight: 500,
                    color: 'var(--slate)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>
                    · {t}
                  </span>
                ))}
              </div>
            </div>
          </div>
        ))}
      </div>
    </Section>
  );
}

// ─────────────────────────────────────────────────────────────
// HealthModule — wellness recommendations
// ─────────────────────────────────────────────────────────────
function HealthModule({ persona }) {
  const h = Dm().health[persona];
  const [done, setDone] = React.useState({});
  const toggle = (id) => setDone(d => ({ ...d, [id]: !d[id] }));

  // Readiness ring
  const ringR = 28, ringC = 2 * Math.PI * ringR;
  const fill = (h.readiness / 100) * ringC;

  return (
    <Section eyebrow="Health · coach" title="">
      <Card style={{ padding: 22 }}>
        {/* Top row — sleep / readiness */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 16 }}>
          {/* Readiness ring */}
          <svg width="74" height="74" viewBox="0 0 74 74">
            <circle cx="37" cy="37" r={ringR} fill="none" stroke="rgba(20,20,19,0.08)" strokeWidth="6" />
            <circle cx="37" cy="37" r={ringR} fill="none"
              stroke="var(--loop-orange)" strokeWidth="6" strokeLinecap="round"
              strokeDasharray={`${fill} ${ringC}`}
              transform="rotate(-90 37 37)" />
            <text x="37" y="42" textAnchor="middle"
              fontSize="18" fontWeight="500" letterSpacing="-0.02em" fill="var(--ink)"
              fontFamily="Sofia Sans, -apple-system, sans-serif">
              {h.readiness}
            </text>
          </svg>
          <div style={{ flex: 1 }}>
            <Eyebrow>Readiness</Eyebrow>
            <div style={{ marginTop: 6, fontSize: 13, color: 'var(--ink)', lineHeight: 1.35, fontWeight: 500 }}>
              {h.headline}
            </div>
          </div>
        </div>

        {/* Vitals */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8,
          padding: '14px 0', borderTop: '1px solid rgba(20,20,19,0.08)',
          borderBottom: '1px solid rgba(20,20,19,0.08)' }}>
          <div>
            <div style={{ fontSize: 10, color: 'var(--slate)', textTransform: 'uppercase', letterSpacing: '0.04em', fontWeight: 700 }}>Sleep</div>
            <div style={{ fontSize: 17, fontWeight: 500, marginTop: 2, letterSpacing: '-0.01em' }}>{h.sleep.hours}h</div>
            <div style={{ fontSize: 10, color: h.sleep.trend === 'up' ? 'var(--success)' : 'var(--slate)' }}>{h.sleep.vs}</div>
          </div>
          {h.vitals.map((v, i) => (
            <div key={i}>
              <div style={{ fontSize: 10, color: 'var(--slate)', textTransform: 'uppercase', letterSpacing: '0.04em', fontWeight: 700 }}>{v.label}</div>
              <div style={{ fontSize: 17, fontWeight: 500, marginTop: 2, letterSpacing: '-0.01em' }}>{v.value}</div>
            </div>
          ))}
        </div>

        {/* Actions */}
        <div style={{ marginTop: 4 }}>
          {h.actions.map((a, i) => (
            <div key={a.id} style={{ display: 'flex', alignItems: 'center', gap: 12,
              padding: '12px 0',
              borderBottom: i < h.actions.length - 1 ? '1px solid rgba(20,20,19,0.06)' : 'none' }}>
              <button onClick={() => toggle(a.id)} style={{
                width: 22, height: 22, borderRadius: '50%',
                background: done[a.id] ? 'var(--ink)' : 'transparent',
                border: '1.5px solid var(--ink)', cursor: 'pointer', flexShrink: 0,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              }}>
                {done[a.id] && <Icon name="check" size={12} color="var(--canvas)" />}
              </button>
              <div style={{ flex: 1, fontSize: 13, lineHeight: 1.35,
                textDecoration: done[a.id] ? 'line-through' : 'none',
                color: done[a.id] ? 'var(--slate)' : 'var(--ink)' }}>
                {a.body}
              </div>
              <span style={{ fontSize: 11, color: 'var(--slate)',
                textTransform: 'uppercase', letterSpacing: '0.04em', flexShrink: 0 }}>{a.when}</span>
            </div>
          ))}
        </div>
      </Card>
    </Section>
  );
}

// ─────────────────────────────────────────────────────────────
// OrchestratorBar — header that explains the order + opens config
// ─────────────────────────────────────────────────────────────
function OrchestratorBar({ enabled, order, onOpen }) {
  const count = order.filter(k => enabled[k]).length;
  return (
    <div style={{ padding: '4px 22px 18px' }}>
      <button onClick={onOpen} style={{ width: '100%',
        display: 'flex', alignItems: 'center', gap: 12,
        padding: '14px 16px', borderRadius: 22,
        background: 'var(--canvas-lifted)', border: 'none', cursor: 'pointer',
        textAlign: 'left', fontFamily: 'var(--font-sans)' }}>
        <div style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--ink)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
          <Icon name="layers" size={18} color="var(--canvas)" />
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink)' }}>Orchestrated for today</div>
          <div style={{ fontSize: 11, color: 'var(--slate)', marginTop: 2 }}>
            {count} modules · ranked by your day · tap to configure
          </div>
        </div>
        <Icon name="sliders-horizontal" size={18} color="var(--slate)" />
      </button>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// OrchestratorSheet — bottom sheet for enabling + reordering
// ─────────────────────────────────────────────────────────────
function OrchestratorSheet({ open, onClose, enabled, setEnabled, order, setOrder, modules }) {
  if (!open) return null;

  const move = (k, dir) => {
    const i = order.indexOf(k);
    const j = i + dir;
    if (j < 0 || j >= order.length) return;
    const next = order.slice();
    [next[i], next[j]] = [next[j], next[i]];
    setOrder(next);
  };

  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, background: 'rgba(20,20,19,0.45)',
      zIndex: 50, display: 'flex', alignItems: 'flex-end',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%', background: 'var(--canvas)',
        borderTopLeftRadius: 28, borderTopRightRadius: 28,
        padding: '14px 22px 30px', maxHeight: '78%', overflowY: 'auto',
      }}>
        <div style={{ width: 44, height: 4, borderRadius: 4, background: 'var(--dust)',
          margin: '0 auto 18px' }} />
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
          <div>
            <Eyebrow>Orchestrator</Eyebrow>
            <h2 style={{ fontSize: 22, fontWeight: 500, letterSpacing: '-0.02em', marginTop: 8, lineHeight: 1.2 }}>
              Your AI agents, ranked
            </h2>
            <p style={{ marginTop: 8, fontSize: 13, color: 'var(--slate)', lineHeight: 1.4 }}>
              Each agent contributes a card. Loop sequences them by relevance to today.
              You can pin, mute, or reorder anything.
            </p>
          </div>
          <button onClick={onClose} style={{ width: 36, height: 36, borderRadius: '50%',
            background: 'var(--canvas-lifted)', border: 'none', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="x" size={18} />
          </button>
        </div>

        <div style={{ marginTop: 18 }}>
          {order.map((k, i) => {
            const m = modules[k];
            return (
              <div key={k} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '14px 0',
                borderBottom: i < order.length - 1 ? '1px solid rgba(20,20,19,0.08)' : 'none',
                opacity: enabled[k] ? 1 : 0.45,
              }}>
                <div style={{ width: 28, color: 'var(--slate)', textAlign: 'center',
                  fontSize: 13, fontVariantNumeric: 'tabular-nums', fontWeight: 500 }}>
                  {String(i + 1).padStart(2, '0')}
                </div>
                <div style={{ width: 40, height: 40, borderRadius: 12, background: 'var(--canvas-whisper)',
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                  <Icon name={m.icon} size={20} />
                </div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 14, fontWeight: 500 }}>{m.label}</div>
                  <div style={{ fontSize: 11, color: 'var(--slate)' }}>by {m.agent}</div>
                </div>
                <button onClick={() => move(k, -1)} disabled={i === 0}
                  style={{ width: 30, height: 30, borderRadius: '50%', background: 'transparent',
                    border: 'none', cursor: i === 0 ? 'default' : 'pointer',
                    opacity: i === 0 ? 0.2 : 1,
                    display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name="chevron-up" size={16} />
                </button>
                <button onClick={() => move(k, 1)} disabled={i === order.length - 1}
                  style={{ width: 30, height: 30, borderRadius: '50%', background: 'transparent',
                    border: 'none', cursor: i === order.length - 1 ? 'default' : 'pointer',
                    opacity: i === order.length - 1 ? 0.2 : 1,
                    display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name="chevron-down" size={16} />
                </button>
                <div onClick={() => setEnabled({ ...enabled, [k]: !enabled[k] })}
                  style={{ width: 40, height: 24, borderRadius: 999,
                    background: enabled[k] ? 'var(--ink)' : 'rgba(20,20,19,0.18)',
                    position: 'relative', cursor: 'pointer', flexShrink: 0,
                    transition: 'background 200ms' }}>
                  <div style={{ position: 'absolute', top: 2,
                    left: enabled[k] ? 18 : 2,
                    width: 20, height: 20, borderRadius: '50%', background: 'var(--canvas-lifted)',
                    transition: 'left 200ms', boxShadow: '0 1px 3px rgba(0,0,0,0.1)' }} />
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  ModuleFrame, InsightsModule, InsightCard,
  WeatherModule, HealthModule, BriefingPair,
  WeatherTile, HealthTile, WeatherExpanded, HealthExpanded,
  SpotsModule,
  OrchestratorBar, OrchestratorSheet,
});
