/* Peptino — shared helpers + icons. Exported to window. */

/* ---------------- Icons (stroke, 24 grid) ---------------- */
const ICON = {
  check:      'M20 6L9 17l-5-5',
  clock:      'M12 7v5l3 2 M12 21a9 9 0 100-18 9 9 0 000 18',
  flame:      'M12 3c1 3 4 4 4 8a4 4 0 01-8 0c0-1 .5-2 1-2.5C9 11 12 9 12 3z',
  bolt:       'M13 2L4 14h7l-1 8 9-12h-7l1-8z',
  moon:       'M21 12.8A9 9 0 1111.2 3 7 7 0 0021 12.8z',
  brain:      'M9 3a3 3 0 00-3 3 3 3 0 00-2 5 3 3 0 001 5 3 3 0 005 1V3z M15 3a3 3 0 013 3 3 3 0 012 5 3 3 0 01-1 5 3 3 0 01-5 1V3z',
  sparkle:    'M12 3l1.6 5.4L19 10l-5.4 1.6L12 17l-1.6-5.4L5 10l5.4-1.6z',
  flask:      'M9 3h6 M10 3v6l-5 9a2 2 0 002 3h10a2 2 0 002-3l-5-9V3 M7.5 15h9',
  calendar:   'M7 3v3 M17 3v3 M4 8h16 M5 5h14a1 1 0 011 1v13a1 1 0 01-1 1H5a1 1 0 01-1-1V6a1 1 0 011-1z',
  search:     'M11 18a7 7 0 100-14 7 7 0 000 14z M21 21l-4-4',
  settings:   'M12 9a3 3 0 100 6 3 3 0 000-6z M19 12a7 7 0 00-.1-1.3l2-1.6-2-3.4-2.4 1a7 7 0 00-2.2-1.3L14 2h-4l-.3 2.1a7 7 0 00-2.2 1.3l-2.4-1-2 3.4 2 1.6A7 7 0 005 12a7 7 0 00.1 1.3l-2 1.6 2 3.4 2.4-1a7 7 0 002.2 1.3L10 22h4l.3-2.1a7 7 0 002.2-1.3l2.4 1 2-3.4-2-1.6A7 7 0 0019 12z',
  plus:       'M12 5v14 M5 12h14',
  chevR:      'M9 6l6 6-6 6',
  chevB:      'M15 6l-6 6 6 6',
  chevD:      'M6 9l6 6 6-6',
  bell:       'M18 8a6 6 0 10-12 0c0 7-3 9-3 9h18s-3-2-3-9 M13.7 21a2 2 0 01-3.4 0',
  person:     'M12 12a4 4 0 100-8 4 4 0 000 8z M5 21a7 7 0 0114 0',
  syringe:    'M18 2l4 4 M17 5l2 2 M15 7l2 2-6 6-3 1-1-1 1-3 6-6z M9 13l-5 5 M5 17l2 2',
  droplet:    'M12 3s6 6.5 6 11a6 6 0 11-12 0c0-4.5 6-11 6-11z',
  pause:      'M9 4v16 M15 4v16',
  trophy:     'M7 4h10v5a5 5 0 01-10 0V4z M5 5H3v2a3 3 0 003 3 M19 5h2v2a3 3 0 01-3 3 M9 19h6 M12 14v5',
  ruler:      'M3 8l5-5 13 13-5 5L3 8z M8 7l2 2 M11 10l2 2 M14 13l2 2',
  shield:     'M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z',
  pill:       'M10.5 13.5l3-3 M8 6l-2 2a4 4 0 000 6l2 2 6-6-2-2a4 4 0 00-6 0z',
  arrowUp:    'M12 19V5 M5 12l7-7 7 7',
  arrowDown:  'M12 5v14 M19 12l-7 7-7-7',
  edit:       'M12 20h9 M16.5 3.5a2.1 2.1 0 013 3L7 19l-4 1 1-4 12.5-12.5z',
  info:       'M12 21a9 9 0 100-18 9 9 0 000 18z M12 11v5 M12 8h.01',
  chart:      'M3 3v18h18 M7 14l3-3 3 2 4-5',
  dna:        'M7 3c0 4 10 6 10 9s-10 5-10 9 M17 3c0 4-10 6-10 9s10 5 10 9 M8 6h8 M8 18h8',
  lock:       'M5 11h14v9H5z M8 11V8a4 4 0 018 0v3',
  download:   'M12 4v11 M8 11l4 4 4-4 M5 20h14',
  globe:      'M12 21a9 9 0 100-18 9 9 0 000 18z M3 12h18 M12 3c2.5 2.7 2.5 15.3 0 18 M12 3c-2.5 2.7-2.5 15.3 0 18',
  cube:       'M12 2l9 5v10l-9 5-9-5V7l9-5z M12 12l9-5 M12 12v10 M12 12L3 7',
  ellipsis:   'M5 12h.01 M12 12h.01 M19 12h.01',
  calculator: 'M6 2h12a1 1 0 011 1v18a1 1 0 01-1 1H6a1 1 0 01-1-1V3a1 1 0 011-1z M8 6h8 M8 11h.01 M12 11h.01 M16 11h.01 M8 15h.01 M12 15h.01 M16 15v4',
  book:       'M4 4a2 2 0 012-2h13v18H6a2 2 0 00-2 2V4z M4 4v16',
  trash:      'M4 7h16 M9 7V4h6v3 M6 7l1 13h10l1-13',
  bookmark:   'M6 3h12v18l-6-4-6 4V3z',
  close:      'M6 6l12 12 M18 6L6 18',
  target:     'M12 21a9 9 0 100-18 9 9 0 000 18z M12 16a4 4 0 100-8 4 4 0 000 8z M12 12h.01',
  trending:   'M3 17l6-6 4 4 8-8 M15 7h6v6',
  apple:      'M16 3c.1 1-.3 2-1 2.7-.7.8-1.7 1.3-2.7 1.2-.1-1 .4-2 1-2.7C14 3.5 15 3 16 3z M19 17c-.5 1.2-1.1 2.3-2 3.3-.8.9-1.4 1.5-2.4 1.5s-1.3-.4-2.4-.4-1.5.4-2.5.4-1.6-.6-2.4-1.5C3.5 18.6 2.5 15 4 12.5c.8-1.3 2-2 3.3-2 1 0 1.9.5 2.5.5s1.7-.6 2.9-.5c.9 0 2.3.4 3.2 1.7-2.8 1.6-2.3 5.5.1 5.3z',
  bell2:      'M18 8a6 6 0 10-12 0c0 7-3 9-3 9h18s-3-2-3-9 M13.7 21a2 2 0 01-3.4 0',
};
function Icon({ name, size = 22, sw = 1.9, color = 'currentColor', fill = 'none', style }) {
  return (
    <svg className="icon" width={size} height={size} viewBox="0 0 24 24" fill={fill}
      stroke={color} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}>
      <path d={ICON[name] || ICON.info} />
    </svg>
  );
}

