// shared.jsx — design tokens, copy, placeholders, and the live lab-data widget.

// ── Palettes ─────────────────────────────────────────────────────────────
// Each preserves "deep navy + warm cream"; only the accent + ink shift.
const PALETTES = {
  marine: {
    name: 'Marine',
    ink: '#0E1E3A',     // deep navy
    inkSoft: '#1B2C4A',
    cream: '#F2EBDD',   // warm cream
    creamDeep: '#E8DFCB',
    paper: '#FBF7EE',
    line: '#1E3158',
    accent: '#B8965B',  // restrained gold
    accentSoft: '#D6BB87',
    muted: '#5B6783',
    signal: '#3D7CD9',
  },
  graphite: {
    name: 'Graphite',
    ink: '#0A1628',
    inkSoft: '#16243C',
    cream: '#ECE6D9',
    creamDeep: '#DCD5C5',
    paper: '#F6F1E5',
    line: '#1A2A45',
    accent: '#3FB6C2',  // signal cyan
    accentSoft: '#7BCED7',
    muted: '#4A5870',
    signal: '#3FB6C2',
  },
  atlantic: {
    name: 'Atlantic',
    ink: '#142244',
    inkSoft: '#1F315A',
    cream: '#EFE4D0',
    creamDeep: '#E0D2B7',
    paper: '#F8F1E2',
    line: '#1F315A',
    accent: '#7A8F6E',  // sage
    accentSoft: '#A4B499',
    muted: '#5B6480',
    signal: '#5B7AB8',
  },
};

// ── Type pairings ────────────────────────────────────────────────────────
const TYPES = {
  editorial: {
    name: 'Editorial',
    display: '"Source Serif 4", "Source Serif Pro", Georgia, serif',
    body:    '"Geist", ui-sans-serif, system-ui, sans-serif',
    mono:    '"Geist Mono", ui-monospace, monospace',
    displayWeight: 400,
    displayTracking: '-0.022em',
  },
  clinical: {
    name: 'Clinical',
    display: '"Newsreader", "Source Serif 4", Georgia, serif',
    body:    '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif',
    mono:    '"IBM Plex Mono", ui-monospace, monospace',
    displayWeight: 400,
    displayTracking: '-0.018em',
  },
  technical: {
    name: 'Technical',
    display: '"Geist", ui-sans-serif, system-ui, sans-serif',
    body:    '"Geist", ui-sans-serif, system-ui, sans-serif',
    mono:    '"Geist Mono", ui-monospace, monospace',
    displayWeight: 500,
    displayTracking: '-0.034em',
  },
};

// ── Hero copy variants ───────────────────────────────────────────────────
// One row per heroCopy value; each row supplies copy for both concepts.
const HERO_COPY = {
  optimize: {
    a: {
      eyebrow: 'A Florida concierge practice · By application',
      h: ['Optimize the years', 'you have ahead.'],
      sub: 'Every Man\'s Health is a regional Florida concierge practice for men who want their healthspan to keep pace with their life — built around an in-person physician relationship, coordinated laboratory testing, and longitudinal monitoring of the things that matter.',
    },
    b: {
      eyebrow: 'Signal · Insight · Plan',
      h: ['Your biology,', 'observed continuously.'],
      sub: 'A regional concierge practice for men — pairing coordinated laboratory testing with physician-guided plans built around the way your body actually changes.',
    },
  },
  practice: {
    a: {
      eyebrow: 'A modern concierge practice for men',
      h: ['Care, not commerce.', 'Built around the man.'],
      sub: 'A limited-panel Florida concierge program for prevention, hormones, metabolic health, sexual health, vitality, longevity and cognition — provided by physicians who see you in person, follow you longitudinally, and answer to you alone.',
    },
    b: {
      eyebrow: 'Lab-driven · Longitudinal',
      h: ['Lab-driven care,', 'built for the long arc.'],
      sub: 'We measure what matters, again and again — and give you the same view your physician sees. Your plan adapts as the data does, across the next thirty years of your life.',
    },
  },
  numbers: {
    a: {
      eyebrow: 'Know your numbers',
      h: ['Every man should know', 'his numbers.'],
      sub: 'A comprehensive in-person evaluation, coordinated laboratory testing, and a physician who knows your story. Membership covers your physician relationship, longitudinal monitoring, and the technology that keeps it all coordinated.',
    },
    b: {
      eyebrow: 'Health, instrumented',
      h: ['Care that learns', 'as you do.'],
      sub: 'Each visit, each lab draw, each adjustment becomes another data point. Our platform reads them together — your physician decides what changes, what holds, and what to watch.',
    },
  },
};

