// Healify V2 — Component library
// All visuals respect theme variables (--t-*) so dark mode and color tweaks work live.

// ============================================================================
// ICONS — line-style, 1.75px stroke, currentColor
// ============================================================================
const Icon = ({ d, size = 22, stroke = 1.75, fill, viewBox = "0 0 24 24", style }) =>
<svg width={size} height={size} viewBox={viewBox} fill="none" style={style}>
    <path d={d} stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" fill={fill || "none"} />
  </svg>;


const HIcons = {
  home: "M3 11.5 12 4l9 7.5V20a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1v-8.5Z",
  pulse: "M3 12h4l2-5 3 10 2-7 2 5h5",
  spark: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2 2M16.4 16.4l2 2M5.6 18.4l2-2M16.4 7.6l2-2",
  plate: "M5 12a7 7 0 0 1 14 0M5 12a7 7 0 0 0 14 0M5 12h14M3 16h18",
  dumbbell: "M3 9v6M5 7v10M19 7v10M21 9v6M7 12h10",
  heart: "M12 21s-7-4.5-9.3-9A5.3 5.3 0 0 1 12 6a5.3 5.3 0 0 1 9.3 6c-2.3 4.5-9.3 9-9.3 9Z",
  moon: "M20 14.5A8 8 0 1 1 9.5 4a6.5 6.5 0 0 0 10.5 10.5Z",
  brain: "M9 4a3 3 0 0 0-3 3 3 3 0 0 0-2 5 3 3 0 0 0 1 4 3 3 0 0 0 4 3V4ZM15 4a3 3 0 0 1 3 3 3 3 0 0 1 2 5 3 3 0 0 1-1 4 3 3 0 0 1-4 3V4Z",
  droplet: "M12 3s6 6.5 6 11a6 6 0 1 1-12 0c0-4.5 6-11 6-11Z",
  flame: "M12 3s4 4 4 8a4 4 0 0 1-8 0c0-1 .5-2 1-3 .5 1.5 1.5 2 2 1.5C10 8 12 6 12 3Z",
  bed: "M3 19v-7a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v7M3 15h18M7 9V7a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2",
  mic: "M12 3a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V6a3 3 0 0 0-3-3ZM5 11a7 7 0 0 0 14 0M12 18v3M8 21h8",
  send: "M3 11.5 21 4l-7 17-2.5-7.5L3 11.5Z",
  plus: "M12 5v14M5 12h14",
  minus: "M5 12h14",
  check: "M5 12.5 10 17l9-10",
  chevR: "m9 6 6 6-6 6",
  chevL: "m15 6-6 6 6 6",
  chevD: "m6 9 6 6 6-6",
  chevU: "m6 15 6-6 6 6",
  close: "M6 6l12 12M18 6 6 18",
  search: "M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14ZM21 21l-5-5",
  bell: "M6 19h12l-1.5-2V11a4.5 4.5 0 0 0-9 0v6L6 19ZM10 22h4",
  settings: "M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm9 4-2-1V8l2-2-2-2-2 2h-3l-1-2h-2l-1 2H7L5 4 3 6l2 2v3l-2 1 2 2-2 2 2 2 2-2h3l1 2h2l1-2h3l2 2 2-2-2-2 2-2Z",
  user: "M5 21a7 7 0 0 1 14 0M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z",
  menu: "M4 7h16M4 12h16M4 17h10",
  sparkle: "M12 3l1.8 4.7L18 9l-4.2 1.3L12 15l-1.8-4.7L6 9l4.2-1.3L12 3ZM19 14l.9 2.1L22 17l-2.1.9L19 20l-.9-2.1L16 17l2.1-.9L19 14Z",
  shield: "M12 3 4 6v6c0 4.5 3.5 8.5 8 9 4.5-.5 8-4.5 8-9V6l-8-3Z",
  flag: "M5 21V4M5 4h12l-2 4 2 4H5",
  target: "M12 3v3M12 18v3M3 12h3M18 12h3M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0-6 0M12 12m-7 0a7 7 0 1 0 14 0a7 7 0 1 0-14 0",
  arrowR: "M5 12h14M13 6l6 6-6 6",
  arrowU: "M12 19V5M6 11l6-6 6 6",
  arrowD: "M12 5v14M6 13l6 6 6-6",
  trash: "M4 7h16M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2M6 7l1 13a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1l1-13",
  copy: "M9 4h9a1 1 0 0 1 1 1v12M4 9h9a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V10Z",
  refresh: "M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5M21 12a9 9 0 0 1-15 6.7L3 16M3 21v-5h5",
  thumbs: "M7 22V11M2 13v8h5V11l4-7c2 0 3 1 2 4l-1 3h7c2 0 3 1 3 3l-2 7c0 1-1 2-2 2H7Z",
  share: "M12 3v13M12 3l4 4M12 3l-4 4M5 14v5a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-5",
  voice: "M3 12a9 9 0 0 1 18 0M6 12a6 6 0 0 1 12 0M9 12a3 3 0 0 1 6 0",
  filter: "M4 5h16M7 12h10M10 19h4",
  calendar: "M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7ZM4 11h16M8 3v4M16 3v4",
  clock: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18ZM12 7v5l3 2",
  data: "M4 20V8M10 20V4M16 20V12M22 20H2",
  lock: "M6 11V8a6 6 0 0 1 12 0v3M5 11h14a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1Z",
  scan: "M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3M3 12h18"
};

const Glyph = ({ name, size = 22, stroke = 1.75, color, style }) =>
<span style={{ color: color || 'currentColor', display: 'inline-flex', ...style }}>
    <Icon d={HIcons[name] || ''} size={size} stroke={stroke} />
  </span>;


// ============================================================================
// SURFACES — HCard, HSection
// ============================================================================
const HCard = ({ children, pad = 'var(--density-pad)', radius = 20, style, onClick, elevate = true, tone, ...rest }) => {
  const bg = tone === 'cream' ? 'var(--t-cream)' :
  tone === 'ink' ? 'var(--t-ink-card)' :
  tone === 'glass' ? 'rgba(255,255,255,0.6)' :
  'var(--t-surface)';
  const fg = tone === 'ink' ? 'var(--t-ink-card-fg)' : 'var(--t-fg-1)';
  return (
    <div onClick={onClick} style={{
      background: bg,
      color: fg,
      borderRadius: radius,
      padding: pad,
      boxShadow: elevate ? 'var(--shadow-md)' : 'none',
      cursor: onClick ? 'pointer' : 'default',
      transition: 'transform 150ms ease, box-shadow 150ms ease',
      ...style
    }} {...rest}>
      {children}
    </div>);

};

const HSectionLabel = ({ children, action, style }) =>
<div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', padding: '0 4px', marginBottom: 10, ...style }}>
    <div className="h-label">{children}</div>
    {action ? <button onClick={action.onClick} style={{ fontFamily: 'var(--font-body)', fontSize: 12, fontWeight: 500, color: 'var(--t-fg-2)', letterSpacing: '-0.1px' }}>{action.label} ›</button> : null}
  </div>;


