/**
 * PatientPortal.jsx
 * Personalized patient experience — new user onboarding + returning user dashboard.
 * Rendered at hash routes: #patient-portal (auto-selects mode based on journey)
 *
 * New user (isNew=true):     3-step wizard → save context → redirect to dashboard
 * Returning user (isNew=false): Personalized dashboard with history, quick actions, pending items
 */

const { useState, useEffect, useCallback } = React;

// ─── Icons (inline SVG) ───────────────────────────────────────────────────────
const Icon = ({ name, size = 20, color = 'currentColor', style = {} }) => {
  const icons = {
    tooth:      'M12 2C8.5 2 6 4.5 6 8c0 1.5.4 2.9 1 4l.5 6c.2 1.1 1.1 2 2.3 2h4.4c1.2 0 2.1-.9 2.3-2l.5-6c.6-1.1 1-2.5 1-4 0-3.5-2.5-6-6-6z',
    map:        'M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z M12 13a3 3 0 100-6 3 3 0 000 6z',
    shield:     'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z',
    wallet:     'M21 7H3a2 2 0 00-2 2v10a2 2 0 002 2h18a2 2 0 002-2V9a2 2 0 00-2-2zM1 7l11-5 11 5 M16 13a1 1 0 100-2 1 1 0 000 2z',
    dollar:     'M12 1v22 M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6',
    search:     'M11 19a8 8 0 100-16 8 8 0 000 16z M21 21l-4.35-4.35',
    chevron:    'M9 18l6-6-6-6',
    check:      'M20 6L9 17l-5-5',
    clock:      'M12 22a10 10 0 100-20 10 10 0 000 20z M12 6v6l4 2',
    alert:      'M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z M12 9v4 M12 17h.01',
    star:       'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z',
    refresh:    'M23 4v6h-6 M1 20v-6h6 M3.51 9a9 9 0 0114.85-3.36L23 10 M1 14l4.64 4.36A9 9 0 0020.49 15',
    home:       'M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z M9 22V12h6v10',
    user:       'M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2 M12 11a4 4 0 100-8 4 4 0 000 8z',
    arrowRight: 'M5 12h14 M12 5l7 7-7 7',
    x:          'M18 6L6 18 M6 6l12 12',
    phone:      'M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07A19.5 19.5 0 013.07 9.81 19.79 19.79 0 01.15 1.18 2 2 0 012.13 0h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L6.91 7.91a16 16 0 006.16 6.16l1.27-.45a2 2 0 012.11.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z',
  };
  return React.createElement('svg', {
    width: size, height: size, viewBox: '0 0 24 24',
    fill: 'none', stroke: color, strokeWidth: 2,
    strokeLinecap: 'round', strokeLinejoin: 'round', style,
  },
    React.createElement('path', { d: icons[name] || '' })
  );
};

// ─── Colors ───────────────────────────────────────────────────────────────────
const C = { navy: '#1B3557', mint: '#52C4A0', cream: '#FAF9F7', slate: '#64748B', light: '#E2E8F0', red: '#EF4444', amber: '#F59E0B' };

// ─── Step data for new-user wizard ────────────────────────────────────────────
const ONBOARDING_STEPS = [
  {
    id: 'concern',
    title: "What's on your mind?",
    subtitle: 'Select everything that applies — we\'ll tailor your experience.',
    type: 'multiselect',
    options: [
      { id: 'pain',       label: 'Tooth pain or sensitivity',    icon: 'alert'   },
      { id: 'checkup',    label: 'Routine checkup / cleaning',   icon: 'check'   },
      { id: 'cost',       label: 'Understanding dental costs',   icon: 'dollar'  },
      { id: 'cosmetic',   label: 'Cosmetic / smile improvement', icon: 'star'    },
      { id: 'insurance',  label: 'Using my dental insurance',    icon: 'shield'  },
      { id: 'anxiety',    label: 'Dental anxiety',               icon: 'user'    },
      { id: 'children',   label: 'Pediatric / family dentistry', icon: 'home'    },
      { id: 'emergency',  label: 'Dental emergency',             icon: 'phone'   },
    ],
  },
  {
    id: 'location',
    title: 'Where are you located?',
    subtitle: 'We\'ll show you verified dentists nearby and local cost estimates.',
    type: 'zip',
  },
  {
    id: 'insurance',
    title: 'Do you have dental insurance?',
    subtitle: 'Helps us show you accurate cost estimates and in-network options.',
    type: 'insurance',
    options: [
      { id: 'delta_dental', label: 'Delta Dental'  },
      { id: 'cigna',        label: 'Cigna'         },
      { id: 'aetna',        label: 'Aetna'         },
      { id: 'metlife',      label: 'MetLife'        },
      { id: 'guardian',     label: 'Guardian'       },
      { id: 'humana',       label: 'Humana'         },
      { id: 'other',        label: 'Other'          },
      { id: 'none',         label: 'No insurance'   },
    ],
  },
];