// ── Tone slider → CTA / phrasing ────────────────────────────────────────
// 1 = white-coat clinical, 10 = consumer DTC.
function toneCopy(t) {
  // Three bands keep the copy coherent without flickering on every tick.
  if (t <= 3) {
    return {
      band: 'clinical',
      ctaPrimary: 'Schedule an evaluation',
      ctaSecondary: 'Speak with our membership team',
      hookEyebrow: 'Florida concierge · Physician-directed',
      bandTag: 'Concierge medical practice · Florida',
    };
  }
  if (t <= 7) {
    return {
      band: 'balanced',
      ctaPrimary: 'Apply for membership',
      ctaSecondary: 'See how the program works',
      hookEyebrow: 'Florida concierge · Physician-led, lab-driven',
      bandTag: 'A concierge practice for men · By application',
    };
  }
  return {
    band: 'consumer',
    ctaPrimary: 'Begin your application',
    ctaSecondary: 'How the program works',
    hookEyebrow: 'A Florida concierge practice for men',
    bandTag: 'Limited panel · By application',
  };
}

// ── Service categories (shared) ─────────────────────────────────────────
const SERVICES = [
  { id: 'prevention', label: '01', title: 'Preventive medicine',
    body: 'Comprehensive baselines, cardiometabolic risk, cancer screening guidance, and the ordinary primary-care work that nothing else replaces.' },
  { id: 'hormone', label: '02', title: 'Hormone optimization',
    body: 'Testosterone, thyroid, adrenal and related axes — evaluated as part of the whole, monitored over time, and addressed through physician-guided plans. Never a medication-first prescription.' },
  { id: 'metabolic', label: '03', title: 'Metabolic health',
    body: 'Insulin sensitivity, lipid biology, body composition, sleep and recovery — the foundation under everything else.' },
  { id: 'sexual', label: '04', title: 'Sexual health',
    body: 'Libido, erectile function, pelvic health, fertility considerations — discussed plainly and treated through evidence-based pathways.' },
  { id: 'cognitive', label: '05', title: 'Cognitive performance',
    body: 'Sleep, mood, focus, and the metabolic and hormonal contributors that shape how your brain feels at fifty and at seventy-five.' },
  { id: 'longevity', label: '06', title: 'Healthspan & longevity',
    body: 'Longitudinal biomarkers, recovery, cardiorespiratory fitness, and the unglamorous habits that compound across decades.' },
];

// ── Life-stage personalization ──────────────────────────────────────────
const LIFE_STAGES = [
  { range: '30 – 44', focus: 'Prevention · Performance', body: 'Establish a meaningful baseline, protect the next two decades of cardiovascular and metabolic health, and act on the lifestyle inputs that compound the longest.' },
  { range: '45 – 59', focus: 'Hormones · Metabolic · Vitality', body: 'A more active period — energy, body composition, sleep architecture, sexual health and hormone trajectories all warrant deliberate attention. We map them together.' },
  { range: '60 +',     focus: 'Longevity · Cognition · Function', body: 'Healthspan — function, cognition, mobility, recovery, and resilience. The plan focuses on the inputs with the highest leverage on quality-of-life over the next decades.' },
];