// ============================================================================
// BUTTONS
// ============================================================================
const HPrimaryButton = ({ children, onClick, variant = 'gradient', icon, full = false, size = 'lg', style }) => {
  const h = size === 'sm' ? 40 : size === 'md' ? 48 : 56;
  const px = size === 'sm' ? 16 : 24;
  const fontSize = size === 'sm' ? 14 : 16;
  const bg =
  variant === 'gradient' ? 'var(--grad-warm-orange)' :
  variant === 'ink' ? 'var(--t-pill)' :
  variant === 'ghost' ? 'transparent' :
  variant === 'soft' ? 'var(--t-ink-04)' : 'var(--brand-orange-vibey)';
  const fg = variant === 'ghost' ? 'var(--t-fg-1)' : variant === 'soft' ? 'var(--t-fg-1)' : variant === 'ink' ? 'var(--t-pill-fg)' : '#fff';
  const shadow = variant === 'gradient' ? 'var(--shadow-orange)' : 'none';
  return (
    <button onClick={onClick} style={{
      background: bg, color: fg, height: h, padding: `0 ${px}px`,
      borderRadius: variant === 'soft' ? 14 : 999, display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      gap: 8, fontFamily: 'var(--font-body)', fontWeight: 500, fontSize, letterSpacing: '-0.2px',
      width: full ? '100%' : 'auto', boxShadow: shadow, border: variant === 'ghost' ? '1px solid var(--t-border)' : 'none',
      ...style
    }}>
      {icon ? <Glyph name={icon} size={18} /> : null}
      {children}
    </button>);

};

const HIconButton = ({ icon, onClick, size = 40, tone = 'soft', style }) => {
  const bg = tone === 'ink' ? 'var(--t-pill)' : tone === 'orange' ? 'var(--brand-orange-vibey)' : 'var(--t-surface)';
  const fg = tone === 'ink' ? 'var(--t-pill-fg)' : tone === 'orange' ? '#fff' : 'var(--t-fg-1)';
  return (
    <button onClick={onClick} style={{
      width: size, height: size, borderRadius: 999,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      background: bg, color: fg, boxShadow: tone === 'soft' ? '0 1px 3px rgba(0,0,0,0.06)' : 'var(--shadow-md)',
      ...style
    }}>
      <Glyph name={icon} size={18} />
    </button>);

};

