// "SCN2A — what families need to know" — plain-English explainer for families,
// plus the "A lifelong journey" timeline and the full "Will's story" page.
//
// Recreated from the Claude Design handoff (originally a teal/Inter prototype) in
// the live site's Neural Ink v2.1 brand: navy anchor surfaces, warm-white canvas,
// Plus Jakarta Sans, mulberry used sparingly. Content/copy is locked per the
// handoff brief — do not edit the wording without clinician sign-off.

// ---- Neural Ink palette (mirrors lib/neural-ink.css for inline styling) ----
const NK = {
  navy: '#1E3A6E', navyHover: '#16305C', ink: '#0D1B2A', canvas: '#F7F4F0',
  sand: '#E8E3DA', stone: '#B8B2A8', muted: '#6B6659', divider: '#D5CFBF',
  mulberry: '#8E3B5E', mulberryHover: '#76304D', white: '#FFFFFF',
};

// ============================================================
// Content — locked copy
// ============================================================
const FAM_DOORS = [
  {
    n: '01',
    eyebrow: 'Understanding the condition',
    title: 'What SCN2A is, and what it can mean for your child',
    cards: [
      {
        id: 'who-else',
        title: 'Who else?',
        sub: 'Other Australian children and adults living with SCN2A.',
        body: [
          'SCN2A is one of the more common genes linked to seizures that start very early in life. It is also one of the top genes linked to autism.',
          'You are not alone. Children with SCN2A live all around Australia and around the world.',
        ],
      },
      {
        id: 'connected-conditions',
        title: 'Connected conditions',
        sub: 'What often goes with SCN2A.',
        body: [
          'A child with an SCN2A change may have one or more of: seizures (sometimes starting in the first weeks of life), slower learning, autism, shaky or wobbly movements, or pain that comes and goes.',
          'Not every child has all of these. Some children have only mild signs.',
        ],
      },
      {
        id: 'body-brain',
        title: 'Body, brain and growing',
        sub: 'How SCN2A can affect the brain.',
        body: [
          'The SCN2A gene makes a tiny part inside brain cells called a "sodium channel." This part helps brain cells send messages.',
          { kind: 'pair', items: [
            { label: '"Too much" changes', plain: 'the channel works too hard.', detail: 'These often cause seizures in the first three months of life. Doctors call these gain-of-function.' },
            { label: '"Too little" changes', plain: 'the channel does not work enough.', detail: 'These often cause seizures that start later, or autism and learning differences without early seizures. Doctors call these loss-of-function.' },
          ]},
          'Knowing which type your child has helps the doctor choose the right medicine.',
        ],
      },
      {
        id: 'unclear-test',
        title: "If the test wasn't clear",
        sub: 'What to do if your gene result is uncertain.',
        body: [
          'Sometimes a gene test finds a change in SCN2A, but the lab is not sure if it is the cause. The report may say "variant of uncertain significance."',
          'If this happens, ask your neurologist or genetic doctor:',
          { kind: 'list', items: [
            'Can my child’s gene change be sent for extra lab testing to see how it works?',
            'Can we be referred to Australian Genomics or a research team that does this?',
          ]},
          'This extra testing can sometimes show whether the change is "too much" or "too little." That helps with picking medicine.',
        ],
      },
    ],
  },
  {
    n: '02',
    eyebrow: 'Day to day and treatment',
    title: 'Choices, rhythms and the people around you',
    cards: [
      {
        id: 'treatments',
        title: 'Treatments that match',
        sub: 'Why the type of SCN2A change matters.',
        body: [
          'Knowing the type of SCN2A change helps doctors pick seizure medicines.',
          { kind: 'list', items: [
            'For "too much" changes, medicines called sodium channel blockers (like phenytoin, carbamazepine, oxcarbazepine, or lacosamide) often help.',
            'For "too little" changes, those same medicines can sometimes make seizures worse. Doctors usually try other medicines.',
          ]},
          { kind: 'note', text: 'Always talk to your child’s doctor before starting or stopping any medicine.' },
        ],
      },
      {
        id: 'as-life-unfolds',
        title: 'As life unfolds',
        sub: 'What growing up with SCN2A can look like.',
        body: [
          'Children with SCN2A grow up in different ways. Some have very hard early years and then settle. Others learn at their own pace over many years.',
          'Some adults with SCN2A live mostly independent lives. Others need lifelong support.',
          'There is no single path. Your team can help you plan for the next stage.',
        ],
      },
      {
        id: 'carers',
        title: 'Carers, together',
        sub: 'Looking after yourself, too.',
        body: [
          'Looking after a child with SCN2A is hard work. You also need support.',
          { kind: 'links', items: [
            { name: 'Carer Gateway', desc: 'A free national service for carers.', href: 'https://www.carergateway.gov.au/' },
            { name: 'Carers Australia', desc: 'State-based help.', href: 'https://www.carersaustralia.com.au/' },
            { name: 'Rare Voices Australia', desc: 'Peer-support project for rare-disease carers (running until December 2026).', href: 'https://rarevoices.org.au/' },
            { name: 'Epilepsy Action Australia', desc: 'Carer education and a nurse helpline.', href: 'https://www.epilepsy.org.au/' },
          ]},
          { kind: 'note', text: 'It is okay to ask for help. It is okay to rest.' },
        ],
      },
    ],
  },
  {
    n: '03',
    eyebrow: "Research and what's coming",
    title: 'What science can do today, and what is on the horizon',
    cards: [
      {
        id: 'whats-new',
        title: "What's new",
        sub: 'Where science is up to with SCN2A.',
        body: [
          'Scientists are learning more every year. They have grown brain cells in the lab from people with SCN2A.',
          'These cells help test which medicines work for which type of SCN2A change.',
        ],
      },
      {
        id: 'trials',
        title: 'Clinical trials',
        sub: 'Trials in Australia and overseas.',
        body: [
          'A new medicine called elsunersen is being tested for the "too much" type of SCN2A. Early results in one very sick baby were promising — seizures dropped by more than half, and the baby tolerated the treatment well.',
          'More children need to be tested before we know how well it works.',
          { kind: 'links', items: [
            { name: 'Australian New Zealand Clinical Trials Registry', desc: 'For trials in Australia.', href: 'https://www.anzctr.org.au/' },
            { name: 'ClinicalTrials.gov', desc: 'For trials around the world.', href: 'https://clinicaltrials.gov/' },
          ]},
          { kind: 'note', text: 'Always talk to your child’s doctor before joining a clinical trial.' },
        ],
      },
      {
        id: 'staying-in-loop',
        title: 'Staying in the loop',
        sub: 'How to keep up without being overwhelmed.',
        body: [
          'You can stay in the loop through this site, the Rare Voices Australia RARE Portal, Epilepsy Action Australia updates, and by asking your team to tell you when something new comes out.',
          'You do not have to read every paper. Your team can help you understand what matters for your child.',
        ],
      },
      {
        id: 'newer-treatments',
        title: 'Newer treatments',
        sub: 'New medicines and gene therapies on the horizon.',
        body: [
          'For the "too little" type of SCN2A, scientists are testing new tools that could turn the working copy of the gene up.',
          'This work is still in the lab, not in children yet. It is exciting, but it will take time.',
        ],
      },
    ],
  },
  {
    n: '04',
    eyebrow: 'Family stories',
    title: 'Real Australian families, in their own words',
    featured: {
      name: "Will's story",
      kicker: 'Featured family story',
      photo: 'assets/photography/will-and-kris.jpeg',
      photoAlt: 'Will and his mum Kris, holding each other close and smiling.',
      teaser: [
        'Will is twenty-four. He lives with an SCN2A-related developmental and epileptic encephalopathy, very limited words, and a family who learned a different language of connection — a look, a sound, a moment of calm.',
        'His diagnosis came at fourteen, after years without a name. What began as our family searching for answers became part of the science now building a different future for the children diagnosed next.',
      ],
      byline: 'From Kris Pierce and Dr David Cunnington',
      cta: "Read Will's story",
      to: 'wills-story',
    },
    cards: [
      {
        id: 'share-story',
        wide: true,
        title: 'Share your story',
        sub: 'Every family’s story adds to the picture.',
        body: [
          'Stories from Australian families living with SCN2A are powerful. They remind us that no one is alone in this.',
          'We share stories with families’ permission. If you would like to share your story, please get in touch.',
        ],
      },
    ],
  },
  {
    n: '05',
    eyebrow: 'Looking ahead',
    title: 'What we know — and what we are still learning',
    cards: [
      {
        id: 'across-lifetime',
        title: 'Across a lifetime',
        sub: 'How SCN2A can look at different ages.',
        body: [
          'We are still learning about how SCN2A affects people as they grow into adults.',
          'A 2025 international study (with Australian doctors involved) is the most complete picture we have so far. It shows that life with SCN2A looks different for different people.',
        ],
      },
      {
        id: 'life-expectancy',
        title: 'Looking ahead — life expectancy',
        sub: "What we know — and don't know — about life expectancy.",
        body: [
          'We do not yet have good long-term data on life expectancy for SCN2A.',
          'The risk is highest for babies and children with very hard-to-control seizures. Many children with milder forms grow up and live long lives.',
          { kind: 'note', text: 'Your doctor is the best person to talk to about your child.' },
        ],
      },
    ],
  },
];