/* ---------------- Status bar ---------------- */
function StatusBar({ time = '9:41' }) {
  return (
    <div className="statusbar c-1">
      <span className="num">{time}</span>
      <span className="icons">
        <svg width="18" height="12" viewBox="0 0 18 12" fill="currentColor"><rect x="0" y="7" width="3" height="5" rx="1"/><rect x="5" y="4" width="3" height="8" rx="1"/><rect x="10" y="1.5" width="3" height="10.5" rx="1"/><rect x="15" y="0" width="3" height="12" rx="1" opacity="0.35"/></svg>
        <svg width="17" height="12" viewBox="0 0 17 12" fill="currentColor"><path d="M8.5 2.5c2 0 3.8.8 5.2 2.1l1.1-1.2A9 9 0 008.5 1 9 9 0 002.2 3.4l1.1 1.2A7.4 7.4 0 018.5 2.5z" opacity="0.9"/><path d="M8.5 6c1.1 0 2.1.4 2.8 1.2l1.2-1.2A6 6 0 008.5 4.3a6 6 0 00-4 1.7l1.2 1.2A4 4 0 018.5 6z"/><circle cx="8.5" cy="9.5" r="1.6"/></svg>
        <svg width="26" height="12" viewBox="0 0 26 12" fill="none"><rect x="1" y="1" width="21" height="10" rx="2.5" stroke="currentColor" opacity="0.4"/><rect x="3" y="3" width="15" height="6" rx="1.2" fill="currentColor"/><rect x="23.5" y="4" width="1.5" height="4" rx="0.75" fill="currentColor" opacity="0.5"/></svg>
      </span>
    </div>
  );
}