// ─── QUICK ACTION TILES ───────────────────────────────────────────────────────
const QUICK_ACTIONS = {
  pain:      [
    { label: 'Assess my pain',      route: '#triage',         icon: 'tooth',    color: C.red   },
    { label: 'Find emergency care', route: '#emergency',      icon: 'phone',    color: C.amber },
    { label: 'Get a cost estimate', route: '#cost-estimate',  icon: 'dollar',   color: C.navy  },
    { label: 'Get second opinion',  route: '#second-opinion', icon: 'shield',   color: C.mint  },
  ],
  checkup:   [
    { label: 'Find a dentist',       route: '#directory',      icon: 'search',  color: C.navy  },
    { label: 'Cost estimate',        route: '#cost-estimate',  icon: 'dollar',  color: C.mint  },
    { label: 'Dental wallet',        route: '#wallet',         icon: 'wallet',  color: C.navy  },
    { label: 'Education library',    route: '#education',      icon: 'home',    color: C.slate },
  ],
  cost:      [
    { label: 'Get an estimate',      route: '#cost-estimate',  icon: 'dollar',  color: C.mint  },
    { label: 'Check my benefits',    route: '#wallet',         icon: 'shield',  color: C.navy  },
    { label: 'Second opinion',       route: '#second-opinion', icon: 'check',   color: C.navy  },
    { label: 'Find affordable care', route: '#directory',      icon: 'search',  color: C.slate },
  ],
  default:   [
    { label: 'Symptom check',        route: '#triage',         icon: 'tooth',   color: C.navy  },
    { label: 'Find a dentist',       route: '#directory',      icon: 'search',  color: C.mint  },
    { label: 'Cost estimate',        route: '#cost-estimate',  icon: 'dollar',  color: C.navy  },
    { label: 'My records',           route: '#wallet',         icon: 'wallet',  color: C.slate },
  ],
};

// ─── Main component ────────────────────────────────────────────────────────────
function PatientPortal() {
  const { journey, loading } = typeof useUserJourney !== 'undefined'
    ? useUserJourney()
    : { journey: null, loading: false };

  const [localJourney] = useState(() => {
    // Fallback if JourneyProvider not wrapping
    if (journey) return null;
    const role = localStorage.getItem('td_role');
    const visitCount = parseInt(localStorage.getItem('td_visit_count') || '0', 10);
    const patientCtx = (() => { try { return JSON.parse(localStorage.getItem('td_patient_ctx') || '{}'); } catch { return {}; } })();
    return { isNew: visitCount <= 1 || !role, patientCtx, role: role || 'patient', visitCount };
  });

  const ctx = journey || localJourney || {};
  const { isNew, patientCtx = {}, role } = ctx;

  if (loading) return React.createElement(LoadingScreen);
  if (isNew || !role) return React.createElement(NewPatientWizard, { onComplete: () => window.location.reload() });
  return React.createElement(ReturningPatientDashboard, { ctx });
}