const FAM_PAPERS = [
  { name: 'Wolff et al., Brain 2017', href: 'https://pubmed.ncbi.nlm.nih.gov/28379373/' },
  { name: 'Sanders et al., Trends Neurosci. 2018', href: 'https://pubmed.ncbi.nlm.nih.gov/29691040/' },
  { name: 'Hedrich, Lauxmann & Lerche, Epilepsia 2019', href: 'https://pubmed.ncbi.nlm.nih.gov/31904120/' },
  { name: 'Wolff, Brunklaus & Zuberi, Epilepsia 2019', href: 'https://pubmed.ncbi.nlm.nih.gov/31904126/' },
  { name: 'Reynolds, King & Gorman, Eur J Paediatr Neurol. 2020', href: 'https://pubmed.ncbi.nlm.nih.gov/31924505/' },
  { name: 'Brunklaus et al., Epilepsia 2020', href: 'https://pubmed.ncbi.nlm.nih.gov/32090326/' },
  { name: 'Spratt et al., Cell Rep. 2021', href: 'https://pubmed.ncbi.nlm.nih.gov/34348157/' },
  { name: 'Que et al., J Neurosci. 2021', href: 'https://pubmed.ncbi.nlm.nih.gov/34716231/' },
  { name: 'Thompson et al., J Gen Physiol. 2023', href: 'https://pubmed.ncbi.nlm.nih.gov/37578743/' },
  { name: 'Wagner et al., Nat Med. 2025', href: 'https://pubmed.ncbi.nlm.nih.gov/40263630/' },
  { name: 'Goad et al., Neurology 2025', href: 'https://pubmed.ncbi.nlm.nih.gov/40694750/' },
  { name: 'Tamura et al., Nature 2025', href: 'https://pubmed.ncbi.nlm.nih.gov/40963013/' },
  { name: 'Foster et al., Pediatr Neurol. 2017', href: 'https://pubmed.ncbi.nlm.nih.gov/27867041/' },
];

const FAM_ORGS = [
  { name: 'Rare Voices Australia', href: 'https://rarevoices.org.au/' },
  { name: 'Genetic Support Network of Victoria', href: 'https://www.gsnv.org.au/' },
  { name: 'Epilepsy Action Australia', href: 'https://www.epilepsy.org.au/' },
  { name: 'Australian Genomics', href: 'https://www.australiangenomics.org.au/' },
  { name: 'NDIS', href: 'https://www.ndis.gov.au/' },
  { name: 'Carer Gateway', href: 'https://www.carergateway.gov.au/' },
  { name: 'ANZCTR', href: 'https://www.anzctr.org.au/' },
];

// ============================================================
// Page header band — eyebrow, H1, tagline, disclaimer, dates, print
// ============================================================
function FamiliesHeaderBand() {
  return (
    <section style={{ background: NK.navy, color: '#fff', position: 'relative', overflow: 'hidden' }}>
      <NetworkMotif opacity={0.16} stroke="#fff" dense />
      <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 6, background: NK.mulberry, zIndex: 2 }} />
      <div className="container" style={{ position: 'relative', zIndex: 2, padding: '64px 32px 56px' }}>
        <div className="eyebrow" style={{ color: '#D8C2CD', marginBottom: 16 }}>For families</div>
        <h1 className="hero-h1-mobile-lg" style={{
          fontSize: 'clamp(34px, 4.6vw, 56px)', fontWeight: 800, lineHeight: 1.06,
          letterSpacing: '-0.02em', color: '#fff', margin: 0, maxWidth: 920, textWrap: 'pretty',
        }}>
          SCN2A — what families need to know
        </h1>
        <p className="hero-sub-mobile" style={{ fontSize: 20, lineHeight: 1.55, marginTop: 22, maxWidth: 720, color: 'rgba(255,255,255,0.92)' }}>
          Reliable information, in plain words — written for parents and carers,
          reviewed by clinicians, grounded in the latest evidence.
        </p>

        {/* Disclaimer pill */}
        <div style={{
          display: 'inline-flex', alignItems: 'flex-start', gap: 10, marginTop: 26,
          background: 'rgba(255,255,255,0.10)', color: '#fff',
          padding: '12px 16px', borderRadius: 5,
          borderLeft: `3px solid ${NK.mulberry}`, maxWidth: 640,
          fontSize: 14.5, fontWeight: 500, lineHeight: 1.5,
        }}>
          <i data-lucide="info" style={{ width: 18, height: 18, flexShrink: 0, marginTop: 1 }} />
          Information only — not medical advice. Please talk to your clinical team.
        </div>

        {/* Meta line + print */}
        <div className="families-meta" style={{
          display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 24, marginTop: 30,
          paddingTop: 22, borderTop: '1px dashed rgba(255,255,255,0.35)',
        }}>
          <div className="ledger-mono" style={{ fontSize: 12, color: 'rgba(255,255,255,0.8)', letterSpacing: '0.06em', display: 'flex', alignItems: 'center', gap: 8 }}>
            <i data-lucide="calendar-check-2" style={{ width: 14, height: 14 }} />
            LAST REVIEWED 29 MAY 2026
          </div>
          <div className="ledger-mono" style={{ fontSize: 12, color: 'rgba(255,255,255,0.8)', letterSpacing: '0.06em', display: 'flex', alignItems: 'center', gap: 8 }}>
            <i data-lucide="calendar-clock" style={{ width: 14, height: 14 }} />
            NEXT REVIEW 29 MAY 2027
          </div>
          <div className="print-btn" style={{ marginLeft: 'auto' }}>
            <Button variant="outlineLight" icon="printer" onClick={() => window.print()}>Print or save as PDF</Button>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// Sticky "On this page" door nav