const HBackButton = ({ onClick, label }) =>
<button onClick={onClick} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, height: 36, padding: '0 10px 0 6px', borderRadius: 999, background: 'transparent', color: 'var(--t-fg-1)' }}>
    <span style={{ width: 30, height: 30, borderRadius: 999, background: 'var(--t-ink-04)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
      <Glyph name="chevL" size={16} />
    </span>
    {label ? <span style={{ fontWeight: 500, fontSize: 14 }}>{label}</span> : null}
  </button>;


// ============================================================================
// TOP BAR
// ============================================================================
const HTopBar = ({ title, onBack, right, transparent = true, sticky = false }) =>
<div style={{
  position: sticky ? 'sticky' : 'relative', top: sticky ? 0 : 'auto', zIndex: 5,
  height: 52, display: 'flex', alignItems: 'center', justifyContent: 'space-between',
  padding: '0 12px',
  background: transparent ? 'transparent' : 'var(--t-surface)',
  backdropFilter: transparent ? 'none' : 'blur(20px)'
}}>
    <div style={{ minWidth: 44 }}>{onBack ? <HBackButton onClick={onBack} /> : null}</div>
    <div style={{ fontFamily: 'var(--font-body)', fontWeight: 600, fontSize: 17, letterSpacing: '-0.2px' }}>{title}</div>
    <div style={{ minWidth: 44, display: 'flex', justifyContent: 'flex-end', gap: 8 }}>{right}</div>
  </div>;


// ============================================================================
// TAB BAR — V2: clearer affordance for AI center button
// ============================================================================
// HealifyHeart — the canonical brand mark, traced from the Healify favicon.
// `solid` (default): orange-gradient rounded-square with white heart (app icon).
// `mono`: monochrome heart only on transparent bg — uses currentColor; for monochrome chips, tab bar, etc.
const HealifyHeart = ({ size = 32, mono = false, radius = 0.18, color }) => {
  if (mono) {
    // Just the heart, on transparent. Uses currentColor so it inherits text
    // color by default; an explicit `color` prop overrides (e.g. white on the
    // dark center tab button).
    return (
      <svg width={size} height={size} viewBox="0 0 143 143" fill="none" aria-label="Healify" style={color ? { color } : undefined}>
        <path d="M102.797 43.9628C96.7125 37.8759 86.8795 37.767 80.6622 43.7177L56.6732 66.6784C50.9889 72.119 50.8887 81.1695 56.4511 86.7347L73.4639 103.754L73.4639 97.7376C73.4639 95.9215 74.1856 94.1799 75.47 92.8961L94.7702 73.6053L102.204 66.9001C108.929 60.8331 109.2 50.3692 102.797 43.9628Z" fill="currentColor" />
        <path d="M69.9505 47.8472L53.1071 63.9686C49.019 67.8814 47.3524 73.3597 48.1278 78.5481L40.6064 70.5766C33.7366 63.2955 33.9171 51.8672 41.0134 44.8067C48.381 37.4763 60.3435 37.6653 67.4759 45.2246L69.9505 47.8472Z" fill="currentColor" />
      </svg>);

  }
  const id = React.useId().replace(/:/g, '');
  return (
    <svg width={size} height={size} viewBox="0 0 143 143" fill="none" aria-label="Healify">
      <defs>
        <linearGradient id={`hh-g-${id}`} x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor="#FF6942" />
          <stop offset="100%" stopColor="#FDB36B" />
        </linearGradient>
      </defs>
      <rect width="143" height="143" rx={143 * radius} fill={`url(#hh-g-${id})`} />
      <path d="M102.797 43.9628C96.7125 37.8759 86.8795 37.767 80.6622 43.7177L56.6732 66.6784C50.9889 72.119 50.8887 81.1695 56.4511 86.7347L73.4639 103.754L73.4639 97.7376C73.4639 95.9215 74.1856 94.1799 75.47 92.8961L94.7702 73.6053L102.204 66.9001C108.929 60.8331 109.2 50.3692 102.797 43.9628Z" fill="white" />
      <path d="M69.9505 47.8472L53.1071 63.9686C49.019 67.8814 47.3524 73.3597 48.1278 78.5481L40.6064 70.5766C33.7366 63.2955 33.9171 51.8672 41.0134 44.8067C48.381 37.4763 60.3435 37.6653 67.4759 45.2246L69.9505 47.8472Z" fill="white" />
    </svg>);

};

// Healify wordmark — heart + "healify"
const HealifyWordmark = ({ size = 22, color }) =>
<svg width={size * (351 / 83)} height={size} viewBox="0 0 351 83" fill={color || 'currentColor'} aria-label="Healify">
    <path d="M74.8068 5.16064C68.0367 -1.61274 57.0947 -1.73389 50.1762 4.88794L23.4818 30.438C17.1564 36.4923 17.0449 46.5635 23.2347 52.7563L42.1662 71.6945L42.1662 65C42.1662 62.9792 42.9692 61.0411 44.3985 59.6125L65.8753 38.1461L74.1469 30.6847C81.6312 23.9335 81.9323 12.2896 74.8068 5.16064Z" />
    <path d="M38.2575 9.48308L19.5145 27.4225C14.9654 31.7767 13.1108 37.8728 13.9737 43.6464L5.6041 34.7758C-2.04049 26.6736 -1.83966 13.9564 6.05696 6.09961C14.2554 -2.05743 27.5671 -1.84721 35.5039 6.56464L38.2575 9.48308Z" />
    <path d="M144.125 40.1223H115.216V65.5095H105.962V8.18359H115.216V31.851H144.125V8.18359H153.461V65.5095H144.125V40.1223Z" />
    <path d="M178.681 65.3582C174.454 65.3582 170.777 64.4931 167.649 62.7629C164.52 60.9786 162.105 58.4374 160.403 55.1392C158.757 51.8409 157.934 48.0291 157.934 43.7035C157.934 39.378 158.757 35.5932 160.403 32.349C162.105 29.0508 164.52 26.5095 167.649 24.7253C170.777 22.941 174.427 22.0488 178.598 22.0488C183.044 22.0488 186.804 23.0491 189.878 25.0497C193.006 27.0502 195.256 29.8889 196.629 33.5656C198.056 37.1882 198.44 41.3786 197.781 46.1366H164.191L166.825 43.0547C166.606 47.7587 167.539 51.4625 169.624 54.1659C171.71 56.8694 174.729 58.2211 178.681 58.2211C181.425 58.2211 183.621 57.6263 185.267 56.4368C186.969 55.2473 188.094 53.8145 188.643 52.1383H197.37C196.766 54.7336 195.641 57.0316 193.994 59.0321C192.347 60.9786 190.207 62.5196 187.572 63.6551C184.938 64.7905 181.974 65.3582 178.681 65.3582ZM164.355 39.8106H191.606L188.807 42.487C189.246 40.0539 189.137 37.81 188.478 35.7554C187.819 33.6467 186.612 31.9976 184.855 30.808C183.099 29.6185 180.904 29.0238 178.269 29.0238C175.964 29.0238 173.933 29.5915 172.177 30.7269C170.475 31.8083 169.158 33.4034 168.225 35.5121C167.292 37.5667 166.853 40.0268 166.908 42.8925L164.355 39.8106Z" />
    <path d="M217.27 65.7803C212.848 65.7803 209.326 64.6065 206.705 62.2589C204.139 59.9112 202.856 56.8265 202.856 53.0048C202.856 49.3469 204.085 46.426 206.542 44.2421C209.053 42.0583 212.656 40.8026 217.352 40.475L227.425 39.738C228.462 39.6288 229.226 39.3285 229.718 38.8371C230.209 38.2912 230.455 37.4176 230.455 36.2165C230.455 33.8689 229.663 32.1218 228.08 30.9753C226.497 29.8288 224.395 29.2555 221.774 29.2555C218.99 29.2555 216.806 29.8834 215.222 31.1391C213.639 32.3402 212.711 34.0873 212.438 36.3803H203.921C204.467 31.7396 206.269 28.1909 209.326 25.7341C212.383 23.2772 216.56 22.0488 221.856 22.0488C227.425 22.0488 231.71 23.4137 234.713 26.1435C237.771 28.8733 239.299 33.0499 239.299 38.6733V57.0176H242.657V64.5519H238.972C236.624 64.5519 234.822 63.8967 233.567 62.5864C232.366 61.2215 231.765 59.2561 231.765 56.6901V52.2678L232.993 53.1686C232.12 57.3179 230.291 60.4572 227.507 62.5864C224.777 64.7157 221.365 65.7803 217.27 65.7803ZM218.826 58.6555C221.119 58.6555 223.139 58.1642 224.886 57.1814C226.688 56.1987 228.08 54.8338 229.063 53.0867C230.1 51.3396 230.619 49.3469 230.619 47.1084V45.5525L218.99 46.3714C216.424 46.5898 214.567 47.2176 213.421 48.255C212.274 49.2923 211.701 50.7118 211.701 52.5135C211.701 54.5335 212.329 56.0622 213.585 57.0995C214.84 58.1369 216.587 58.6555 218.826 58.6555Z" />
    <path d="M256.554 65.5095C253.606 65.5095 251.34 64.7179 249.757 63.1346C248.173 61.5513 247.382 59.2855 247.382 56.3374V8.18359H256.145V57.9752H260.157V65.5095H256.554Z" />
    <path d="M265.947 24.2346H274.71V65.5093H265.947V24.2346ZM270.37 16.7004C268.786 16.7004 267.476 16.2363 266.439 15.3082C265.401 14.3254 264.883 13.0697 264.883 11.541C264.883 10.5583 265.128 9.68476 265.62 8.92042C266.111 8.10148 266.766 7.47362 267.585 7.03685C268.404 6.54549 269.332 6.2998 270.37 6.2998C271.953 6.2998 273.263 6.81847 274.301 7.85579C275.338 8.83852 275.857 10.0669 275.857 11.541C275.857 13.0151 275.338 14.2435 274.301 15.2263C273.318 16.209 272.008 16.7004 270.37 16.7004Z" />
    <path d="M288.115 31.6872H280.663L280.581 24.2349H285.495C286.368 24.2349 287.023 24.0165 287.46 23.5797C287.897 23.0883 288.115 22.4332 288.115 21.6142L288.197 19.8126C288.47 16.373 289.699 13.5886 291.882 11.4594C294.066 9.27552 297.315 8.18359 301.628 8.18359H305.804V15.636H299.089C298.216 15.636 297.588 15.827 297.206 16.2092C296.823 16.5368 296.632 17.1647 296.632 18.0928V24.2349H304.904V31.6872H296.796V65.5095H288.115V31.6872Z" />
    <path d="M325.844 67.7331C326.171 66.7504 326.335 65.8496 326.335 65.0306C326.335 64.2117 326.171 63.3382 325.844 62.41L310.529 24.4111H319.783L331.003 54.2206H331.33L341.485 24.4111H350.657L329.693 82.0646H320.602L325.844 67.7331Z" />
  </svg>;


// Tab bar — aligned with real app: Home / Health / Anna(FAB) / Nutrition / Fitness.
// Menu lives off-pill, opened via the avatar/menu chip on the home greeting header.
// Active peripheral tab gets a soft peach pill + orange filled icon.
const HTabBar = ({ tab, onChange, hasUnread = false, online = true }) => {
  const tabs = [
    { k: 'home',      icon: 'home',     label: 'Home' },
    { k: 'health',    icon: 'pulse',    label: 'Health' },
    { k: 'anna',      icon: null,       label: 'Anna' },
    { k: 'nutrition', icon: 'plate',    label: 'Nutrition' },
    { k: 'fitness',   icon: 'dumbbell', label: 'Move' },
  ];

  return (
    <div style={{
      position: 'relative',
      background: 'var(--t-surface)',
      borderRadius: 999,
      padding: '8px 10px',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      gap: 4,
      boxShadow: 'var(--shadow-lg)',
      border: '1px solid var(--t-border)'
    }}>
      {tabs.map((t) => {
        const active = tab === t.k;
        if (t.k === 'anna') {
          // Center FAB — dark circle with the Healify mark, lifted above the pill.
          return (
            <button key={t.k} onClick={() => onChange(t.k)} aria-label="Chat with Anna" style={{
              position: 'relative', width: 60, height: 60, borderRadius: 999,
              background: 'var(--brand-ink)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              boxShadow: '0 8px 22px rgba(0,0,0,0.28)',
              transform: 'translateY(-12px)',
              border: '3px solid var(--t-surface)',
              flexShrink: 0,
            }}>
              <HealifyHeart size={34} mono color="#fff" />
              {online ?
                <span style={{ position: 'absolute', bottom: 6, right: 6, width: 11, height: 11, boxSizing: 'border-box', borderRadius: 999, background: 'var(--success)', border: '2px solid var(--brand-ink)' }} /> :
                null}
              {hasUnread ?
                <span style={{ position: 'absolute', top: 6, right: 6, width: 11, height: 11, boxSizing: 'border-box', borderRadius: 999, background: 'var(--error)', border: '2px solid var(--brand-ink)' }} /> :
                null}
            </button>
          );
        }
        return (
          <button key={t.k} onClick={() => onChange(t.k)} aria-label={t.label} aria-pressed={active} style={{
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            width: 44, height: 44, borderRadius: 999,
            color: active ? 'var(--brand-orange-vibey)' : 'var(--t-fg-3)',
            background: active ? 'color-mix(in oklab, var(--brand-orange-vibey) 14%, transparent)' : 'transparent',
            transition: 'background 200ms ease, color 200ms ease',
            flexShrink: 0,
          }}>
            <Glyph name={t.icon} size={22} stroke={active ? 2.2 : 1.85} />
          </button>);

      })}
    </div>);

};

const AnnaMonogram = ({ size = 24, color = '#fff' }) =>
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <path d="M12 3.5 5 19.5h3.2L9.5 16h5l1.3 3.5H19L12 3.5Zm-1.4 9.6 1.4-3.8 1.4 3.8h-2.8Z" fill={color} />
    <circle cx="20" cy="6" r="2" fill={color} />
  </svg>;


// ============================================================================
// ANNA AVATAR — multi-state, identity-forward
// ============================================================================
const HAnnaAvatar = ({ size = 44, state = 'idle', ring = true }) => {
  // state: idle | listening | thinking | speaking
  const ringColor = state === 'listening' ? 'var(--success)' : state === 'thinking' ? 'var(--brand-orange-vibey)' : 'var(--brand-orange-vibey)';
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }}>
      {ring &&
      <div style={{
        position: 'absolute', inset: -3,
        borderRadius: 999,
        background: state === 'idle' ? `conic-gradient(${ringColor}, transparent 60%, ${ringColor})` : `linear-gradient(135deg, ${ringColor}, var(--brand-gold-sand))`,
        animation: state === 'thinking' ? 'ring-spin 2s linear infinite' : 'none',
        padding: 2
      }}>
          <div style={{ width: '100%', height: '100%', borderRadius: 999, background: 'var(--t-surface)' }} />
        </div>
      }
      <img src="assets/anna.png" alt="Anna" style={{
        position: 'absolute', inset: ring ? 2 : 0,
        width: size - (ring ? 4 : 0), height: size - (ring ? 4 : 0),
        borderRadius: 999, objectFit: 'cover'
      }} />
      {state === 'listening' &&
      <span style={{ position: 'absolute', bottom: -2, right: -2, width: 12, height: 12, borderRadius: 999, background: 'var(--success)', border: '2px solid var(--t-surface)', animation: 'pulse-soft 1.2s ease-in-out infinite' }} />
      }
    </div>);

};