// ─── Loading screen ────────────────────────────────────────────────────────────
function LoadingScreen() {
  return React.createElement('div', {
    className: 'portal-screen',
    style: { minHeight: '60vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }
  },
    React.createElement('div', { style: { textAlign: 'center' } },
      React.createElement('div', { className: 'skeleton', style: { width: 40, height: 40, borderRadius: '50%', margin: '0 auto 16px' } }),
      React.createElement('p', { className: 'section-subtitle' }, 'Loading your experience…'),
    )
  );
}

// ─── NEW PATIENT WIZARD ────────────────────────────────────────────────────────
function NewPatientWizard({ onComplete }) {
  const [step, setStep] = useState(0);
  const [answers, setAnswers] = useState({ concern: [], zip: '', insurance: '' });
  const [zipInput, setZipInput] = useState('');
  const [transitioning, setTransitioning] = useState(false);

  const current = ONBOARDING_STEPS[step];
  const progress = ((step) / ONBOARDING_STEPS.length) * 100;

  const advance = async () => {
    setTransitioning(true);
    await new Promise(r => setTimeout(r, 180));
    if (step < ONBOARDING_STEPS.length - 1) {
      setStep(s => s + 1);
      setTransitioning(false);
    } else {
      // Save context
      const ctx = { concerns: answers.concern, zip: answers.zip, insuranceCarrier: answers.insurance, onboardedAt: new Date().toISOString() };
      localStorage.setItem('td_patient_ctx', JSON.stringify(ctx));
      localStorage.setItem('td_role', 'patient');
      if (typeof trackEvent !== 'undefined') trackEvent('patient_onboarding_complete', ctx);
      onComplete();
    }
  };

  const canAdvance = () => {
    if (current.type === 'multiselect') return answers.concern.length > 0;
    if (current.type === 'zip') return answers.zip.length === 5;
    if (current.type === 'insurance') return !!answers.insurance;
    return true;
  };

  const toggle = (id) => {
    setAnswers(prev => ({
      ...prev,
      concern: prev.concern.includes(id) ? prev.concern.filter(x => x !== id) : [...prev.concern, id],
    }));
  };

  return React.createElement('div', {
    className: 'portal-screen animate-fade-in-up',
    style: {
      minHeight: '100vh',
      display: 'flex', flexDirection: 'column', alignItems: 'center',
      justifyContent: 'center', padding: '24px 16px',
    }
  },
    // Header + step indicator
    React.createElement('div', { style: { width: '100%', maxWidth: 560, marginBottom: 24 } },
      React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 } },
        React.createElement('span', { style: { fontSize: 13, fontWeight: 700, color: 'var(--color-accent)', letterSpacing: 1 } }, 'THEDENTIST.AI'),
        React.createElement('span', { className: 'section-subtitle' }, `${step + 1} of ${ONBOARDING_STEPS.length}`),
      ),
      React.createElement('div', { className: 'step-indicator' },
        ONBOARDING_STEPS.map((s, i) => (
          React.createElement(React.Fragment, { key: s.id },
            React.createElement('div', {
              className: `step-dot ${i < step ? 'completed' : i === step ? 'active' : 'pending'}`,
            }, i < step
              ? (window.FlatIcon
                ? React.createElement(window.FlatIcon, { name: 'check', size: 12, color: 'var(--paper)' })
                : null)
              : i + 1),
            i < ONBOARDING_STEPS.length - 1 && React.createElement('div', { className: 'step-connector' }),
          )
        ))
      ),
      React.createElement('div', { className: 'progress-bar', style: { marginTop: 8 } },
        React.createElement('div', {
          className: 'progress-fill',
          style: { width: `${progress + (100 / ONBOARDING_STEPS.length)}%` }
        })
      ),
    ),

    // Card
    React.createElement('div', {
      className: 'card card-raised',
      style: {
        maxWidth: 560, width: '100%',
        opacity: transitioning ? 0 : 1, transform: transitioning ? 'translateY(8px)' : 'none',
        transition: 'all 0.18s ease',
      }
    },
      React.createElement('div', { className: 'disclaimer-banner', style: { marginBottom: 16 } },
        'Information only — not diagnosis. A licensed dentist must confirm.'
      ),
      React.createElement('h2', { className: 'section-title', style: { marginBottom: 8 } }, current.title),
      React.createElement('p', { className: 'section-subtitle', style: { marginBottom: 28 } }, current.subtitle),

      // Step content
      current.type === 'multiselect' && React.createElement('div', { className: 'concern-grid' },
        current.options.map(opt =>
          React.createElement('button', {
            key: opt.id,
            type: 'button',
            onClick: () => toggle(opt.id),
            className: `concern-card${answers.concern.includes(opt.id) ? ' selected' : ''}`,
          },
            React.createElement(Icon, { name: opt.icon, size: 16, color: answers.concern.includes(opt.id) ? 'var(--color-accent)' : 'var(--color-text-tertiary)' }),
            React.createElement('span', null, opt.label),
          )
        )
      ),

      current.type === 'zip' && React.createElement('div', null,
        React.createElement('input', {
          type: 'text', inputMode: 'numeric', maxLength: 5,
          placeholder: 'Enter ZIP code',
          className: 'input',
          value: zipInput,
          onChange: e => {
            const v = e.target.value.replace(/\D/g, '');
            setZipInput(v);
            setAnswers(prev => ({ ...prev, zip: v }));
          },
          style: { fontSize: 18, fontWeight: 600, letterSpacing: 4 }
        }),
        React.createElement('p', { className: 'section-subtitle', style: { marginTop: 10 } }, 'Your ZIP is never shared. Used only to find nearby dentists and show local pricing.'),
        React.createElement('button', {
          type: 'button',
          className: 'btn btn-ghost btn-sm',
          style: { marginTop: 8, paddingLeft: 0 },
          onClick: () => { setAnswers(prev => ({ ...prev, zip: 'skip' })); }
        }, "Skip — I'll add this later"),
      ),

      current.type === 'insurance' && React.createElement('div', { className: 'concern-grid' },
        current.options.map(opt =>
          React.createElement('button', {
            key: opt.id,
            type: 'button',
            onClick: () => setAnswers(prev => ({ ...prev, insurance: opt.id })),
            className: `concern-card${answers.insurance === opt.id ? ' selected' : ''}`,
            style: { justifyContent: 'center' },
          }, opt.label)
        )
      ),

      // CTA
      React.createElement('button', {
        type: 'button',
        onClick: canAdvance() ? advance : null,
        disabled: !canAdvance() && current.type !== 'zip',
        className: `btn btn-primary btn-block${canAdvance() ? '' : ''}`,
        style: { marginTop: 28, opacity: canAdvance() ? 1 : 0.5, cursor: canAdvance() ? 'pointer' : 'default' },
      },
        step === ONBOARDING_STEPS.length - 1 ? 'Take me to my dashboard' : 'Continue',
        React.createElement(Icon, { name: 'arrowRight', size: 16, color: canAdvance() ? 'white' : 'var(--color-text-tertiary)' }),
      ),
    ),
  );
}