/* ---------------- Progress ring ---------------- */
function Ring({ progress = 0.75, size = 140, stroke = 14, children }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const off = c * (1 - Math.max(0, Math.min(1, progress)));
  const ctr = size / 2;
  return (
    <div style={{ width: size, height: size, position: 'relative', flex: '0 0 ' + size + 'px' }}>
      <svg width={size} height={size}>
        <circle cx={ctr} cy={ctr} r={r} fill="none" stroke="var(--sunken)" strokeWidth={stroke} />
        <circle cx={ctr} cy={ctr} r={r} fill="none" stroke="var(--accent)" strokeWidth={stroke}
          strokeLinecap="round" strokeDasharray={c} strokeDashoffset={off}
          transform={`rotate(-90 ${ctr} ${ctr})`} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        {children}
      </div>
    </div>
  );
}

/* ---------------- Decay chart ---------------- */
function DecayChart({ width = 318, height = 150, halfLife = 0.5, peak = 0.62, label = '4h' }) {
  // exponential decay sampled across the view; serum rises fast then decays
  const pad = { l: 6, r: 6, t: 10, b: 20 };
  const W = width - pad.l - pad.r, H = height - pad.t - pad.b;
  const N = 60;
  const pts = [];
  for (let i = 0; i <= N; i++) {
    const t = i / N;                       // 0..1 of timeline
    // rise to peak then exponential decay
    const rise = Math.min(1, t / peak * 1.0);
    const f = t <= peak ? Math.pow(rise, 0.65) : Math.exp(-(t - peak) / halfLife);
    pts.push([pad.l + t * W, pad.t + (1 - f) * H]);
  }
  const line = pts.map((p, i) => (i ? 'L' : 'M') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');
  const area = line + ` L ${pad.l + W} ${pad.t + H} L ${pad.l} ${pad.t + H} Z`;
  const nowX = pad.l + 0.42 * W;
  const peakX = pad.l + peak * W, peakY = pad.t;
  const grid = [0.25, 0.5, 0.75].map((g) => pad.t + g * H);
  const id = 'dg' + Math.round(peak * 100);
  return (
    <svg width={width} height={height}>
      <defs>
        <linearGradient id={id} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor="var(--accent)" stopOpacity="0.22" />
          <stop offset="1" stopColor="var(--accent)" stopOpacity="0.01" />
        </linearGradient>
      </defs>
      {grid.map((y, i) => <line key={i} x1={pad.l} y1={y} x2={pad.l + W} y2={y} stroke="var(--border)" strokeWidth="1" />)}
      <path d={area} fill={`url(#${id})`} />
      <path d={line} fill="none" stroke="var(--accent)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
      <line x1={nowX} y1={pad.t} x2={nowX} y2={pad.t + H} stroke="var(--text-3)" strokeWidth="1.4" strokeDasharray="3 3" />
      <circle cx={peakX} cy={peakY + 2} r="4" fill="var(--accent)" stroke="var(--surface)" strokeWidth="2" />
      {['0h', '2h', label, '8h', '12h'].map((t, i) => (
        <text key={i} x={pad.l + (i / 4) * W} y={height - 5} fontSize="10.5" fontWeight="600"
          fill="var(--text-3)" textAnchor={i === 0 ? 'start' : i === 4 ? 'end' : 'middle'} fontFamily="Hanken Grotesk">{t}</text>
      ))}
    </svg>
  );
}

/* ---------------- Vial gauge ---------------- */
function Vial({ level = 0.46, width = 60, height = 132, tone }) {
  const neckH = 14, capH = 9, bodyTop = capH + neckH, bodyH = height - bodyTop;
  const fillH = bodyH * Math.max(0.04, Math.min(1, level));
  const fillY = bodyTop + (bodyH - fillH);
  const col = tone || 'var(--accent)';
  const low = level <= 0.2;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
      <defs><clipPath id={'vc' + Math.round(level * 100)}><rect x="9" y={bodyTop} width={width - 18} height={bodyH} rx="9" /></clipPath></defs>
      {/* cap + neck */}
      <rect x={width / 2 - 11} y="0" width="22" height={capH} rx="2.5" fill="var(--border-strong)" />
      <rect x={width / 2 - 8} y={capH} width="16" height={neckH} fill="var(--sunken)" />
      {/* body well */}
      <rect x="9" y={bodyTop} width={width - 18} height={bodyH} rx="9" fill="var(--sunken)" />
      {/* liquid */}
      <g clipPath={`url(#vc${Math.round(level * 100)})`}>
        <rect x="9" y={fillY} width={width - 18} height={fillH} fill={low ? 'var(--danger-fill)' : col} opacity={low ? 0.9 : 0.85} />
        <ellipse cx={width / 2} cy={fillY} rx={(width - 18) / 2} ry="3" fill={low ? 'var(--danger-fill)' : col} />
      </g>
      <rect x="9" y={bodyTop} width={width - 18} height={bodyH} rx="9" fill="none" stroke="var(--border-strong)" strokeWidth="1.5" />
    </svg>
  );
}