// ── How-it-works steps ──────────────────────────────────────────────────
const STEPS = [
  { n: '01', t: 'Intake & history',
    a: 'A structured medical history, prior records, current medications, and the questions you want answered.',
    b: 'Structured intake with a physician on file. Your records, history, medications, goals — captured once, kept current.' },
  { n: '02', t: 'Baseline laboratory',
    a: 'A comprehensive panel coordinated through trusted laboratory partners. Specimens drawn near you.',
    b: 'A comprehensive panel coordinated through trusted laboratory partners. Results return into your longitudinal record.' },
  { n: '03', t: 'Physician review',
    a: 'A licensed physician reviews your data, integrates it with your history, and meets with you over telehealth.',
    b: 'AI-assisted review surfaces patterns and outliers; a licensed physician interprets them with you on a video visit.' },
  { n: '04', t: 'Personalized plan',
    a: 'Lifestyle, monitoring, and — if and only if indicated — prescription or compounded therapeutics.',
    b: 'A living plan: lifestyle, monitoring cadence, prescriptions or 503A compounded therapies where clinically indicated.' },
  { n: '05', t: 'Continuous monitoring',
    a: 'Re-checks at thoughtful intervals. Your record is yours, longitudinal, and portable.',
    b: 'Recurring labs, in-app messaging, and timeline views your physician sees in the same window you do.' },
];

// ── Trust strip / credibility points ────────────────────────────────────
const TRUST = [
  { k: 'Lab-guided',  v: 'Coordinated through trusted partners' },
  { k: '503A',        v: 'Compliant compounding when clinically used' },
  { k: 'Telehealth',  v: 'Follow-up where licensed' },
  { k: 'No ads',      v: 'No insurance billing' },
];

// ── Compliance / care principles ────────────────────────────────────────
const PRINCIPLES = [
  ['Evidence first', 'We prescribe and treat where the medical literature supports it. We say "we don\'t know" when we don\'t.'],
  ['Physician-led, not medication-first', 'Therapeutics are one tool among many. Lifestyle, monitoring, and the physician relationship come first — and stay first.'],
  ['Technology supports the physician', 'Software helps organize, trend, and contextualize your record. Clinical interpretation and medical decisions stay with your physician.'],
  ['Your data, yours', 'Your longitudinal record belongs to you. Export it. Take it elsewhere. Bring it back.'],
];

// ── Visual placeholder — striped slate with mono caption ────────────────
function Placeholder({ label, w = '100%', h = 280, tone = '#0E1E3A', cream = '#F2EBDD', mono = '"Geist Mono", monospace', round = 0, dark = true }) {
  const stripeFg = dark ? 'rgba(255,255,255,0.04)' : 'rgba(0,0,0,0.04)';
  const stripeBg = dark ? tone : cream;
  const text = dark ? 'rgba(255,255,255,0.62)' : 'rgba(14,30,58,0.55)';
  const border = dark ? 'rgba(255,255,255,0.08)' : 'rgba(14,30,58,0.10)';
  return (
    <div style={{
      width: w, height: h, borderRadius: round,
      background: `repeating-linear-gradient(135deg, ${stripeBg} 0 14px, ${stripeFg} 14px 15px)`,
      position: 'relative', overflow: 'hidden',
      boxShadow: `inset 0 0 0 1px ${border}`,
    }}>
      <div style={{
        position: 'absolute', top: 12, left: 14,
        fontFamily: mono, fontSize: 10, letterSpacing: '0.12em',
        textTransform: 'uppercase', color: text,
      }}>{label}</div>
      <div style={{
        position: 'absolute', bottom: 12, right: 14,
        fontFamily: mono, fontSize: 9, letterSpacing: '0.16em',
        textTransform: 'uppercase', color: text, opacity: 0.7,
      }}>placeholder · drop image</div>
    </div>
  );
}