// ─── RETURNING PATIENT DASHBOARD ───────────────────────────────────────────────
function ReturningPatientDashboard({ ctx }) {
  const { patientCtx = {}, visitCount, daysSinceLastVisit, onboarding } = ctx;
  const { concerns = [], zip, insuranceCarrier, savedDentistNpi, lastCondition } = patientCtx;

  const greeting = typeof getReturnGreeting !== 'undefined' ? getReturnGreeting(ctx) : 'Welcome back.';
  const primaryConcern = concerns[0] || 'default';
  const tiles = QUICK_ACTIONS[primaryConcern] || QUICK_ACTIONS.default;

  const [activeSection, setActiveSection] = useState('dashboard');

  return React.createElement('div', { className: 'portal-screen animate-fade-in-up', style: { minHeight: '100vh' } },

    // Top nav
    React.createElement(PatientNav, { activeSection, onNavigate: setActiveSection, patientCtx }),

    // Hero strip
    React.createElement('div', { className: 'landing-modern-hero', style: { margin: '0 var(--space-4)', marginTop: 'var(--space-4)' } },
      React.createElement('div', { style: { maxWidth: 760, margin: '0 auto' } },
        React.createElement('p', { className: 'badge badge-blue', style: { marginBottom: 8, display: 'inline-flex' } }, greeting),
        React.createElement('h1', { className: 'landing-modern-headline', style: { fontSize: 'clamp(1.25rem, 4vw, 1.75rem)' } },
          lastCondition ? `Still tracking: ${lastCondition}` : 'Your dental health, personalized.'
        ),
        zip && React.createElement('p', { className: 'section-subtitle' }, `${zip} · ${insuranceCarrier ? insuranceCarrier.replace('_', ' ') : 'No insurance on file'}`),
      )
    ),

    // Main content
    React.createElement('div', { style: { maxWidth: 760, margin: '0 auto', padding: '0 24px 80px' } },

      React.createElement('div', { className: 'disclaimer-banner', style: { marginTop: 24 } },
        'Information only — not diagnosis. Confirm with a licensed dentist. ',
        React.createElement('a', { href: '/methodology/', className: 'methodology-link' }, 'How we measure')
      ),

      // Quick action tiles
      React.createElement('div', { style: { marginBottom: 32, marginTop: 24 } },
        React.createElement('h2', { className: 'section-title', style: { fontSize: '1rem', marginBottom: 16 } },
          concerns.includes('pain') ? 'Quick actions for you' : 'What would you like to do?'
        ),
        React.createElement('div', { className: 'grid-2', style: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12 } },
          tiles.map((tile, i) =>
            React.createElement('a', {
              key: i, href: tile.route,
              className: 'card',
              style: {
                display: 'flex', alignItems: 'center', gap: 14,
                textDecoration: 'none', padding: '18px 20px',
                borderLeft: `4px solid ${tile.color}`,
              },
            },
              React.createElement('div', {
                style: { width: 36, height: 36, borderRadius: 10, background: `${tile.color}15`, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }
              }, React.createElement(Icon, { name: tile.icon, size: 18, color: tile.color })),
              React.createElement('span', { style: { fontSize: 14, fontWeight: 600, color: 'var(--color-text-primary)' } }, tile.label),
              React.createElement(Icon, { name: 'chevron', size: 14, color: 'var(--color-text-tertiary)', style: { marginLeft: 'auto' } }),
            )
          )
        ),
      ),

      // Smart contextual cards
      React.createElement(ContextualCards, { patientCtx, visitCount, daysSinceLastVisit }),

      // Dental Coach CTA (if not enrolled)
      !patientCtx.coachEnrolled && React.createElement('div', {
        className: 'card',
        style: {
          background: 'linear-gradient(135deg, #111827 0%, #1A56DB 100%)',
          marginTop: 24, color: 'white',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 20,
          border: 'none',
        }
      },
        React.createElement('div', null,
          React.createElement('div', { className: 'badge badge-green', style: { marginBottom: 6 } }, 'Free · Dental Coach'),
          React.createElement('h3', { style: { margin: '0 0 6px', fontSize: 17, fontWeight: 700, color: 'white' } }, 'Get your personalized dental plan'),
          React.createElement('p', { style: { margin: 0, fontSize: 13, opacity: 0.85 } }, 'Weekly SMS tips based on your concerns. Free, cancel anytime.'),
        ),
        React.createElement('a', {
          href: '#coach',
          className: 'btn btn-primary btn-sm',
          style: { flexShrink: 0, textDecoration: 'none' }
        }, 'Enroll free'),
      ),
    ),
  );
}