// ============================================================================
// CHIPS / QUICK REPLIES
// ============================================================================
const HChip = ({ children, onClick, icon, active = false, tone = 'soft', style }) => {
  const bg = active ? 'var(--t-pill)' : tone === 'cream' ? 'var(--t-cream)' : tone === 'ghost' ? 'transparent' : 'var(--t-ink-04)';
  const fg = active ? 'var(--t-pill-fg)' : 'var(--t-fg-1)';
  return (
    <button onClick={onClick} style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '8px 14px', borderRadius: 999,
      background: bg, color: fg,
      fontFamily: 'var(--font-body)', fontSize: 13, fontWeight: 500, letterSpacing: '-0.1px',
      border: tone === 'ghost' ? '1px solid var(--t-border)' : 'none',
      whiteSpace: 'nowrap', flexShrink: 0,
      ...style
    }}>
      {icon ? <Glyph name={icon} size={14} /> : null}
      {children}
    </button>);

};

const HQuickReplies = ({ items = [], onPick }) =>
<div style={{ display: 'flex', gap: 8, overflowX: 'auto', paddingBottom: 4, scrollbarWidth: 'none', margin: '0 -16px', padding: '0 16px 4px' }}>
    {items.map((item, i) =>
  <HChip key={i} tone="cream" onClick={() => onPick && onPick(item)}>{item}</HChip>
  )}
  </div>;