// ── AbstractPanel — brand-consistent NON-PHOTO visual ───────────────────
// A calm navy (or cream) field with a faint measurement grid and a quiet
// data motif. Replaces personal/photo placeholders: reads as a longitudinal
// record / signal field, not an image slot. variant: 'signal' | 'grid' |
// 'record' | 'monogram'.
function AbstractPanel({ label, tag, w = '100%', h = 280, tone = '#0E1E3A', cream = '#F2EBDD', accent = '#B8965B', mono = '"Geist Mono", monospace', variant = 'signal', dark = true, round = 0 }) {
  const bg = dark ? tone : cream;
  const ink = dark ? cream : tone;
  const line = dark ? 'rgba(242,235,221,0.10)' : 'rgba(14,30,58,0.10)';
  const text = dark ? 'rgba(242,235,221,0.62)' : 'rgba(14,30,58,0.55)';
  const grid = dark ? 'rgba(242,235,221,0.045)' : 'rgba(14,30,58,0.045)';
  const trend = [0.74, 0.68, 0.6, 0.55, 0.46, 0.4, 0.33, 0.3, 0.25, 0.2, 0.16, 0.12];
  const W = 320, Hs = 120;
  const xs = (i) => 12 + (i / (trend.length - 1)) * (W - 24);
  const ys = (v) => 12 + v * (Hs - 24);
  const path = trend.map((v, i) => `${i === 0 ? 'M' : 'L'} ${xs(i).toFixed(1)} ${ys(v).toFixed(1)}`).join(' ');
  return (
    <div style={{
      width: w, height: h, borderRadius: round, background: bg, position: 'relative', overflow: 'hidden',
      boxShadow: `inset 0 0 0 1px ${line}`,
      backgroundImage: `linear-gradient(${grid} 1px, transparent 1px), linear-gradient(90deg, ${grid} 1px, transparent 1px)`,
      backgroundSize: '28px 28px',
    }}>
      {variant === 'monogram' && (
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <svg width="40%" height="40%" viewBox="0 0 32 32" fill="none" aria-hidden="true" style={{ opacity: 0.5 }}>
            <circle cx="16" cy="16" r="15" stroke={ink} strokeWidth="0.8" />
            <path d="M9 22 V11 L16 19 L23 11 V22" stroke={accent} strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </div>
      )}
      {(variant === 'signal' || variant === 'record') && (
        <svg viewBox={`0 0 ${W} ${Hs}`} preserveAspectRatio="none" width="100%" height="100%"
             style={{ position: 'absolute', inset: 0, opacity: 0.6 }} aria-hidden="true">
          <path d={`${path} L ${xs(trend.length - 1)} ${Hs} L 12 ${Hs} Z`} fill={accent} fillOpacity="0.06" />
          <path d={path} fill="none" stroke={accent} strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" vectorEffect="non-scaling-stroke" />
          {variant === 'record' && [0.25, 0.5, 0.75].map((g) => (
            <line key={g} x1="12" x2={W - 12} y1={12 + g * (Hs - 24)} y2={12 + g * (Hs - 24)} stroke={ink} strokeOpacity="0.12" strokeDasharray="2 4" vectorEffect="non-scaling-stroke" />
          ))}
          <circle cx={xs(trend.length - 1)} cy={ys(trend[trend.length - 1])} r="2.5" fill={accent} />
        </svg>
      )}
      {label && <div style={{ position: 'absolute', top: 12, left: 14, fontFamily: mono, fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: text }}>{label}</div>}
      <div style={{ position: 'absolute', bottom: 12, right: 14, fontFamily: mono, fontSize: 9, letterSpacing: '0.16em', textTransform: 'uppercase', color: text, opacity: 0.7 }}>{tag || 'abstract · non-photo'}</div>
    </div>
  );
}