// ─── Patient nav ───────────────────────────────────────────────────────────────
function PatientNav({ activeSection, onNavigate, patientCtx }) {
  const items = [
    { id: 'dashboard',     label: 'Home',       icon: 'home'   },
    { id: 'find',          label: 'Find',        icon: 'search' },
    { id: 'wallet',        label: 'Records',     icon: 'wallet' },
    { id: 'second-opinion',label: 'Opinion',     icon: 'shield' },
  ];
  return React.createElement('nav', {
    style: {
      background: 'var(--color-surface)', borderBottom: '1px solid var(--color-border)',
      padding: '0 24px', display: 'flex', alignItems: 'center',
      justifyContent: 'space-between', position: 'sticky', top: 0, zIndex: 100,
    }
  },
    React.createElement('span', { style: { fontSize: 14, fontWeight: 800, color: 'var(--color-text-primary)', letterSpacing: -0.5 } }, 'TheDentist.ai'),
    React.createElement('div', { style: { display: 'flex', gap: 4 } },
      items.map(item =>
        React.createElement('a', {
          key: item.id, href: `#${item.id}`,
          className: `nav-tab${activeSection === item.id ? ' active' : ''}`,
          style: {
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
            padding: '8px 10px', textDecoration: 'none', fontSize: 10,
          }
        },
          React.createElement(Icon, { name: item.icon, size: 18, color: activeSection === item.id ? 'var(--color-accent)' : 'var(--color-text-tertiary)' }),
          item.label,
        )
      )
    ),
  );
}