// ============================================================================
// FOCUS RING — the V2 hero viz. Circular progress with optional segments
// ============================================================================
const HFocusRing = ({ score = 73, size = 220, stroke = 18, segments, animate = true }) => {
  const r = size / 2 - stroke - 6;
  const c = 2 * Math.PI * r;
  const arc = Math.max(0, Math.min(100, score)) / 100;
  const segR = r + stroke + 6;
  const segCirc = 2 * Math.PI * segR;
  const uid = React.useId().replace(/:/g, '');
  const [drawn, setDrawn] = React.useState(!animate);
  React.useEffect(() => {
    if (!animate) return;
    const id = requestAnimationFrame(() => setDrawn(true));
    return () => cancelAnimationFrame(id);
  }, [animate]);
  const target = c * arc;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ display: 'block' }}>
      <defs>
        <linearGradient id={`ring-grad-${uid}`} x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor="#FF6942" />
          <stop offset="100%" stopColor="#FDB36B" />
        </linearGradient>
      </defs>
      {segments && segments.map((s, i) => {
        const start = i / segments.length;
        const len = 1 / segments.length;
        const gap = 0.02;
        const sLen = (len - gap) * segCirc;
        const sOffset = -((start + gap / 2) * segCirc);
        return (
          <circle key={i} cx={size / 2} cy={size / 2} r={segR} fill="none" stroke={s.color}
          strokeWidth={5} strokeLinecap="round"
          strokeDasharray={`${drawn ? sLen * s.value : 0} ${segCirc - (drawn ? sLen * s.value : 0)}`}
          strokeDashoffset={sOffset}
          transform={`rotate(-90 ${size / 2} ${size / 2})`} opacity={0.95}
          style={{ transition: `stroke-dasharray 1200ms cubic-bezier(.2,.7,.3,1) ${120 + i * 90}ms` }} />);

      })}
      <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--t-ink-04)" strokeWidth={stroke} />
      <circle cx={size / 2} cy={size / 2} r={r} fill="none"
      stroke={`url(#ring-grad-${uid})`} strokeWidth={stroke} strokeLinecap="round"
      strokeDasharray={`${drawn ? target : 0} ${c}`}
      transform={`rotate(-90 ${size / 2} ${size / 2})`}
      style={{ transition: 'stroke-dasharray 1400ms cubic-bezier(.2,.7,.3,1) 80ms' }} />
    </svg>);

};

// Number count-up for headline stats
const CountUp = ({ to = 0, from = 0, duration = 900, decimals = 0, prefix = '', suffix = '' }) => {
  const [v, setV] = React.useState(from);
  React.useEffect(() => {
    let raf, start;
    const step = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setV(from + (to - from) * eased);
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [to, from, duration]);
  return <>{prefix}{v.toFixed(decimals)}{suffix}</>;
};

// ============================================================================
// SPARKLINE — inline mini chart
// ============================================================================
const HSparkline = ({ data = [], width = 120, height = 32, color = 'var(--brand-orange-vibey)', fill = true }) => {
  if (data.length < 2) return null;
  const min = Math.min(...data),max = Math.max(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = i / (data.length - 1) * width;
    const y = height - 4 - (v - min) / range * (height - 8);
    return [x, y];
  });
  const path = pts.map(([x, y], i) => i === 0 ? `M${x} ${y}` : `L${x} ${y}`).join(' ');
  const area = path + ` L${width} ${height} L0 ${height} Z`;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
      {fill &&
      <defs>
          <linearGradient id={`sl-${color.replace(/[^a-z0-9]/gi, '')}`} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={color} stopOpacity="0.18" />
            <stop offset="100%" stopColor={color} stopOpacity="0" />
          </linearGradient>
        </defs>
      }
      {fill && <path d={area} fill={`url(#sl-${color.replace(/[^a-z0-9]/gi, '')})`} />}
      <path d={path} stroke={color} strokeWidth={1.8} fill="none" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={pts[pts.length - 1][0]} cy={pts[pts.length - 1][1]} r="2.5" fill={color} />
    </svg>);

};

// ============================================================================
// BAR CHART — mini bars (for chat data cards)
// ============================================================================
const HMiniBars = ({ data = [], width = 220, height = 80, color = 'var(--brand-orange-vibey)', highlightLast = true }) => {
  const max = Math.max(...data.map((d) => d.value || d), 1);
  const barW = (width - (data.length - 1) * 6) / data.length;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
      {data.map((d, i) => {
        const v = d.value !== undefined ? d.value : d;
        const h = Math.max(4, v / max * (height - 16));
        const x = i * (barW + 6);
        const y = height - h - 12;
        const last = highlightLast && i === data.length - 1;
        return (
          <g key={i}>
            <rect x={x} y={y} width={barW} height={h} rx={4} fill={last ? color : 'var(--t-ink-12)'} />
            {d.label && <text x={x + barW / 2} y={height - 2} fontSize="9" textAnchor="middle" fill="var(--t-fg-3)" fontFamily="var(--font-body)">{d.label}</text>}
          </g>);

      })}
    </svg>);

};

// ============================================================================
// STATUS DOT / BADGE
// ============================================================================
const HStatus = ({ status = 'normal' }) => {
  const map = {
    normal: { c: 'var(--success)', t: 'Normal' },
    fair: { c: 'var(--warning)', t: 'Fair' },
    attention: { c: 'var(--error)', t: 'Needs attention' }
  };
  const s = map[status] || map.normal;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 500, color: 'var(--t-fg-2)' }}>
      <span style={{ width: 8, height: 8, borderRadius: 999, background: s.c }} />
      {s.t}
    </span>);

};

// ============================================================================
// FOCUS ROW — V2: icon tile + content + sparkline + trend
// ============================================================================
const HFocusRow = ({ domain, title, value, unit, status, spark, trend, onClick }) => {
  const colorMap = {
    sleep: { c: 'var(--focus-sleep)', tint: 'var(--focus-sleep-tint)', icon: 'moon' },
    nutrition: { c: 'var(--focus-nutrition)', tint: 'var(--focus-nutrition-tint)', icon: 'plate' },
    fitness: { c: 'var(--focus-fitness)', tint: 'var(--focus-fitness-tint)', icon: 'dumbbell' },
    mental: { c: 'var(--focus-mental)', tint: 'var(--focus-mental-tint)', icon: 'brain' },
    heart: { c: 'var(--focus-heart)', tint: 'var(--focus-heart-tint)', icon: 'heart' }
  };
  const d = colorMap[domain] || colorMap.heart;
  return (
    <HCard onClick={onClick} pad="14px" radius={18}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <div style={{ width: 44, height: 44, borderRadius: 999, background: d.tint, color: d.c, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
          <Glyph name={d.icon} size={22} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 15, fontWeight: 500, color: 'var(--t-fg-1)', letterSpacing: '-0.2px' }}>{title}</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginTop: 2 }}>
            <span style={{ fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 600, color: 'var(--t-fg-1)', letterSpacing: '-0.02em' }}>{value}</span>
            {unit && <span style={{ fontSize: 12, color: 'var(--t-fg-3)' }}>{unit}</span>}
            {trend !== undefined &&
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 2, marginLeft: 4, fontSize: 11, color: trend > 0 ? 'var(--success)' : trend < 0 ? 'var(--error)' : 'var(--t-fg-3)', fontWeight: 500 }}>
                <Glyph name={trend > 0 ? 'arrowU' : trend < 0 ? 'arrowD' : 'minus'} size={11} stroke={2} />
                {Math.abs(trend)}%
              </span>
            }
          </div>
        </div>
        {spark ? <HSparkline data={spark} width={84} height={32} color={d.c} /> : null}
      </div>
      {status ? <div style={{ marginTop: 10, display: 'flex', justifyContent: 'space-between' }}><HStatus status={status} /><Glyph name="chevR" size={14} style={{ color: 'var(--t-fg-3)' }} /></div> : null}
    </HCard>);

};