// ============================================================
function DoorNavStrip({ items, activeSection, onJump, top }) {
  return (
    <div className="door-nav-strip hide-mobile" style={{
      position: 'sticky', top, zIndex: 20,
      background: '#fff', borderBottom: `1px solid ${NK.divider}`,
    }}>
      <div className="container" style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '10px 32px', overflowX: 'auto' }}>
        <div className="eyebrow" style={{ color: NK.muted, marginRight: 12, flexShrink: 0 }}>On this page</div>
        {items.map((it) => {
          const on = activeSection === it.id;
          return (
            <button key={it.id} onClick={() => onJump(it.id)} style={{
              background: on ? NK.navy : 'transparent',
              color: on ? '#fff' : NK.ink,
              border: `1px solid ${on ? NK.navy : NK.divider}`,
              borderRadius: 5, padding: '8px 12px',
              fontFamily: 'inherit', fontSize: 13, fontWeight: 600, cursor: 'pointer',
              flexShrink: 0, display: 'inline-flex', alignItems: 'center', gap: 8,
              transition: 'background 120ms, color 120ms, border-color 120ms',
            }}>
              {it.n && <span style={{ fontSize: 11, fontWeight: 700, color: on ? 'rgba(255,255,255,0.72)' : NK.navy, fontVariantNumeric: 'tabular-nums' }}>{it.n}</span>}
              <span>{it.label}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

// ============================================================
// "What is SCN2A?" — navy anchor explainer
// ============================================================
function FamHeroExplainer() {
  return (
    <section style={{ background: NK.navy, color: '#fff', position: 'relative', overflow: 'hidden' }}>
      <NetworkMotif opacity={0.14} stroke="#E8E3DA" />
      <div className="container" style={{ position: 'relative', padding: '64px 32px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '0.9fr 1.4fr', gap: 56, alignItems: 'start' }} className="stack-mobile">
          <div>
            <div className="eyebrow" style={{ color: '#D8C2CD', marginBottom: 14 }}>Start here</div>
            <h2 className="h2-mobile" style={{ fontSize: 'clamp(30px, 3.4vw, 44px)', margin: 0, lineHeight: 1.08, fontWeight: 800, letterSpacing: '-0.02em', color: '#fff' }}>
              What is&nbsp;SCN2A?
            </h2>
          </div>
          <div style={{ fontSize: 20, lineHeight: 1.6, color: 'rgba(255,255,255,0.94)' }}>
            <p style={{ margin: '0 0 18px', maxWidth: 'none' }}>
              SCN2A is a gene. Genes are instructions inside our cells.
              The SCN2A gene helps brain cells "talk" to each other.
            </p>
            <p style={{ margin: 0, maxWidth: 'none' }}>
              When SCN2A has a change in it, the brain may work differently.
              This can lead to seizures, slower learning, autism, or differences
              in how the body moves. <strong style={{ color: '#fff', fontWeight: 700 }}>Each child is different.</strong>
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// Expandable door card
// ============================================================
function CardBody({ body }) {
  return (
    <div style={{ fontSize: 16.5, lineHeight: 1.65, color: NK.ink, maxWidth: '68ch' }}>
      {body.map((b, i) => {
        if (typeof b === 'string') {
          return <p key={i} style={{ margin: i === 0 ? 0 : '14px 0 0', maxWidth: 'none' }}>{b}</p>;
        }
        if (b.kind === 'list') {
          return (
            <ul key={i} style={{ margin: '14px 0 0', paddingLeft: 22, display: 'flex', flexDirection: 'column', gap: 8 }}>
              {b.items.map((it, j) => <li key={j}>{it}</li>)}
            </ul>
          );
        }
        if (b.kind === 'pair') {
          return (
            <div key={i} className="stack-mobile" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, margin: '18px 0 0' }}>
              {b.items.map((p, j) => (
                <div key={j} style={{ background: NK.canvas, borderLeft: `3px solid ${NK.navy}`, borderRadius: 5, padding: '14px 16px' }}>
                  <div style={{ fontSize: 14, fontWeight: 700, color: NK.navy, marginBottom: 4 }}>{p.label}</div>
                  <div style={{ fontSize: 15, lineHeight: 1.55, color: NK.ink, marginBottom: 6 }}>{p.plain}</div>
                  <div style={{ fontSize: 13.5, lineHeight: 1.55, color: NK.muted }}>{p.detail}</div>
                </div>
              ))}
            </div>
          );
        }
        if (b.kind === 'links') {
          return (
            <ul key={i} style={{ listStyle: 'none', padding: 0, margin: '16px 0 0', display: 'flex', flexDirection: 'column', gap: 10 }}>
              {b.items.map((l, j) => (
                <li key={j} style={{ display: 'grid', gridTemplateColumns: '20px 1fr', gap: 12, paddingBottom: 10, borderBottom: `1px solid ${NK.canvas}` }}>
                  <i data-lucide="external-link" style={{ width: 16, height: 16, color: NK.navy, marginTop: 3 }} />
                  <div>
                    <a href={l.href} target="_blank" rel="noopener noreferrer" style={{ color: NK.ink, fontWeight: 700, textDecoration: 'none', fontSize: 15.5 }}>{l.name}</a>
                    <div style={{ fontSize: 14, color: NK.muted, marginTop: 2 }}>{l.desc}</div>
                  </div>
                </li>
              ))}
            </ul>
          );
        }
        if (b.kind === 'note') {
          return (
            <div key={i} style={{
              margin: '18px 0 0', background: NK.sand, borderLeft: `4px solid ${NK.mulberry}`, borderRadius: 5,
              padding: '14px 16px', fontSize: 15, fontWeight: 500, color: NK.ink,
              display: 'flex', alignItems: 'flex-start', gap: 12,
            }}>
              <i data-lucide="alert-triangle" style={{ width: 18, height: 18, marginTop: 2, flexShrink: 0, color: NK.mulberry }} />
              <div>{b.text}</div>
            </div>
          );
        }
        return null;
      })}
    </div>
  );
}

function ExpandableCard({ card, open, onToggle, wide }) {
  const contentRef = React.useRef(null);
  const [h, setH] = React.useState(0);
  React.useEffect(() => {
    if (contentRef.current) setH(contentRef.current.scrollHeight);
  }, [open, card]);

  const handleKey = (e) => {
    if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle(); }
  };

  return (
    <article style={{
      background: '#fff', border: `1px solid ${open ? NK.navy : NK.divider}`, borderRadius: 5,
      boxShadow: open ? '0 8px 24px rgba(13,27,42,0.08)' : 'none',
      transition: 'box-shadow 200ms cubic-bezier(0.4,0,0.2,1), border-color 200ms',
      gridColumn: wide ? '1 / -1' : 'auto', breakInside: 'avoid',
    }}>
      <button type="button" aria-expanded={open} aria-controls={`${card.id}-content`} onClick={onToggle} onKeyDown={handleKey}
        style={{
          width: '100%', background: 'transparent', border: 0, textAlign: 'left', cursor: 'pointer',
          padding: '22px 26px', display: 'flex', alignItems: 'flex-start', gap: 18, minHeight: 44,
          fontFamily: 'inherit', borderRadius: 5,
        }}>
        <div style={{ flex: 1 }}>
          <h3 style={{ margin: 0, fontSize: 20, lineHeight: 1.25, fontWeight: 700, color: open ? NK.navy : NK.ink, transition: 'color 200ms', letterSpacing: '-0.005em' }}>
            {card.title}
          </h3>
          {card.sub && <p style={{ margin: '6px 0 0', fontSize: 14.5, lineHeight: 1.5, color: NK.muted, fontWeight: 400, maxWidth: 'none' }}>{card.sub}</p>}
        </div>
        <div style={{
          flexShrink: 0, width: 36, height: 36, borderRadius: 5,
          background: open ? NK.navy : NK.sand, color: open ? '#fff' : NK.ink,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          transition: 'background 200ms, color 200ms, transform 200ms',
          transform: open ? 'rotate(180deg)' : 'rotate(0deg)',
        }}>
          <i data-lucide="chevron-down" style={{ width: 20, height: 20 }} />
        </div>
      </button>
      <div id={`${card.id}-content`} className="card-collapsible" style={{ height: open ? h : 0, overflow: 'hidden', transition: 'height 320ms cubic-bezier(0.4,0,0.2,1)' }}>
        <div ref={contentRef} style={{ padding: '4px 26px 26px', borderTop: `1px solid ${NK.canvas}`, marginTop: 0, paddingTop: 20 }}>
          <CardBody body={card.body} />
        </div>
      </div>
    </article>
  );
}

// ============================================================
// Featured family story card (Door 4)
// ============================================================
function FeaturedStory({ story, navigate }) {
  return (
    <article className="featured-story" style={{
      background: '#fff', border: `1px solid ${NK.divider}`, borderRadius: 5, overflow: 'hidden',
      display: 'grid', gridTemplateColumns: 'minmax(280px, 0.85fr) 1.15fr', gridColumn: '1 / -1',
    }}>
      <div style={{ position: 'relative', minHeight: 420, background: NK.sand, overflow: 'hidden' }}>
        <img src={story.photo} alt={story.photoAlt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 22%' }} />
      </div>
      <div style={{ padding: '40px 44px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
        <div className="eyebrow" style={{ color: NK.navy, marginBottom: 14, display: 'inline-flex', alignItems: 'center', gap: 8 }}>
          <i data-lucide="quote" style={{ width: 16, height: 16 }} />
          {story.kicker}
        </div>
        <h3 style={{ margin: 0, fontSize: 'clamp(26px, 2.4vw, 32px)', lineHeight: 1.1, fontWeight: 800, letterSpacing: '-0.02em', color: NK.ink }}>
          {story.name}
        </h3>
        <div style={{ marginTop: 18, display: 'flex', flexDirection: 'column', gap: 14 }}>
          {story.teaser.map((p, i) => (
            <p key={i} style={{ margin: 0, fontSize: 17.5, lineHeight: 1.6, color: NK.ink, maxWidth: '54ch' }}>{p}</p>
          ))}
        </div>
        <div style={{ fontSize: 14, color: NK.muted, marginTop: 16, fontStyle: 'italic' }}>{story.byline}</div>
        <div style={{ marginTop: 26 }}>
          <Button size="lg" variant="primary" onClick={() => navigate(story.to)}>
            {story.cta} <i data-lucide="arrow-right" style={{ width: 18, height: 18, marginLeft: 2 }} />
          </Button>
        </div>
      </div>
    </article>
  );
}

// ============================================================
// One door — heading + grid of expandable cards
// ============================================================
function Door({ door, background, expanded, onToggleCard, onExpandAll, onCollapseAll, navigate }) {
  const cardsOpenHere = door.cards.filter(c => expanded[c.id]).length;
  const allOpen = cardsOpenHere === door.cards.length;

  return (
    <section style={{ background, position: 'relative' }}>
      <div className="container" style={{ padding: '72px 32px' }}>
        <div className="door-head" style={{
          display: 'grid', gridTemplateColumns: '1fr auto', alignItems: 'end', gap: 24,
          paddingBottom: 28, marginBottom: 32, borderBottom: `1px solid ${NK.divider}`,
        }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 22 }}>
            <div style={{ fontSize: 76, fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.85, color: NK.navy, fontVariantNumeric: 'tabular-nums', flexShrink: 0, marginTop: -2 }}>{door.n}</div>
            <div style={{ paddingTop: 6 }}>
              <div className="eyebrow" style={{ color: NK.ink, marginBottom: 10, display: 'inline-flex', alignItems: 'center', gap: 8 }}>
                <span style={{ display: 'inline-block', width: 18, height: 2, background: NK.navy }} />
                {door.eyebrow}
              </div>
              <h2 className="h2-mobile" style={{ margin: 0, fontSize: 'clamp(26px, 3vw, 36px)', lineHeight: 1.15, fontWeight: 700, letterSpacing: '-0.018em', maxWidth: 700, color: NK.ink, textWrap: 'balance' }}>
                {door.title}
              </h2>
            </div>
          </div>
          <div className="door-toggle">
            <button onClick={() => allOpen ? onCollapseAll(door) : onExpandAll(door)} style={{
              background: 'transparent', border: `1px solid ${NK.navy}`, borderRadius: 5, color: NK.navy,
              padding: '8px 14px', fontFamily: 'inherit', fontWeight: 600, fontSize: 13, cursor: 'pointer',
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}>
              <i data-lucide={allOpen ? 'minimize-2' : 'maximize-2'} style={{ width: 14, height: 14 }} />
              {allOpen ? 'Collapse all' : 'Expand all'}
            </button>
          </div>
        </div>

        <div className="door-grid" style={{
          display: 'grid',
          gridTemplateColumns: door.cards.length === 1 && !door.featured ? '1fr' : 'repeat(auto-fit, minmax(min(420px, 100%), 1fr))',
          gap: 18,
        }}>
          {door.featured && <FeaturedStory story={door.featured} navigate={navigate} />}
          {door.cards.map(card => (
            <ExpandableCard key={card.id} card={card} wide={card.wide || (door.cards.length === 1 && !door.featured)} open={!!expanded[card.id]} onToggle={() => onToggleCard(card.id)} />
          ))}
        </div>
      </div>
    </section>
  );
}

// ============================================================
// "A lifelong journey" — interactive 9-stage timeline
// Source: SCN2A_LifeJourney.pdf; clinical/advocacy language adapted to the
// page's plain-English voice, acronyms glossed on first use. Confirm at sign-off.
// ============================================================
const LIFE_STAGES = [
  { n: '01', name: 'Newborn and diagnosis', age: 'Birth – 3 months',
    happening: ['With "too much" changes, seizures can start within hours of birth.', 'Feeding can be hard, and a baby may be floppy (low muscle tone). Genetic testing usually starts now.'],
    support: ['A newborn (neonatal) neurology team and a genetic doctor.', 'Start NDIS access and connect with Carer Gateway.'] },
  { n: '02', name: 'Stabilisation', age: 'Weeks to years',
    happening: ['The type of change — "too much" or "too little" — matters a lot. Treatment is very different.', 'Sodium channel blockers often help "too much" changes, but can make "too little" changes worse.'],
    support: ['A specialist (tertiary) epilepsy service and a team from different fields.', 'Psychological support for parents and for brothers and sisters.'] },
  { n: '03', name: 'Infancy and early intervention', age: '3 months – 3 years',
    happening: ['Developmental delay may show in movement, talking and social skills.', 'Sleep, feeding and staying calm (regulation) can be hard.'],
    support: ['NDIS Early Childhood Approach.', 'Occupational therapy, speech and physio. Start communication tools (AAC). Ask for respite now.'],
    transition: { label: 'Transition', text: 'Start communication tools (AAC) before school. Connect with an early childhood education service that offers support.' } },
  { n: '04', name: 'Pre-school', age: '3 – 6 years',
    happening: ['The picture of epilepsy, intellectual disability and autism becomes clearer.', 'For many children, development begins to plateau (slow down).'],
    support: ['Inclusion Support Programme for early childhood education and care.', 'Use communication tools (AAC) everywhere. Add behaviour support.'],
    transition: { label: 'Transition', text: 'Starting school: plan 12–18 months ahead. You will need an education plan (IEP), transport, and aide training.' } },
  { n: '05', name: 'Primary school', age: '6 – 12 years',
    happening: ['Hard-to-control (refractory) seizures are common. Bone and joint (orthopaedic) issues can emerge.', 'Most children need special education or a lot of in-class support.'],
    support: ['A yearly education plan (IEP). Aides trained in seizure response and communication tools.', 'Continence aids, an assistive-technology review, and holiday programs.'],
    transition: { label: 'Transition', text: 'High school: shift the focus to everyday life skills. Start planning for puberty and behaviour now.' } },
  { n: '06', name: 'Adolescence', age: '12 – 18 years',
    happening: ['Puberty can change seizure patterns and medicine.', 'Mental health risks rise sharply — including anxiety and depression.'],
    support: ['Begin moving to adult services from age 14.', 'Sort out guardianship or supported decision-making now.'],
    transition: { label: 'Transition', text: 'Paediatric (child) supports end at 18. Plan for this "cliff" well before it arrives.' } },
  { n: '07', name: 'Transition to adulthood', age: '18 – 25 years',
    happening: ['The move from child services to adult services can be abrupt.', 'There is a higher risk of sudden death in epilepsy (SUDEP). Every team should be aware.'],
    support: ['A coordinated handover with overlap — not a sudden drop.', 'Plan supported living (SIL/SDA). Put guardianship, a trust and a will in place.'],
    transition: { label: 'Critical', text: 'Families most often report the system failing here. Housing, legal and medical supports all need to be sorted.' } },
  { n: '08', name: 'Adulthood', age: '25 – 50 years',
    happening: ['Support needs are equal to, or greater than, in childhood.', 'Parents are ageing — planning who takes over care cannot be put off.'],
    support: ['Supported living (SIL, SDA), or family-supported living with skilled workers.', 'Around-the-clock supervision, day programs and community access.'] },
  { n: '09', name: 'Older adulthood', age: '50+ years',
    happening: ['Ageing can come early. The risk of falls and swallowing problems rises.', 'Reviewing all medicines (polypharmacy) is essential. Palliative planning matters.'],
    support: ['Specialist geriatric (older-age) and disability services.', 'Advance care planning, and bereavement support for the family.'] },
];

const CARER_REALITY = [
  { icon: 'heart-pulse', label: 'Care', text: 'Carers give extraordinary levels of direct care — far beyond typical parenting.' },
  { icon: 'moon', label: 'Sleep', text: 'Seizures at night mean most carers live with ongoing, serious sleep loss.' },
  { icon: 'briefcase', label: 'Employment', text: 'Most families have to cut back significantly on paid work.' },
  { icon: 'wallet', label: 'Financial', text: 'Families carry significant extra costs across the whole of life.' },
  { icon: 'eye', label: 'Supervision', text: 'Most adults with SCN2A need around-the-clock supervision to stay safe.' },
  { icon: 'infinity', label: 'Lifelong', text: 'Skills often plateau in late childhood — full independence is usually not reached.' },
];

function JourneyColumn({ icon, title, items, accent, border }) {
  return (
    <div style={{ padding: '26px 28px', borderRight: border ? `1px solid ${NK.canvas}` : 'none' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16 }}>
        <i data-lucide={icon} style={{ width: 18, height: 18, color: accent }} />
        <h4 style={{ margin: 0, fontSize: 14, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: accent }}>{title}</h4>
      </div>
      <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 14 }}>
        {items.map((it, i) => (
          <li key={i} style={{ display: 'grid', gridTemplateColumns: '8px 1fr', gap: 14, alignItems: 'start' }}>
            <span style={{ width: 8, height: 8, background: accent, borderRadius: 2, marginTop: 8 }} />
            <span style={{ fontSize: 16, lineHeight: 1.55, color: NK.ink }}>{it}</span>
          </li>
        ))}
      </ul>
    </div>
  );
}

function journeyStepBtn(disabled) {
  return {
    display: 'inline-flex', alignItems: 'center', gap: 8, background: 'transparent',
    border: `1px solid ${NK.divider}`, borderRadius: 5, color: disabled ? NK.stone : NK.navy,
    padding: '10px 16px', fontFamily: 'inherit', fontSize: 14, fontWeight: 600,
    cursor: disabled ? 'default' : 'pointer', opacity: disabled ? 0.6 : 1,
  };
}

function LifeJourney() {
  const [active, setActive] = React.useState(0);
  const s = LIFE_STAGES[active];
  const isCritical = s.transition && s.transition.label === 'Critical';

  return (
    <section id="journey" style={{ background: '#fff', borderTop: `1px solid ${NK.divider}` }}>
      <div className="container" style={{ padding: '72px 32px' }}>
        <div style={{ maxWidth: 760, marginBottom: 40 }}>
          <div className="eyebrow" style={{ color: NK.ink, marginBottom: 12, display: 'inline-flex', alignItems: 'center', gap: 8 }}>
            <span style={{ display: 'inline-block', width: 18, height: 2, background: NK.navy }} />
            Looking ahead
          </div>
          <h2 className="h2-mobile" style={{ margin: 0, fontSize: 'clamp(26px, 3vw, 36px)', lineHeight: 1.15, fontWeight: 700, letterSpacing: '-0.018em', color: NK.ink, textWrap: 'balance' }}>
            A lifelong journey with SCN2A
          </h2>
          <p style={{ margin: '16px 0 0', fontSize: 18, lineHeight: 1.6, color: NK.muted, maxWidth: 'none' }}>
            SCN2A is part of life at every age. This timeline shows what often happens
            at each stage, and the supports that should be in place. Every child is
            different — use it as a guide for the conversations to have with your team.
          </p>
        </div>

        {/* Stage rail */}
        <div role="tablist" aria-label="Life stages" className="journey-rail" style={{
          display: 'grid', gridTemplateColumns: 'repeat(9, minmax(116px, 1fr))', gap: 8,
          overflowX: 'auto', paddingBottom: 6, marginBottom: 28,
        }}>
          {LIFE_STAGES.map((st, i) => {
            const on = i === active;
            return (
              <button key={st.n} role="tab" aria-selected={on} onClick={() => setActive(i)} style={{
                textAlign: 'left', backgroundColor: on ? NK.navy : '#fff', color: on ? '#fff' : NK.ink,
                border: '1px solid', borderColor: on ? NK.navy : NK.divider,
                borderTop: on ? `3px solid ${NK.navy}` : `3px solid ${NK.divider}`, borderRadius: 5,
                padding: '12px 12px 14px', cursor: 'pointer', fontFamily: 'inherit', minHeight: 76,
                transition: 'background-color 120ms, border-color 120ms, color 120ms',
                display: 'flex', flexDirection: 'column', gap: 4,
              }}>
                <span style={{ fontSize: 18, fontWeight: 800, letterSpacing: '-0.02em', color: on ? 'rgba(255,255,255,0.85)' : NK.navy, fontVariantNumeric: 'tabular-nums' }}>{st.n}</span>
                <span style={{ fontSize: 11.5, fontWeight: 600, color: on ? 'rgba(255,255,255,0.92)' : NK.muted, lineHeight: 1.25 }}>{st.age}</span>
              </button>
            );
          })}
        </div>

        {/* Detail panel */}
        <div style={{ border: `1px solid ${NK.divider}`, borderTop: `4px solid ${NK.navy}`, borderRadius: 5, background: '#fff', overflow: 'hidden' }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 18, flexWrap: 'wrap', padding: '24px 28px', borderBottom: `1px solid ${NK.canvas}`, background: NK.canvas }}>
            <span style={{ fontSize: 40, fontWeight: 800, letterSpacing: '-0.03em', color: NK.navy, lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>{s.n}</span>
            <div>
              <h3 style={{ margin: 0, fontSize: 24, fontWeight: 700, color: NK.ink, letterSpacing: '-0.01em' }}>{s.name}</h3>
              <div style={{ fontSize: 14.5, fontWeight: 600, color: NK.navy, marginTop: 2 }}>{s.age}</div>
            </div>
            <div style={{ marginLeft: 'auto', fontSize: 13, color: NK.muted, fontWeight: 500 }}>Stage {active + 1} of {LIFE_STAGES.length}</div>
          </div>

          <div className="journey-cols" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0 }}>
            <JourneyColumn icon="activity" title="What's happening" items={s.happening} accent={NK.ink} border />
            <JourneyColumn icon="hand-helping" title="Support that should be in place" items={s.support} accent={NK.navy} />
          </div>

          {s.transition && (
            <div style={{
              display: 'flex', alignItems: 'flex-start', gap: 12, margin: '0 28px 28px', padding: '16px 18px', borderRadius: 5,
              background: NK.sand, borderLeft: `4px solid ${isCritical ? NK.mulberry : NK.navy}`,
            }}>
              <i data-lucide={isCritical ? 'alert-triangle' : 'arrow-right-circle'} style={{ width: 18, height: 18, marginTop: 2, flexShrink: 0, color: isCritical ? NK.mulberry : NK.navy }} />
              <div>
                <span className="eyebrow" style={{ color: isCritical ? NK.mulberry : NK.navy, marginRight: 8 }}>{s.transition.label}</span>
                <span style={{ fontSize: 15.5, lineHeight: 1.55, color: NK.ink }}>{s.transition.text}</span>
              </div>
            </div>
          )}
        </div>

        {/* Stepper */}
        <div className="journey-stepper" style={{ display: 'flex', justifyContent: 'space-between', marginTop: 16 }}>
          <button onClick={() => setActive(a => Math.max(0, a - 1))} disabled={active === 0} style={journeyStepBtn(active === 0)}>
            <i data-lucide="chevron-left" style={{ width: 16, height: 16 }} /> Earlier stage
          </button>
          <button onClick={() => setActive(a => Math.min(LIFE_STAGES.length - 1, a + 1))} disabled={active === LIFE_STAGES.length - 1} style={journeyStepBtn(active === LIFE_STAGES.length - 1)}>
            Later stage <i data-lucide="chevron-right" style={{ width: 16, height: 16 }} />
          </button>
        </div>

        {/* Carer reality */}
        <div style={{ marginTop: 64 }}>
          <div style={{ borderTop: `6px solid ${NK.navy}`, paddingTop: 28, marginBottom: 24 }}>
            <h3 style={{ margin: 0, fontSize: 24, fontWeight: 700, color: NK.ink, letterSpacing: '-0.01em' }}>What this means for families</h3>
            <p style={{ margin: '8px 0 0', fontSize: 16.5, lineHeight: 1.6, color: NK.muted, maxWidth: '64ch' }}>
              Caring does not pause. These pressures run across the whole journey — and they are
              real, measurable, and worth naming when you ask for support.
            </p>
          </div>
          <div className="carer-grid" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1, background: NK.divider, border: `1px solid ${NK.divider}`, borderRadius: 5, overflow: 'hidden' }}>
            {CARER_REALITY.map((c) => (
              <div key={c.label} style={{ background: '#fff', padding: '22px 22px 24px' }}>
                <div style={{ width: 40, height: 40, borderRadius: 5, background: NK.sand, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 14 }}>
                  <i data-lucide={c.icon} style={{ width: 20, height: 20, color: NK.navy }} />
                </div>
                <div className="eyebrow" style={{ color: NK.navy, marginBottom: 8 }}>{c.label}</div>
                <p style={{ margin: 0, fontSize: 15.5, lineHeight: 1.55, color: NK.ink, maxWidth: 'none' }}>{c.text}</p>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// Sources accordion + governance footer
// ============================================================
function SourcesAccordion() {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  const [h, setH] = React.useState(0);
  React.useEffect(() => { if (ref.current) setH(ref.current.scrollHeight); }, [open]);

  return (
    <section style={{ background: '#fff', borderTop: `1px solid ${NK.divider}` }}>
      <div className="container" style={{ padding: '56px 32px' }}>
        <div style={{ border: `1px solid ${NK.divider}`, borderRadius: 5, overflow: 'hidden' }}>
          <button type="button" aria-expanded={open} onClick={() => setOpen(o => !o)} style={{
            width: '100%', background: NK.canvas, border: 0, padding: '20px 24px',
            display: 'flex', alignItems: 'center', gap: 16, cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit',
          }}>
            <i data-lucide="book-open" style={{ width: 20, height: 20, color: NK.navy }} />
            <div style={{ flex: 1 }}>
              <div className="eyebrow" style={{ color: NK.navy, marginBottom: 3 }}>References</div>
              <div style={{ fontSize: 18, fontWeight: 700, color: NK.ink }}>Sources and references</div>
            </div>
            <div className="hide-mobile" style={{ fontSize: 13, color: NK.muted }}>{FAM_PAPERS.length} papers · {FAM_ORGS.length} organisations</div>
            <i data-lucide="chevron-down" style={{ width: 22, height: 22, color: NK.navy, transform: open ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 200ms' }} />
          </button>
          <div style={{ height: open ? h : 0, overflow: 'hidden', transition: 'height 320ms cubic-bezier(0.4,0,0.2,1)' }}>
            <div ref={ref} style={{ padding: '28px 28px 32px', borderTop: `1px solid ${NK.divider}` }}>
              <div className="stack-mobile" style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 48 }}>
                <div>
                  <div className="eyebrow" style={{ color: NK.muted, marginBottom: 14 }}>Peer-reviewed papers</div>
                  <ol style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 8 }}>
                    {FAM_PAPERS.map((p, i) => (
                      <li key={p.href} style={{ display: 'grid', gridTemplateColumns: '24px 1fr auto', gap: 10, alignItems: 'baseline', fontSize: 14.5, lineHeight: 1.5, paddingBottom: 8, borderBottom: `1px solid ${NK.canvas}` }}>
                        <span className="ledger-mono" style={{ fontSize: 12, color: NK.muted }}>{String(i + 1).padStart(2, '0')}</span>
                        <span style={{ color: NK.ink }}>{p.name}</span>
                        <a href={p.href} target="_blank" rel="noopener noreferrer" style={{ color: NK.ink, fontWeight: 700, textDecoration: 'none', fontSize: 13, display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                          PubMed <i data-lucide="external-link" style={{ width: 12, height: 12 }} />
                        </a>
                      </li>
                    ))}
                  </ol>
                </div>
                <div>
                  <div className="eyebrow" style={{ color: NK.muted, marginBottom: 14 }}>Australian organisations</div>
                  <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
                    {FAM_ORGS.map((o) => (
                      <li key={o.href} style={{ padding: '10px 0', borderBottom: `1px solid ${NK.canvas}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
                        <span style={{ fontSize: 14.5, color: NK.ink, fontWeight: 500 }}>{o.name}</span>
                        <a href={o.href} target="_blank" rel="noopener noreferrer" style={{ color: NK.ink, fontWeight: 600, textDecoration: 'none', fontSize: 13, display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                          Visit <i data-lucide="external-link" style={{ width: 12, height: 12 }} />
                        </a>
                      </li>
                    ))}
                  </ul>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function GovernanceFooter({ clinicianName }) {
  return (
    <section style={{ background: NK.canvas, borderTop: `1px solid ${NK.divider}` }}>
      <div className="container" style={{ padding: '40px 32px 56px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '64px 1fr', gap: 24, alignItems: 'start' }} className="gov-grid">
          <div style={{ width: 64, height: 64, borderRadius: 5, background: NK.navy, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <i data-lucide="shield-check" style={{ width: 28, height: 28 }} />
          </div>
          <div>
            <div className="eyebrow" style={{ color: NK.navy, marginBottom: 10 }}>Governance</div>
            <p style={{ margin: 0, fontSize: 16, lineHeight: 1.6, color: NK.ink, maxWidth: '70ch' }}>
              Written using peer-reviewed evidence and Australian-recognised support organisations.
            </p>
            <p style={{ margin: '10px 0 0', fontSize: 16, lineHeight: 1.6, color: NK.ink, maxWidth: '70ch' }}>
              Reviewed by{' '}
              <span style={{ background: '#fff', border: `1px dashed ${NK.mulberry}`, borderRadius: 3, padding: '2px 8px', fontWeight: 600, color: NK.mulberry, fontSize: 14 }}>
                {clinicianName || '[CLINICIAN NAME, ROLE]'}
              </span>{' '}
              on 29 May 2026. Next review due 29 May 2027.
            </p>
            <p style={{ margin: '14px 0 0', fontSize: 14, lineHeight: 1.6, color: NK.muted, maxWidth: '70ch' }}>
              This page is information only. It is not medical advice.
              Please talk to your child's clinical team about anything important.
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// FamiliesPage — assembles the whole page
// ============================================================
function FamiliesPage({ navigate }) {
  const CLINICIAN = '[CLINICIAN NAME, ROLE]';
  const [expanded, setExpanded] = React.useState({ [FAM_DOORS[0].cards[0].id]: true });
  const [activeSection, setActiveSection] = React.useState('door-0');
  const [navTop, setNavTop] = React.useState(0);

  // Keep lucide icons rendered as internal state changes (App's effect only
  // fires on route change, not on our card/timeline interactions).
  React.useEffect(() => { if (window.lucide && window.lucide.createIcons) window.lucide.createIcons(); });

  // Measure the sticky site header so the in-page nav docks just below it.
  React.useEffect(() => {
    const measure = () => { const hdr = document.querySelector('header'); setNavTop(hdr ? hdr.offsetHeight : 0); };
    measure();
    window.addEventListener('resize', measure);
    return () => window.removeEventListener('resize', measure);
  }, []);

  const navItems = [
    ...FAM_DOORS.map((d, i) => ({ id: `door-${i}`, n: d.n, label: d.eyebrow })),
    { id: 'journey', n: '', label: 'Lifelong journey' },
  ];

  // Track which section is in view for the sticky in-page nav.
  React.useEffect(() => {
    const els = navItems.map(it => document.getElementById(it.id)).filter(Boolean);
    if (!els.length) return;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting && e.target.id) setActiveSection(e.target.id); });
    }, { rootMargin: '-40% 0px -50% 0px', threshold: 0 });
    els.forEach(s => obs.observe(s));
    return () => obs.disconnect();
  }, []);

  const toggleCard = (id) => setExpanded(prev => ({ ...prev, [id]: !prev[id] }));
  const expandAll = (door) => setExpanded(prev => { const n = { ...prev }; door.cards.forEach(c => n[c.id] = true); return n; });
  const collapseAll = (door) => setExpanded(prev => { const n = { ...prev }; door.cards.forEach(c => n[c.id] = false); return n; });

  const scrollToSection = (id) => {
    const el = document.getElementById(id);
    if (el) {
      const top = el.getBoundingClientRect().top + window.scrollY - (navTop + 56);
      window.scrollTo({ top, behavior: 'smooth' });
    }
  };

  // White / warm-canvas alternation for section rhythm.
  const doorBg = ['#fff', NK.canvas, '#fff', NK.canvas, '#fff'];

  return (
    <div className="families-page" data-screen-label="Families">
      <FamiliesHeaderBand />
      <Breadcrumbs items={[{ label: 'Support', to: 'support' }, { label: 'Newly diagnosed', to: 'newly-diagnosed' }, { label: 'What families need to know' }]} navigate={navigate} />
      <DoorNavStrip items={navItems} activeSection={activeSection} onJump={scrollToSection} top={navTop} />
      <FamHeroExplainer />

      {FAM_DOORS.map((door, i) => (
        <div id={`door-${i}`} key={door.n}>
          <Door door={door} background={doorBg[i]} expanded={expanded} onToggleCard={toggleCard} onExpandAll={expandAll} onCollapseAll={collapseAll} navigate={navigate} />
        </div>
      ))}

      <LifeJourney />
      <SourcesAccordion />
      <GovernanceFooter clinicianName={CLINICIAN} />
    </div>
  );
}

// ============================================================
// Will's story — full family-story page
// Text supplied by Kris Pierce and Dr David Cunnington, set for the web
// almost unchanged (Australian English, sentence-case headings).
// ============================================================
const WILL_STORY = {
  title: "Will's story",
  byline: 'From Kris Pierce and Dr David Cunnington',
  photo: 'assets/photography/will-and-kris.jpeg',
  photoAlt: 'Will and his mum Kris, holding each other close and smiling.',
  caption: 'Will and his mum Kris.',
  lead: "Will's story began long before we had words like precision medicine, developmental and epileptic encephalopathy, or SCN2A. For us, it began with two babies who should have been discovering the world together, but instead one was fighting to survive it.",
  blocks: [
    { type: 'p', text: "Will is a twin. He and his sister Ella arrived together, and from the very first days the contrast between them was something we had to live with. While Ella met her milestones, Will met seizures. While Ella learned to speak, play, and grow independently, Will's world became defined by neurological instability, hospital admissions, medications, scans, specialists, and uncertainty." },
    { type: 'p', text: "In early infancy, the seizures came without warning. Catastrophic, relentless, terrifying. The kind that divide your life into before and after. One moment we were new parents imagining milestones, birthdays, school, friendships, a future full of possibility for both of our children. The next, we were learning emergency protocols, medication schedules, intensive care routines, and how to function on almost no sleep while living in constant fear." },
    { type: 'p', text: "The seizures stole so much from Will before he ever had the chance to gain it. They disrupted his development during the most critical stages of infancy. And they reshaped Ella's childhood too, because no twin grows up untouched by what happens to the other." },
    { type: 'p', text: "For fourteen years, we didn't have a name for what was happening to him. We knew he had epilepsy. We knew it didn't respond to the usual medications. We didn't know why." },
    { type: 'p', text: "And it was never just epilepsy. Will carries the full spectrum of what SCN2A can bring. Severe intellectual disability. Autism. Movement and motor difficulties. Sleep disturbance. Communication that has never developed beyond a handful of sounds. Behavioural complexity. Gastrointestinal issues. The kind of vulnerability that means a cold can become a hospital admission. Will didn't sit neatly in the epilepsy space, or the disability space, or the autism space. He sat across all of them at once, and the system was never designed for a child like that." },
    { type: 'p', text: "Will was eventually diagnosed with an SCN2A-related developmental and epileptic encephalopathy in 2014, at the age of fourteen. A rare genetic condition that changed the trajectory of his life, and ours, forever." },
    { type: 'p', text: "Today, Will is twenty-four. He lives with intellectual disability and very limited communication. He still lives at home with us, just as he has since the day his seizures began. Our home is not simply a family home, it is also a place of care coordination, advocacy, behavioural support, risk management, and around-the-clock caregiving. We have become nurses, therapists, case managers, and protectors, while still trying to simply be Mum and Dad. And Ella has grown up inside all of it. She is her own person, with her own strengths, her own life, her own future. But she is also the sibling of a brother whose needs have shaped the rhythm of every day we have ever lived as a family." },
    { type: 'pull', text: "Yet Will is far more than his diagnosis. He has taught us a different language of connection." },
    { type: 'p', text: "A look, a sound, a smile, a moment of calm, these things carry enormous meaning in our family. Progress is measured differently in our world. Stability is celebrated. Small wins matter enormously. Joy exists, but it exists alongside exhaustion, grief, vigilance, and the knowledge that the future remains uncertain." },
    { type: 'p', text: "Like many rare disease families, we quickly realised that surviving the condition was only part of the battle. Families are forced to navigate fragmented systems, limited awareness, delayed diagnoses, inadequate psychosocial support, and research ecosystems that have historically overlooked ultra-rare conditions. We become the coordinators of care, the keepers of knowledge, and the drivers of progress, because there is no other choice." },
    { type: 'h', text: 'The Florey changed what was possible' },
    { type: 'p', text: "Soon after Will's diagnosis, we were linked with scientists at The Florey who had already started working on SCN2A. That connection changed everything. For the first time, our family wasn't on the outside of the science looking in. We were part of it." },
    { type: 'p', text: "We worked together to build a biobank of cells, including Will's, so the biology of his condition could be studied in the lab. We linked our family into a natural history study so what the team was seeing under the microscope could be matched against what we were living with day to day. Mechanism and experience, lined up side by side." },
    { type: 'p', text: "Our work at The Florey now sits with three researchers in particular. Associate Professor Snezana Maljevic leads on the functional science, understanding exactly what goes wrong when SCN2A misbehaves. With Bang Bui, we're working on unique biomarkers, ways of measuring what's happening in the brain that could one day tell us whether a treatment is working before we have to wait for clinical signs. With Chris Reid, we're now hoping to understand the co-morbidities that come with DEEs, the conditions that travel alongside the seizures and shape so much of daily life." },
    { type: 'p', text: "These pieces, taken together, lead to better understanding. And in our case, they've led to a treatment now in clinical trials. That's a sentence we never expected to write." },
    { type: 'p', text: "We want to be honest about what that means. The treatment emerging from this work is not for Will. The years he lost cannot be given back, and the biology of his condition is too entrenched for him to benefit in the way a newly diagnosed child might. This work is for the children coming behind him. For the families who will receive an SCN2A diagnosis next year, and the year after, and the year after that, and who will walk into a fundamentally different landscape because of what The Florey has built." },
    { type: 'p', text: "That matters to us just as much. Perhaps more. Will's biology, his cells, our family's data and our years of lived experience are part of the foundation that those future children will stand on. We can't change his story. We can help change theirs." },
    { type: 'p', text: "We still have a long way to go to reach a cure. But we believe it's within arm's reach, if we can keep supporting this important work." },
    { type: 'h', text: 'From our family to a movement' },
    { type: 'p', text: "Out of our experience with Will, and alongside many other families walking similar paths, SCN2A Australia was built to create something that did not exist when our journey began: a connected, informed, and empowered community capable of driving meaningful change." },
    { type: 'p', text: "What started as families searching for answers has evolved into a national organisation contributing to research, advocacy, education, policy reform, and global collaboration in SCN2A and developmental and epileptic encephalopathies. We have brought families, clinicians, researchers, industry, and policymakers together to accelerate understanding and push for systems that are responsive to the realities families face. We have advocated for equitable access to genomic testing, earlier diagnosis, multidisciplinary care, psychosocial support, and preparedness for emerging precision therapies." },
    { type: 'p', text: "Importantly, we have worked to move the conversation beyond seizures alone. SCN2A impacts every aspect of life: communication, cognition, behaviour, mobility, education, mental health, family functioning, financial security, and long-term wellbeing. Families do not experience these conditions in silos, and systems cannot continue responding in silos either." },
    { type: 'p', text: "As the precision medicine pipeline advances, this work has become even more urgent. For families like ours, these therapies are not abstract scientific breakthroughs. They represent time. Development. Opportunity. Stability. The possibility that future children diagnosed with SCN2A may have a fundamentally different trajectory than Will did." },
    { type: 'p', text: "That progress matters deeply to us because we know what is at stake." },
    { type: 'p', text: "Will's childhood cannot be given back. The years lost to uncontrolled seizures and delayed diagnosis cannot be rewritten. But his story, and the stories of many children like him, are helping drive change for the next generation. Ella's story is part of this too. Siblings of children with severe disability carry their own weight, build their own resilience, and deserve their own place in the way we tell these stories." },
    { type: 'p', text: "Our journey with Will transformed us from parents navigating survival into advocates determined to challenge systems, accelerate research, and ensure lived experience is no longer treated as an afterthought. Because behind every policy discussion, every funding decision, every research paper, and every clinical trial, there are real children and real families living this reality every single day." },
    { type: 'pull', text: "Will may have very limited words, but his life has spoken loudly." },
    { type: 'p', text: "He has taught us, and Ella, about resilience, humanity, inequity, love, and what it truly means to fight for a future that others cannot yet see." },
  ],
};

function WillsStoryPage({ navigate }) {
  React.useEffect(() => { if (window.lucide && window.lucide.createIcons) window.lucide.createIcons(); });

  return (
    <div data-screen-label="Will's story">
      <Breadcrumbs items={[{ label: 'Support', to: 'support' }, { label: 'What families need to know', to: 'families' }, { label: "Will's story" }]} navigate={navigate} />

      <div className="container-narrow" style={{ padding: '28px 32px 0' }}>
        <a href="#families" onClick={(e) => { e.preventDefault(); navigate('families'); }} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, color: NK.ink, textDecoration: 'none', fontSize: 14, fontWeight: 700 }}>
          <i data-lucide="arrow-left" style={{ width: 16, height: 16 }} /> Back to family information
        </a>
      </div>

      <header className="container-narrow" style={{ padding: '24px 32px 0' }}>
        <div className="eyebrow" style={{ color: NK.ink, marginBottom: 16 }}>Family story</div>
        <h1 className="hero-h1-mobile-lg" style={{ margin: 0, fontSize: 'clamp(38px, 5vw, 56px)', lineHeight: 1.05, fontWeight: 800, letterSpacing: '-0.025em', color: NK.ink }}>
          {WILL_STORY.title}
        </h1>
        <div style={{ fontSize: 16, color: NK.muted, marginTop: 16, fontWeight: 500 }}>{WILL_STORY.byline}</div>
      </header>

      <figure className="container-narrow" style={{ margin: '32px auto 0', padding: '0 32px' }}>
        <div className="photo-tint" style={{ position: 'relative', width: '100%', aspectRatio: '16 / 10', background: NK.sand, borderRadius: 5, overflow: 'hidden' }}>
          <img src={WILL_STORY.photo} alt={WILL_STORY.photoAlt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 20%' }} />
        </div>
        <figcaption style={{ fontSize: 13.5, color: NK.muted, marginTop: 10 }}>{WILL_STORY.caption}</figcaption>
      </figure>

      <div className="container-narrow" style={{ padding: '40px 32px 0' }}>
        <p style={{ margin: 0, fontSize: 'clamp(21px, 2.4vw, 25px)', lineHeight: 1.5, fontWeight: 500, color: NK.ink, maxWidth: '38ch', borderLeft: `4px solid ${NK.mulberry}`, paddingLeft: 22 }}>
          {WILL_STORY.lead}
        </p>
      </div>

      <article className="container-narrow" style={{ padding: '8px 32px 64px' }}>
        <div className="prose-body" style={{ maxWidth: '68ch', fontSize: 18, lineHeight: 1.7, color: NK.ink }}>
          {WILL_STORY.blocks.map((b, i) => {
            if (b.type === 'h') {
              return (
                <h2 key={i} style={{ margin: '48px 0 0', fontSize: 'clamp(24px, 2.6vw, 30px)', lineHeight: 1.2, fontWeight: 700, letterSpacing: '-0.015em', color: NK.ink, paddingTop: 16, borderTop: `6px solid ${NK.navy}`, display: 'table' }}>
                  {b.text}
                </h2>
              );
            }
            if (b.type === 'pull') {
              return (
                <blockquote key={i} style={{ margin: '40px 0', padding: '28px 32px', background: NK.canvas, borderLeft: `4px solid ${NK.mulberry}`, borderRadius: 5, fontSize: 'clamp(22px, 2.4vw, 27px)', lineHeight: 1.4, fontWeight: 700, letterSpacing: '-0.015em', color: NK.ink, fontStyle: 'normal' }}>
                  {b.text}
                </blockquote>
              );
            }
            return <p key={i} style={{ margin: '20px 0 0' }}>{b.text}</p>;
          })}
        </div>
      </article>

      {/* Share CTA — navy anchor */}
      <section style={{ background: NK.navy, color: '#fff', position: 'relative', overflow: 'hidden' }}>
        <NetworkMotif opacity={0.16} stroke="#E8E3DA" />
        <div className="container-narrow" style={{ position: 'relative', padding: '56px 32px', display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between', gap: 28 }}>
          <div style={{ maxWidth: 560 }}>
            <h2 style={{ margin: 0, fontSize: 'clamp(26px, 3vw, 34px)', lineHeight: 1.15, fontWeight: 800, letterSpacing: '-0.02em', color: '#fff' }}>Share your story</h2>
            <p style={{ margin: '12px 0 0', fontSize: 18, lineHeight: 1.6, color: 'rgba(255,255,255,0.92)' }}>
              One family's story matters. One thousand families' stories change policy.
              We share stories with families' permission — if you'd like to share yours, we'd love to hear from you.
            </p>
          </div>
          <Button size="lg" variant="mulberry" onClick={() => navigate('contact')}>Get in touch <i data-lucide="arrow-right" style={{ width: 18, height: 18, marginLeft: 2 }} /></Button>
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { FamiliesPage, WillsStoryPage });