// ─── Contextual cards (smart suggestions) ─────────────────────────────────────
function ContextualCards({ patientCtx, visitCount, daysSinceLastVisit }) {
  const cards = [];
  const { concerns = [], lastCondition, savedDentistNpi, zip } = patientCtx;

  // Emergency detection
  if (concerns.includes('pain') || concerns.includes('emergency')) {
    cards.push({
      priority: 'urgent',
      title: 'Pain needs attention',
      body: 'If you\'re experiencing severe pain, swelling, or bleeding — get evaluated today.',
      cta: 'Find emergency care', route: '#emergency',
      color: C.red, icon: 'alert',
    });
  }

  // Long gap between visits
  if (daysSinceLastVisit > 180) {
    cards.push({
      priority: 'medium',
      title: 'It\'s been a while',
      body: 'Most dentists recommend a checkup every 6 months. We can help you find one nearby.',
      cta: `Find a dentist near ${zip || 'you'}`, route: '#directory',
      color: C.amber, icon: 'clock',
    });
  }

  // Returning user — saved dentist context
  if (savedDentistNpi) {
    cards.push({
      priority: 'low',
      title: 'Book with your dentist',
      body: 'You saved a dentist last time. Book your next appointment directly.',
      cta: 'View your dentist', route: `#dentist/${savedDentistNpi}`,
      color: C.mint, icon: 'star',
    });
  }

  // Wallet prompt (after 2nd visit)
  if (visitCount >= 2 && !patientCtx.walletCreated) {
    cards.push({
      priority: 'low',
      title: 'Store your dental records',
      body: 'Dental Wallet keeps your x-rays, EOBs, and treatment history in one secure place.',
      cta: 'Set up my wallet', route: '#wallet',
      color: C.navy, icon: 'wallet',
    });
  }

  if (!cards.length) return null;

  return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
    React.createElement('h2', { className: 'section-title', style: { fontSize: '1rem', marginBottom: 4 } }, 'For you'),
    cards.slice(0, 3).map((card, i) =>
      React.createElement('div', {
        key: i,
        className: card.priority === 'urgent' ? 'emergency-banner' : 'card',
        style: card.priority !== 'urgent' ? {
          display: 'flex', alignItems: 'flex-start', gap: 16,
          borderLeft: `4px solid ${card.color}`,
        } : { display: 'flex', alignItems: 'flex-start', gap: 16 },
      },
        React.createElement('div', {
          style: { width: 36, height: 36, borderRadius: 10, background: `${card.color}15`, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, marginTop: 2 }
        }, React.createElement(Icon, { name: card.icon, size: 18, color: card.color })),
        React.createElement('div', { style: { flex: 1 } },
          React.createElement('h3', { style: { margin: '0 0 4px', fontSize: 14, fontWeight: 700, color: 'var(--color-text-primary)' } }, card.title),
          React.createElement('p', { className: 'section-subtitle', style: { margin: '0 0 10px', fontSize: 13 } }, card.body),
          React.createElement('a', {
            href: card.route,
            className: 'methodology-link',
            style: { color: card.color }
          }, card.cta + ' →'),
        ),
      )
    )
  );
}

// Expose
window.PatientPortal = PatientPortal;
window.NewPatientWizard = NewPatientWizard;
window.ReturningPatientDashboard = ReturningPatientDashboard;