// ── LabChart — gentle longitudinal line, used in Concept A ─────────────
function LabChart({ p, accent, ink, mono, height = 180, label = 'TOTAL TESTOSTERONE · 18-MONTH TREND' }) {
  // Static-feeling chart with one animated 'now' dot that breathes slowly.
  const data = [380, 412, 447, 489, 523, 556, 612, 648, 671, 689, 702, 718];
  const min = 350, max = 750;
  const W = 640, H = height, padL = 56, padR = 24, padT = 18, padB = 28;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  const xs = (i) => padL + (i / (data.length - 1)) * innerW;
  const ys = (v) => padT + (1 - (v - min) / (max - min)) * innerH;
  const path = data.map((v, i) => `${i === 0 ? 'M' : 'L'} ${xs(i).toFixed(1)} ${ys(v).toFixed(1)}`).join(' ');
  const area = `${path} L ${xs(data.length - 1)} ${padT + innerH} L ${padL} ${padT + innerH} Z`;
  const [pulse, setPulse] = React.useState(0);
  React.useEffect(() => {
    let raf, t0 = performance.now();
    const tick = (t) => { setPulse(((t - t0) / 1800) % 1); raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  const last = data.length - 1;
  return (
    <div style={{ width: '100%', borderTop: `1px solid ${p.line}`, borderBottom: `1px solid ${p.line}`, padding: '16px 0', position: 'relative' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: mono, fontSize: 10, letterSpacing: '0.14em', color: p.muted, textTransform: 'uppercase', marginBottom: 6 }}>
        <span>{label}</span>
        <span>ng / dL</span>
      </div>
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} style={{ display: 'block' }}>
        {/* horizontal grid */}
        {[0, 0.25, 0.5, 0.75, 1].map((g) => (
          <line key={g} x1={padL} x2={W - padR}
                y1={padT + g * innerH} y2={padT + g * innerH}
                stroke={p.muted} strokeOpacity="0.18" strokeDasharray={g === 1 ? '0' : '2 4'} />
        ))}
        {/* y labels */}
        {[max, (max + min) / 2, min].map((v, i) => (
          <text key={v} x={padL - 10} y={padT + (i * innerH) / 2 + 4}
                fontFamily={mono} fontSize="10" fill={p.muted} textAnchor="end" letterSpacing="0.04em">{v}</text>
        ))}
        {/* reference band — clinically reasonable range */}
        <rect x={padL} y={ys(700)} width={innerW} height={ys(450) - ys(700)} fill={accent} fillOpacity="0.08" />
        {/* area */}
        <path d={area} fill={accent} fillOpacity="0.10" />
        {/* line */}
        <path d={path} fill="none" stroke={accent} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
        {/* points */}
        {data.map((v, i) => (
          <circle key={i} cx={xs(i)} cy={ys(v)} r={i === last ? 4 : 2.2}
                  fill={i === last ? accent : p.cream} stroke={accent} strokeWidth="1.4" />
        ))}
        {/* pulsing 'now' ring */}
        <circle cx={xs(last)} cy={ys(data[last])}
                r={6 + pulse * 10} fill="none" stroke={accent}
                strokeOpacity={0.6 - pulse * 0.6} strokeWidth="1.2" />
        {/* x labels */}
        {['M01', 'M06', 'M12', 'M18'].map((l, i) => {
          const x = padL + (i / 3) * innerW;
          return <text key={l} x={x} y={H - 8} fontFamily={mono} fontSize="10" fill={p.muted} textAnchor="middle" letterSpacing="0.14em">{l}</text>;
        })}
      </svg>
    </div>
  );
}

// ── Logo — simple custom mark (avoids generic medical cross/caduceus) ──
function EMHMark({ color = '#0E1E3A', size = 28 }) {
  // Two converging strokes — reads as 'M' / men's, also as a chevron.
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" aria-hidden="true">
      <circle cx="16" cy="16" r="15" fill="none" stroke={color} strokeWidth="1.2" />
      <path d="M9 22 V11 L16 19 L23 11 V22" fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// ── useViewport — responsive tier hook ─────────────────────────────────
// Single source of truth for breakpoints across all pages. Above 1024 every
// flag is false, so desktop styling is untouched. Tiers:
//   desktop  > 1024
//   tablet   769–1024   (isTablet)
//   large phone 561–768 (isMobile)
//   phone    ≤ 560      (isMobile + isPhone)
function useViewport() {
  const get = () => (typeof window === 'undefined' ? 1440 : window.innerWidth);
  const [w, setW] = React.useState(get);
  React.useEffect(() => {
    let raf = 0;
    const onResize = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => setW(get()));
    };
    window.addEventListener('resize', onResize);
    return () => { window.removeEventListener('resize', onResize); cancelAnimationFrame(raf); };
  }, []);
  return {
    w,
    isTablet: w <= 1024,   // tablet-and-below
    isMobile: w <= 768,    // stack to single column
    isPhone:  w <= 560,    // tightest tier
    // convenience: horizontal section padding for the current tier
    pad: w <= 560 ? 20 : w <= 768 ? 24 : w <= 1024 ? 40 : 72,
  };
}

Object.assign(window, {
  PALETTES, TYPES, HERO_COPY, toneCopy,
  SERVICES, LIFE_STAGES, STEPS, TRUST, PRINCIPLES,
  Placeholder, LabChart, EMHMark, useViewport, AbstractPanel,
});