/* ---------------- Tab bar (Today · Inventory · + · Protocols · More) ---------------- */
function TabBar({ active = 'today' }) {
  const tabs = [
    { k: 'today', label: 'Today', icon: 'check' },
    { k: 'inventory', label: 'Fridge', icon: 'cube' },
    { k: 'protocols', label: 'Protocols', icon: 'flask' },
    { k: 'more', label: 'More', icon: 'ellipsis' },
  ];
  return (
    <div className="tabbar">
      {tabs.slice(0, 2).map((t) => <TabItem key={t.k} t={t} active={active} />)}
      <div className="tab-add"><Icon name="plus" size={28} sw={2.4} /></div>
      {tabs.slice(2).map((t) => <TabItem key={t.k} t={t} active={active} />)}
    </div>
  );
}
function TabItem({ t, active }) {
  const on = t.k === active;
  return (
    <div className={'tab' + (on ? ' on' : '')}>
      <div className="ic"><Icon name={t.icon} size={22} sw={on ? 2.1 : 1.8} /></div>
      <span className="lbl">{t.label}</span>
    </div>
  );
}

/* ---------------- Calendar grid ---------------- */
function MiniCalendar({ selected = 18 }) {
  const wd = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
  // status by day: taken / partial / missed / pending / empty
  const status = {
    1:'t',2:'t',3:'t',4:'p',5:'t',6:'t',7:'m',8:'t',9:'t',10:'t',11:'t',12:'t',13:'t',14:'t',
    15:'t',16:'p',17:'t',18:'cur',19:'',20:'',21:'',22:'',23:'',24:'',25:'',26:'',27:'',28:'',29:'',30:''
  };
  const dotColor = { t: 'var(--accent)', p: 'var(--warning-fill)', m: 'var(--danger-fill)' };
  const cells = [];
  for (let i = 0; i < 2; i++) cells.push(null); // month starts Wed
  for (let d = 1; d <= 30; d++) cells.push(d);
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', marginBottom: 6 }}>
        {wd.map((w, i) => <div key={i} className="t-label c-3" style={{ textAlign: 'center', fontSize: 10 }}>{w}</div>)}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', rowGap: 4 }}>
        {cells.map((d, i) => {
          if (!d) return <div key={i} />;
          const s = status[d] || '';
          const isSel = d === selected;
          const isCur = s === 'cur';
          return (
            <div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3, padding: '3px 0' }}>
              <div style={{
                width: 32, height: 32, borderRadius: 11, display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontWeight: isSel || isCur ? 700 : 500, fontSize: 14,
                background: isSel ? 'var(--accent)' : isCur ? 'var(--accent-soft)' : 'transparent',
                color: isSel ? 'var(--accent-fg)' : isCur ? 'var(--accent-ink)' : 'var(--text-1)',
                fontVariantNumeric: 'tabular-nums',
              }}>{d}</div>
              <div style={{ height: 5, display: 'flex', gap: 2 }}>
                {dotColor[s] ? <span style={{ width: 5, height: 5, borderRadius: 3, background: dotColor[s] }} /> : null}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

Object.assign(window, { Icon, StatusBar, Ring, DecayChart, Vial, TabBar, TabItem, MiniCalendar, DropletGlyph });

/* ---------------- Droplet brand glyph ---------------- */
function DropletGlyph({ size = 72, tone = 'var(--accent)', variant = 'solid' }) {
  const dPath = "M50 22 C 60 42, 73 50, 73 61 A 23 23 0 1 1 27 61 C 27 50, 40 42, 50 22 Z";
  const cid = 'dg' + Math.round(size) + variant;
  if (variant === 'level') {
    return (
      <svg width={size} height={size} viewBox="0 0 100 100" style={{ display: 'block' }}>
        <defs>
          <clipPath id={cid + 'c'}><path d={dPath} /></clipPath>
          <linearGradient id={cid + 'g'} x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#1E2B11" /><stop offset="100%" stopColor="#0F1709" /></linearGradient>
          <linearGradient id={cid + 'l'} x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#D4F564" /><stop offset="100%" stopColor="#A6D81F" /></linearGradient>
        </defs>
        <g clipPath={`url(#${cid}c)`}>
          <rect x="20" y="18" width="60" height="74" fill={`url(#${cid}g)`} />
          <rect x="20" y="53" width="60" height="40" fill={`url(#${cid}l)`} />
          <ellipse cx="50" cy="53" rx="30" ry="3.2" fill="#E8FC8C" />
          <circle cx="58" cy="68" r="3" fill="#E4FB8A" opacity=".55" />
          <path d="M36 30 C 33 38, 32 46, 33 52" fill="none" stroke="#ffffff" strokeWidth="3" strokeLinecap="round" opacity=".22" />
        </g>
        <path d={dPath} fill="none" stroke="#C4F23D" strokeWidth="3.2" strokeLinejoin="round" />
      </svg>
    );
  }
  return (
    <svg width={size} height={size} viewBox="0 0 100 100" style={{ display: 'block' }}>
      <defs>
        <linearGradient id={cid} x1="28%" y1="14%" x2="74%" y2="92%">
          <stop offset="0" stopColor="#DCFB78" /><stop offset="48%" stopColor="#C4F23D" /><stop offset="100%" stopColor="#A6D81F" />
        </linearGradient>
      </defs>
      <path d={dPath} fill={tone === 'var(--accent)' ? `url(#${cid})` : tone} />
      <ellipse cx="40" cy="56" rx="6" ry="11" transform="rotate(-24 40 56)" fill="#ffffff" opacity=".42" />
    </svg>
  );
}
window.DropletGlyph = DropletGlyph;

/* ---------------- App icon tile (droplet on its dark squircle) ---------------- */
function AppIconTile({ size = 96, radius }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: radius || Math.round(size * 0.224),
      background: 'radial-gradient(125% 125% at 30% 18%, #202126 0%, #0d0d0f 58%, #070708 100%)',
      boxShadow: '0 1px 2px rgba(0,0,0,.12), 0 16px 34px rgba(0,0,0,.20)',
      position: 'relative', overflow: 'hidden', flex: '0 0 auto',
    }}>
      <div style={{ position: 'absolute', inset: 0 }}><DropletGlyph size={size} variant="level" /></div>
      <div style={{ position: 'absolute', inset: 0, borderRadius: 'inherit', boxShadow: 'inset 0 0 0 1px rgba(255,255,255,.06)' }} />
    </div>
  );
}
window.AppIconTile = AppIconTile;