// ============================================================================
// CHAT BUBBLE — supports rich body via children
// ============================================================================
const HChatBubble = ({ from = 'anna', children, time, withAvatar = true, annaState = 'idle', delay = 0 }) => {
  const isAnna = from === 'anna';
  return (
    <div className="fade-up" style={{ display: 'flex', gap: 10, alignItems: 'flex-end', justifyContent: isAnna ? 'flex-start' : 'flex-end', margin: '12px 0', animationDelay: `${delay}ms` }}>
      {isAnna && withAvatar ? <HAnnaAvatar size={32} state={annaState} /> : isAnna ? <div style={{ width: 32 }} /> : null}
      <div style={{
        maxWidth: '78%',
        background: isAnna ? 'var(--t-surface)' : 'var(--grad-user-bubble)',
        color: isAnna ? 'var(--t-fg-1)' : '#fff',
        padding: '12px 14px',
        borderRadius: 20,
        borderBottomLeftRadius: isAnna ? 6 : 20,
        borderBottomRightRadius: isAnna ? 20 : 6,
        fontSize: 15, lineHeight: 1.5, letterSpacing: '-0.2px',
        boxShadow: isAnna ? '0 1px 3px rgba(0,0,0,0.04)' : 'none'
      }}>
        {children}
        {time ? <div style={{ marginTop: 6, fontSize: 10, color: isAnna ? 'var(--t-fg-3)' : 'rgba(255,255,255,0.55)', textAlign: 'right' }}>{time}</div> : null}
      </div>
    </div>);

};

// ============================================================================
// RICH ACTION CARD — numbered actions (Anna's signature)
// ============================================================================
const HNumberedActions = ({ items = [] }) =>
<div style={{ margin: '10px 0 0', display: 'flex', flexDirection: 'column', gap: 10 }}>
    {items.map((it, i) =>
  <div key={i} style={{ display: 'flex', gap: 10, padding: '10px 12px', background: 'var(--t-cream)', borderRadius: 14 }}>
        <div style={{ flexShrink: 0, width: 22, height: 22, borderRadius: 999, background: 'var(--brand-orange-vibey)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'var(--font-display)', fontSize: 12, fontWeight: 600 }}>{i + 1}</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--t-fg-1)', letterSpacing: '-0.1px' }}>{it.title}</div>
          <div style={{ fontSize: 13, color: 'var(--t-fg-2)', marginTop: 2, lineHeight: 1.45 }}>{it.body}</div>
        </div>
      </div>
  )}
  </div>;


// ============================================================================
// SOURCE CHIPS — what data Anna used
// ============================================================================
const HSourceChips = ({ items = [] }) =>
<div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
    {items.map((s, i) =>
  <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '4px 8px 4px 6px', borderRadius: 999, background: 'var(--t-ink-04)', fontSize: 11, color: 'var(--t-fg-2)' }}>
        <span style={{ width: 6, height: 6, borderRadius: 999, background: s.color || 'var(--brand-orange-vibey)' }} />
        {s.label}
      </span>
  )}
  </div>;


// ============================================================================
// DATA CARD IN-BUBBLE — small metric card for chat replies
// ============================================================================
const HBubbleDataCard = ({ title, value, unit, sub, chart, color = 'var(--brand-orange-vibey)' }) =>
<div style={{ marginTop: 10, padding: '12px 14px', background: 'var(--t-cream)', borderRadius: 14 }}>
    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
      <div>
        <div style={{ fontSize: 11, color: 'var(--t-fg-3)', textTransform: 'uppercase', letterSpacing: 1, fontWeight: 500 }}>{title}</div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 4 }}>
          <span style={{ fontFamily: 'var(--font-display)', fontSize: 24, fontWeight: 600, color: 'var(--t-fg-1)' }}>{value}</span>
          {unit && <span style={{ fontSize: 12, color: 'var(--t-fg-3)' }}>{unit}</span>}
        </div>
        {sub && <div style={{ fontSize: 12, color: 'var(--t-fg-2)', marginTop: 4 }}>{sub}</div>}
      </div>
      {chart}
    </div>
  </div>;


// ============================================================================
// TYPING INDICATOR
// ============================================================================
const HTyping = () =>
<div style={{ display: 'flex', gap: 10, alignItems: 'flex-end', margin: '12px 0' }}>
    <HAnnaAvatar size={32} state="thinking" />
    <div style={{ padding: '12px 14px', background: 'var(--t-surface)', borderRadius: 20, borderBottomLeftRadius: 6, display: 'flex', gap: 4, alignItems: 'center', height: 32 }}>
      {[0, 1, 2].map((i) => <span key={i} style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--t-fg-3)', animation: `pulse-soft 1.2s ease-in-out ${i * 0.2}s infinite` }} />)}
    </div>
  </div>;


// ============================================================================
// HABIT CHECK
// ============================================================================
const HHabitCheck = ({ done = false, onClick }) =>
<button onClick={onClick} style={{
  width: 26, height: 26, borderRadius: 999,
  border: `2px solid ${done ? 'var(--brand-orange-vibey)' : 'var(--t-ink-12)'}`,
  background: done ? 'var(--brand-orange-vibey)' : 'transparent',
  color: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
  transition: 'all 180ms ease'
}}>
    {done && <Glyph name="check" size={14} stroke={3} />}
  </button>;


// ============================================================================
// SETTINGS ROW
// ============================================================================
const HSettingsRow = ({ icon, title, sub, value, onClick, danger, toggle }) =>
<button onClick={onClick} style={{
  display: 'flex', alignItems: 'center', gap: 12, width: '100%',
  padding: '14px 14px', background: 'var(--t-surface)',
  border: 'none', borderBottom: '1px solid var(--t-border)',
  color: danger ? 'var(--error)' : 'var(--t-fg-1)', textAlign: 'left'
}}>
    {icon ? <div style={{ width: 32, height: 32, borderRadius: 10, background: 'var(--t-ink-04)', color: danger ? 'var(--error)' : 'var(--t-fg-1)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Glyph name={icon} size={16} /></div> : null}
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{ fontSize: 15, fontWeight: 500, letterSpacing: '-0.2px' }}>{title}</div>
      {sub && <div style={{ fontSize: 12, color: 'var(--t-fg-3)', marginTop: 1 }}>{sub}</div>}
    </div>
    {value && <span style={{ fontSize: 13, color: 'var(--t-fg-3)' }}>{value}</span>}
    {toggle ? <Toggle on={toggle.on} onChange={toggle.onChange} /> : !danger && <Glyph name="chevR" size={16} style={{ color: 'var(--t-fg-3)' }} />}
  </button>;


const Toggle = ({ on, onChange }) =>
<button onClick={(e) => {e.stopPropagation();onChange && onChange(!on);}} style={{
  width: 44, height: 26, borderRadius: 999, background: on ? 'var(--brand-orange-vibey)' : 'var(--t-ink-12)',
  position: 'relative', transition: 'all 200ms ease', padding: 0
}}>
    <span style={{ position: 'absolute', top: 3, left: on ? 21 : 3, width: 20, height: 20, borderRadius: 999, background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,0.2)', transition: 'left 200ms ease' }} />
  </button>;


// ============================================================================
// SCREEN — gives screen a scroll container + safe areas
// ============================================================================
const HScreen = ({ children, bg, pad = '0 16px 140px', label }) =>
<div data-screen-label={label} className="scroll-y" style={{
  position: 'absolute', top: 0, left: 0, right: 0, bottom: 0,
  background: bg || 'var(--t-bg)',
  color: 'var(--t-fg-1)',
  overflowY: 'auto', WebkitOverflowScrolling: 'touch',
  paddingTop: 56 /* reserve for iOS status bar */
}}>
    <div style={{ padding: pad }}>
      {children}
    </div>
  </div>;


// ============================================================================
// ALIGNED COMPONENTS — mirror the actual repo (`healify/src/components/...`):
//   • HUserBanner       — dark pill greeting + score badge (UserBanner)
//   • HSyncBanner       — Apple Health sync progress (SyncProgressBanner)
//   • HFocusRowAligned  — icon + title + status pill + dot + chevron (HFocusRow)
//   • HRecCard          — recommendation card with metric, status, last detected
//   • HToolTile         — 2x2 AI tools grid tile (HToolTile)
// ============================================================================

// Person/body silhouette icon for the Biometrics focus area.
HIcons.body = "M12 4a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm-3 8h6c1 0 2 .9 2 2 0 1.5-1.5 3-4 3-1 0-1.5 1.5-1.5 3v1h-3v-3.5c-2.5 0-3.5-1.5-3.5-3 0-1.1.9-2 2-2Z";
HIcons.refresh = "M4 12a8 8 0 0 1 14-5l2-2v6h-6l2.5-2.5A6 6 0 1 0 18 12";

// Domain meta — name, color token, icon. Matches the repo's focus types.
const FOCUS_META = {
  sleep:      { title: 'Sleep',      color: 'var(--focus-sleep)',     tint: 'var(--focus-sleep-tint)',     icon: 'moon' },
  fitness:    { title: 'Fitness',    color: 'var(--focus-fitness)',   tint: 'var(--focus-fitness-tint)',   icon: 'dumbbell' },
  vitals:     { title: 'Vitals',     color: 'var(--focus-heart)',     tint: 'var(--focus-heart-tint)',     icon: 'heart' },
  mind:       { title: 'Mind',       color: 'var(--focus-mental)',    tint: 'var(--focus-mental-tint)',    icon: 'brain' },
  biometrics: { title: 'Biometrics', color: 'var(--brand-orange-vibey)', tint: 'rgba(255,105,66,0.12)',    icon: 'body' },
  nutrition:  { title: 'Nutrition',  color: 'var(--focus-nutrition)', tint: 'var(--focus-nutrition-tint)', icon: 'plate' },
};

// Status helpers — match repo's status semantics (normal/fair/needs_attention/pending).
const STATUS_META = {
  normal:    { label: 'Normal',          dot: 'var(--success)' },
  on_track:  { label: 'On track',        dot: 'var(--success)' },
  fair:      { label: 'Fair',            dot: 'var(--warning-soft, #FF8B6D)' },
  attention: { label: 'Needs Attention', dot: 'var(--error)' },
  bad:       { label: 'Needs Attention', dot: 'var(--error)' },
  pending:   { label: 'Calculating…',    dot: 'var(--t-fg-3)' },
};

// ────────────────────────────────────────────────────────────────────────────
// HUserBanner — dark 40-radius pill at top of Home.
// Avatar + "Good morning, {Name}" + refresh + Score badge. Matches the
// UserBanner / HGreetingHeader pattern observed in the live app.
// ────────────────────────────────────────────────────────────────────────────
const HUserBanner = ({ name = '', greeting, score, syncing = false, onMenuPress, onScorePress, onRefresh }) => {
  const greet = greeting || (() => {
    const h = new Date().getHours();
    if (h < 12) return 'Good morning';
    if (h < 18) return 'Good afternoon';
    return 'Good evening';
  })();
  const initial = (name || 'U').trim().charAt(0).toUpperCase();
  return (
    <div style={{
      background: 'var(--brand-ink)',
      borderRadius: 40,
      padding: '12px 14px 12px 12px',
      display: 'flex', alignItems: 'center', gap: 12,
      minHeight: 64,
    }}>
      {/* Avatar circle — solid orange with first initial */}
      <button onClick={onMenuPress} aria-label="Menu" style={{
        width: 44, height: 44, borderRadius: 999, flexShrink: 0,
        background: 'var(--brand-orange-vibey)',
        color: '#fff',
        fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 18, letterSpacing: '-0.5px',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {initial}
      </button>

      {/* Greeting block */}
      <div style={{ flex: 1, minWidth: 0, color: '#fff' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, color: 'rgba(255,255,255,0.65)', lineHeight: 1.2 }}>
          <Glyph name="sparkle" size={11} stroke={1.6} />
          <span>{greet},</span>
        </div>
        <div style={{
          fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 19,
          letterSpacing: '-0.3px', color: '#fff', marginTop: 2,
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>{name || 'there'}</div>
      </div>

      {/* Refresh icon */}
      <button onClick={onRefresh} aria-label="Refresh" style={{
        width: 32, height: 32, borderRadius: 999, flexShrink: 0,
        background: 'transparent', color: 'rgba(255,255,255,0.7)',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <Glyph name="refresh" size={18} stroke={1.8} />
      </button>

      {/* Score badge — translucent pill with small label + big number */}
      <button onClick={onScorePress} aria-label={`Health score ${score ?? 'pending'}`} style={{
        flexShrink: 0,
        padding: '6px 12px', borderRadius: 16,
        background: 'rgba(255,255,255,0.08)',
        display: 'flex', flexDirection: 'column', alignItems: 'flex-end',
        lineHeight: 1.1,
      }}>
        <span style={{ fontSize: 9.5, color: 'rgba(255,255,255,0.55)', letterSpacing: 0.5, textTransform: 'uppercase', fontWeight: 500 }}>Score</span>
        <span style={{ fontFamily: 'var(--font-display)', fontSize: 18, fontWeight: 600, color: '#fff', letterSpacing: '-0.3px', marginTop: 1 }}>
          {score != null ? `${score}%` : '—'}
        </span>
      </button>
    </div>
  );
};

// ────────────────────────────────────────────────────────────────────────────
// HSyncBanner — full-width white card with progress bar + label.
// "Syncing 1,440 of 1,440 data points…" — mirrors SyncProgressBanner.
// ────────────────────────────────────────────────────────────────────────────
const HSyncBanner = ({ done = 0, total = 0, label, hidden = false }) => {
  if (hidden) return null;
  const pct = total > 0 ? Math.max(0, Math.min(1, done / total)) : 0;
  const text = label || `Syncing ${done.toLocaleString()} of ${total.toLocaleString()} data points…`;
  return (
    <HCard pad="14px 16px" radius={16}>
      <div style={{ fontSize: 13.5, color: 'var(--t-fg-1)', letterSpacing: '-0.1px', lineHeight: 1.3 }}>
        {text}
      </div>
      <div style={{ marginTop: 10, height: 4, borderRadius: 999, background: 'color-mix(in oklab, var(--brand-orange-vibey) 12%, transparent)', overflow: 'hidden' }}>
        <div style={{
          height: '100%',
          width: `${pct * 100}%`,
          background: 'var(--grad-warm-orange)',
          borderRadius: 999,
          transition: 'width 600ms cubic-bezier(.2,.7,.3,1)',
        }} />
      </div>
    </HCard>
  );
};

// ────────────────────────────────────────────────────────────────────────────
// HFocusRowAligned — the canonical focus row from the repo.
// 44px icon tile (tint @14%, icon in solid domain color) + title +
// status text + status dot + chevron. Domain-driven, no metric/sparkline.
// `ctaPill` swaps the status text for an outlined orange pill (e.g. "Log
// Your First Meal" empty state for Nutrition).
// ────────────────────────────────────────────────────────────────────────────
const HFocusRowAligned = ({ domain, title, status = 'normal', ctaPill, opened = false, onClick }) => {
  const meta = FOCUS_META[domain] || FOCUS_META.nutrition;
  const s = STATUS_META[status] || STATUS_META.normal;
  return (
    <HCard pad="14px 16px" radius={20} onClick={onClick}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, minHeight: 44 }}>
        <div style={{
          width: 44, height: 44, borderRadius: 999, flexShrink: 0,
          background: meta.tint,
          color: meta.color,
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Glyph name={meta.icon} size={22} stroke={1.9} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 17,
            color: 'var(--t-fg-1)', letterSpacing: '-0.3px',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{title || meta.title}</div>
        </div>
        {ctaPill ? (
          <span style={{
            padding: '5px 10px', borderRadius: 999,
            border: '1px solid color-mix(in oklab, var(--brand-orange-vibey) 35%, transparent)',
            color: 'var(--brand-orange-vibey)',
            fontSize: 11.5, fontWeight: 500, letterSpacing: '-0.1px',
            whiteSpace: 'nowrap',
          }}>{ctaPill}</span>
        ) : (
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
            <span style={{ fontSize: 13, color: 'var(--t-fg-2)', letterSpacing: '-0.1px' }}>{s.label}</span>
            <span style={{ width: 8, height: 8, borderRadius: 999, background: s.dot }} />
          </span>
        )}
        <Glyph name={opened ? 'chevU' : 'chevD'} size={14} stroke={2} style={{ color: 'var(--t-fg-3)', marginLeft: 6 }} />
      </div>
    </HCard>
  );
};

// ────────────────────────────────────────────────────────────────────────────
// HRecCard — recommendation card. Used under "RECOMMENDATIONS".
// White card, 12px icon tile + metric name + status + last detected.
// ────────────────────────────────────────────────────────────────────────────
const HRecCard = ({ metric, status = 'fair', domain = 'vitals', detected, onClick }) => {
  const meta = FOCUS_META[domain] || FOCUS_META.vitals;
  const s = STATUS_META[status] || STATUS_META.fair;
  return (
    <HCard pad="14px 16px" radius={16} onClick={onClick}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <div style={{
          width: 36, height: 36, borderRadius: 12, flexShrink: 0,
          background: meta.tint, color: meta.color,
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Glyph name={meta.icon} size={18} stroke={1.9} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontFamily: 'var(--font-display)', fontSize: 15, fontWeight: 500,
            color: 'var(--t-fg-1)', letterSpacing: '-0.2px',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>{metric}</div>
          {detected ? (
            <div style={{ fontSize: 11.5, color: 'var(--t-fg-3)', marginTop: 1 }}>{detected}</div>
          ) : null}
        </div>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, flexShrink: 0 }}>
          <span style={{ fontSize: 12, color: 'var(--t-fg-2)' }}>{s.label}</span>
          <span style={{ width: 8, height: 8, borderRadius: 999, background: s.dot }} />
        </span>
        <Glyph name="chevR" size={14} stroke={2} style={{ color: 'var(--t-fg-3)' }} />
      </div>
    </HCard>
  );
};

// ────────────────────────────────────────────────────────────────────────────
// HToolTile — AI Tools 2x2 grid tile.
// White card, 40px tinted icon tile + title + subtitle. Matches the repo's
// HToolTile primitive (src/components/ui/h-ds/h-tool-tile.tsx).
// ────────────────────────────────────────────────────────────────────────────
const HToolTile = ({ title, subtitle, domain = 'nutrition', icon, onClick }) => {
  const meta = FOCUS_META[domain] || FOCUS_META.nutrition;
  const ico = icon || meta.icon;
  return (
    <button onClick={onClick} style={{
      flex: 1, minWidth: 0,
      background: 'var(--t-surface)', boxShadow: 'var(--shadow-sm)',
      borderRadius: 18, padding: 14,
      display: 'flex', flexDirection: 'column', gap: 10, textAlign: 'left',
    }}>
      <div style={{
        width: 40, height: 40, borderRadius: 12,
        background: meta.tint, color: meta.color,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <Glyph name={ico} size={20} stroke={1.9} />
      </div>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 15, color: 'var(--t-fg-1)', letterSpacing: '-0.2px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</div>
        {subtitle ? <div style={{ fontSize: 12, color: 'var(--t-fg-2)', marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{subtitle}</div> : null}
      </div>
    </button>
  );
};

// ────────────────────────────────────────────────────────────────────────────
// HMedicalDisclaimer — small footer disclaimer matching the repo.
// ────────────────────────────────────────────────────────────────────────────
const HMedicalDisclaimer = () => (
  <div style={{
    padding: '8px 10px', textAlign: 'center',
    fontSize: 10.5, lineHeight: 1.4, color: 'var(--t-fg-3)',
    letterSpacing: '-0.1px',
  }}>
    For educational purposes only. Not medical advice. Sources include peer-reviewed medical literature and clinical guidelines.
  </div>
);

// ============================================================================
// Export to window so other Babel files can use these
// ============================================================================
Object.assign(window, {
  HCard, HSectionLabel, HPrimaryButton, HIconButton, HBackButton,
  HTopBar, HTabBar, HealifyHeart, HealifyWordmark, HAnnaAvatar, AnnaMonogram, HChip, HQuickReplies,
  HFocusRing, HSparkline, HMiniBars, HStatus, HFocusRow,
  HUserBanner, HSyncBanner, HFocusRowAligned, HRecCard, HToolTile, HMedicalDisclaimer,
  FOCUS_META, STATUS_META,
  HChatBubble, HNumberedActions, HSourceChips, HBubbleDataCard, HTyping,
  HHabitCheck, HSettingsRow, Toggle, HScreen,
  Glyph, Icon, HIcons, CountUp
});