// Sections — composes components, patterns, and screens into the styleguide pages.

const { useState: useStateSe } = React;

// helpers ────────────────────────────────────────────────────
function Page({ eyebrow, title, lede, children }) {
  return (
    <div className="page">
      <div className="page-header">
        {eyebrow && <div className="page-eyebrow">{eyebrow}</div>}
        <h1 className="page-title">{title}</h1>
        {lede && <p className="page-lede">{lede}</p>}
      </div>
      {children}
    </div>
  );
}

function Section({ kicker, title, desc, children }) {
  return (
    <div className="section">
      {kicker && <div className="section-h">{kicker}</div>}
      <h2 className="section-title">{title}</h2>
      {desc && <p className="section-desc">{desc}</p>}
      {children}
    </div>
  );
}

function Example({ title, desc, children, span }) {
  return (
    <div className="example" style={span ? { gridColumn: `span ${span}` } : undefined}>
      <div className="example-head">
        <div>
          <div className="example-title">{title}</div>
          {desc && <div className="example-desc">{desc}</div>}
        </div>
      </div>
      <div className="example-body">{children}</div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// Foundations
// ═════════════════════════════════════════════════════════════
function FoundationsPage() {
  const swatches = [
    { name: 'primary', value: '#0771f2', usage: 'Filled buttons, FAB, links, focus, app bar (legacy)', token: '--tb-primary' },
    { name: 'primary-press', value: '#0059d6', usage: 'Pressed state', token: '--tb-primary-press' },
    { name: 'on-primary', value: '#ffffff', usage: 'Foreground over primary', token: '--tb-on-primary' },
    { name: 'surface', value: '#ffffff', usage: 'Cards, sheets, app bar (surface variant)', token: '--tb-surface' },
    { name: 'surface-1', value: '#fafbfc', usage: 'List background', token: '--tb-surface-1' },
    { name: 'on-surface', value: '#1e1f24', usage: 'Primary text', token: '--tb-on-surface' },
    { name: 'on-surface-muted', value: '#62636c', usage: 'Secondary text', token: '--tb-on-surface-muted' },
    { name: 'border', value: 'rgba(0,7,53,0.15)', usage: 'Dividers, card borders', token: '--tb-border' },
  ];

  const statusKeys = ['waiting','enroute','onscene','towing','completed','canceled'];

  const typeRoles = [
    { role: 'Display L', size: 36, weight: 600, sample: 'Dispatching' },
    { role: 'Headline L', size: 22, weight: 600, sample: '06\' Acura TL' },
    { role: 'Headline M', size: 20, weight: 600, sample: 'Update status' },
    { role: 'Title L', size: 18, weight: 600, sample: 'Checked in' },
    { role: 'Title M', size: 16, weight: 600, sample: 'L. Brown is towing' },
    { role: 'Body L', size: 16, weight: 400, sample: '157 Carney Drive, Saint Clair, MI 48079' },
    { role: 'Body M', size: 14, weight: 400, sample: '4:28 PM (25m ago)' },
    { role: 'Body S', size: 13, weight: 400, sample: 'Property Gate Code: 12345' },
    { role: 'Label L', size: 14, weight: 500, sample: 'Edit Call' },
    { role: 'Label M', size: 12, weight: 500, sample: 'WAITING · ACTIVE' },
    { role: 'Label S', size: 11, weight: 600, sample: 'PLATE' },
  ];

  return (
    <Page eyebrow="01 · Foundations"
          title="Foundations"
          lede="Color, typography, spacing, elevation, motion, and touch targets — the substrate every screen sits on. Towbook's web tokens are the source of truth; mobile-specific overrides (Android density, button radius, status bar tints) are added on top.">

      <Section kicker="Color · 01" title="Brand & semantic"
               desc="Towbook blue does the heavy lifting for primary actions and brand chrome. Status colors are a fixed semantic palette tied to tow operations — never use them decoratively.">
        <div className="examples tight">
          <Example title="Brand & surface tokens" desc="Bind product code to these — raw scales are for edge cases.">
            <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 6 }}>
              {swatches.map(s => (
                <div key={s.name} style={{
                  display: 'grid', gridTemplateColumns: '40px 120px 1fr',
                  gap: 12, alignItems: 'center',
                  padding: '8px', borderRadius: 8,
                  border: '1px solid var(--tb-border)',
                }}>
                  <span style={{ width: 40, height: 32, borderRadius: 6, background: s.value, border: '1px solid var(--tb-border)' }}/>
                  <code style={{ fontSize: 11.5 }}>{s.token}</code>
                  <span style={{ fontSize: 12, color: 'var(--slate-11)' }}>{s.usage}</span>
                </div>
              ))}
            </div>
          </Example>

          <Example title="Tow operation status" desc="Each status maps to a single color across pills, accent strips, map pins, and timeline dots.">
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {statusKeys.map(k => (
                <div key={k} style={{
                  display: 'flex', alignItems: 'center', gap: 12,
                  padding: '10px 12px',
                  background: TBT.status[k].bg,
                  borderRadius: 8,
                }}>
                  <span style={{ width: 10, height: 10, borderRadius: 99, background: TBT.status[k].solid }}/>
                  <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: TBT.status[k].fg, textTransform: 'capitalize' }}>{TBT.status[k].label}</span>
                  <code style={{ fontSize: 11, color: TBT.status[k].fg }}>{TBT.status[k].solid}</code>
                </div>
              ))}
            </div>
          </Example>
        </div>
      </Section>

      <Section kicker="Type · 02" title="Type scale"
               desc="Inter Variable across the whole product. Roles are mapped from Material 3 type roles; sizes match Towbook's web scale where they overlap, with Android-friendly minimums (12px floor, 16px body).">
        <div className="example">
          <div style={{ display: 'grid', gridTemplateColumns: '120px 60px 1fr', gap: 10 }}>
            <div className="tag">Role</div>
            <div className="tag">Size</div>
            <div className="tag">Sample</div>
            {typeRoles.map(t => (
              <React.Fragment key={t.role}>
                <div style={{ fontSize: 12, color: 'var(--slate-11)' }}>{t.role}</div>
                <div style={{ fontSize: 12, color: 'var(--slate-11)', fontVariantNumeric: 'tabular-nums' }}>{t.size}/{Math.round(t.size*1.3)}</div>
                <div style={{ fontSize: t.size, fontWeight: t.weight, lineHeight: 1.25, letterSpacing: t.size > 18 ? '-0.015em' : 0, color: 'var(--tb-on-surface)' }}>{t.sample}</div>
              </React.Fragment>
            ))}
          </div>
        </div>
      </Section>

      <Section kicker="Spacing · 03" title="Spacing & shape"
               desc="Tailwind 4px scale. Touch targets follow Material 3 — minimum 48dp.">
        <div className="examples tight">
          <Example title="Spacing scale">
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {[1,2,3,4,5,6,8,10,12,16,20,24].map(s => (
                <div key={s} style={{ display: 'grid', gridTemplateColumns: '40px 60px 1fr', gap: 8, alignItems: 'center' }}>
                  <code style={{ fontSize: 11 }}>{s}</code>
                  <code style={{ fontSize: 11, color: 'var(--slate-11)' }}>{s*4}px</code>
                  <span style={{ width: s*4, height: 12, background: 'var(--blue-10)', borderRadius: 2 }}/>
                </div>
              ))}
            </div>
          </Example>

          <Example title="Radii">
            {[
              { name: 'r-input', val: 4, use: 'Outlined text fields' },
              { name: 'r-chip', val: 8, use: 'Chips, status tags' },
              { name: 'r-card', val: 16, use: 'Cards, list groups' },
              { name: 'r-sheet', val: 28, use: 'Bottom sheets (top corners)' },
              { name: 'r-button', val: 999, use: 'Buttons, FAB, pills' },
            ].map(r => (
              <div key={r.name} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '6px 0' }}>
                <div style={{ width: 56, height: 36, background: 'var(--blue-3)', borderRadius: r.val, border: '1px solid var(--blue-7)' }}/>
                <code style={{ fontSize: 11, width: 70 }}>--tb-{r.name}</code>
                <span style={{ fontSize: 12, color: 'var(--slate-11)' }}>{r.use}</span>
              </div>
            ))}
          </Example>

          <Example title="Touch targets" desc="Hit any actionable element with at least 48×48dp. Visual size can be smaller; padding makes up the rest.">
            <div style={{ display: 'flex', gap: 16, alignItems: 'flex-end' }}>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>
                <div style={{ width: 24, height: 24, background: 'var(--tb-on-surface)', borderRadius: 4, position: 'relative' }}>
                  <div style={{ position: 'absolute', inset: -12, border: '1px dashed var(--blue-10)', borderRadius: 8 }}/>
                </div>
                <span style={{ fontSize: 11, color: 'var(--slate-11)' }}>Icon 24, target 48</span>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>
                <TBSwitch checked onChange={() => {}}/>
                <span style={{ fontSize: 11, color: 'var(--slate-11)' }}>Switch 52×32, target 48</span>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }}>
                <TBButton variant="filled" size="md">Action</TBButton>
                <span style={{ fontSize: 11, color: 'var(--slate-11)' }}>Button h=44</span>
              </div>
            </div>
          </Example>

          <Example title="Elevation">
            {[1,2,3].map(n => (
              <div key={n} style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '8px 0' }}>
                <div style={{
                  width: 56, height: 56, borderRadius: 12,
                  background: 'var(--tb-surface)',
                  boxShadow: `var(--tb-elev-${n})`,
                  border: '1px solid var(--tb-border)',
                }}/>
                <code style={{ fontSize: 11 }}>--tb-elev-{n}</code>
                <span style={{ fontSize: 12, color: 'var(--slate-11)' }}>
                  {n === 1 ? 'Cards (resting), bottom action bar' :
                   n === 2 ? 'Cards (raised), map controls' :
                   'Bottom sheets, dialogs, snackbars'}
                </span>
              </div>
            ))}
          </Example>
        </div>
      </Section>

      <Section kicker="Motion · 04" title="Motion"
               desc="Subtle and fast. Most transitions land in 80–200ms. No bounces or elastic curves; press states return immediately to base color rather than scaling.">
        <div className="example">
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
            <MotionDemo label="Fast · 80ms" desc="Press, hover, ripple onset" duration={80}/>
            <MotionDemo label="Base · 150ms" desc="Tab switch, switch toggle, chip select" duration={150}/>
            <MotionDemo label="Slow · 240ms" desc="Bottom sheet, dialog, FAB morph" duration={240}/>
          </div>
          <div className="note" style={{ marginTop: 12 }}>
            Easing is <code className="kbd">cubic-bezier(0.25, 1, 0.5, 1)</code> across the system — a soft ease-out used for both enter and exit. Never use the browser default.
          </div>
        </div>
      </Section>
    </Page>
  );
}

function MotionDemo({ label, desc, duration }) {
  const [on, setOn] = useStateSe(false);
  return (
    <div style={{
      border: '1px solid var(--tb-border)', borderRadius: 12,
      padding: 14, display: 'flex', flexDirection: 'column', gap: 10,
    }}>
      <div style={{ fontSize: 13, fontWeight: 600 }}>{label}</div>
      <div style={{ fontSize: 11.5, color: 'var(--slate-11)', minHeight: 28 }}>{desc}</div>
      <div style={{
        position: 'relative', height: 40, background: 'var(--slate-3)', borderRadius: 8, padding: 4,
      }}>
        <div style={{
          position: 'absolute',
          left: on ? 'calc(100% - 36px)' : 4,
          top: 4, width: 32, height: 32,
          background: 'var(--tb-primary)', borderRadius: 6,
          transition: `left ${duration}ms cubic-bezier(0.25, 1, 0.5, 1)`,
        }}/>
      </div>
      <button onClick={() => setOn(v => !v)} style={{
        padding: '4px 8px', border: '1px solid var(--tb-border)', borderRadius: 6,
        background: 'transparent', cursor: 'pointer', fontSize: 11, fontWeight: 500,
      }}>Trigger</button>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// Components
// ═════════════════════════════════════════════════════════════
function ComponentsPage() {
  return (
    <Page eyebrow="02 · Core components"
          title="Components"
          lede="Material 3 conventions, Towbook tokens. Each component is shown in its real Android frame — try the interactive states in place. Variant naming follows M3 (filled / tonal / outlined / text) so engineers can map directly to Compose Material 3.">

      <Section kicker="Action · 01" title="Buttons">
        <div className="examples">
          <ExButtons/>
          <ExFab/>
        </div>
      </Section>

      <Section kicker="Input · 02" title="Inputs & controls">
        <div className="examples">
          <ExTextField/>
          <ExSelectionControls/>
          <ExChips/>
        </div>
      </Section>

      <Section kicker="Container · 03" title="Cards & lists">
        <div className="examples">
          <ExCards/>
          <ExListItem/>
        </div>
      </Section>

      <Section kicker="Navigation · 04" title="App bar & tabs">
        <div className="examples">
          <ExAppBar/>
          <ExTabs/>
          <ExSubNav/>
        </div>
      </Section>

      <Section kicker="Feedback · 05" title="Dialogs, sheets, snackbars">
        <div className="examples">
          <ExDialog/>
          <ExSheet/>
          <ExSnackbar/>
        </div>
      </Section>

      <Section kicker="Progress · 06" title="Loading">
        <div className="examples tight">
          <ExProgress/>
        </div>
      </Section>
    </Page>
  );
}

function ExButtons() {
  return (
    <Example title="Variants" desc="Filled is reserved for the single primary action on a screen. Tonal for secondary positive actions, outlined for moderate emphasis, text for low-emphasis or repeated actions in cards.">
      <div className="row">
        <TBButton variant="filled">Save changes</TBButton>
        <TBButton variant="tonal">Assign driver</TBButton>
        <TBButton variant="outlined">Cancel</TBButton>
        <TBButton variant="text">Skip</TBButton>
        <TBButton variant="destructive" icon={I.Trash}>Delete</TBButton>
      </div>
      <div className="row">
        <TBButton variant="filled" size="sm" icon={I.Plus}>New call</TBButton>
        <TBButton variant="filled" size="md" icon={I.Plus}>New call</TBButton>
        <TBButton variant="filled" size="lg" icon={I.Plus}>New call</TBButton>
      </div>
      <div className="row">
        <TBButton variant="filled" disabled>Disabled</TBButton>
        <TBButton variant="outlined" icon={I.Send} trailingIcon={I.ChevronRight}>Send to dispatch</TBButton>
      </div>
    </Example>
  );
}

function ExFab() {
  return (
    <Example title="Floating action button" desc="One per screen. Sits 16dp from the bottom-right; on screens with a bottom action bar, sits above it. Extended FAB for screens where the action label adds clarity.">
      <div className="row">
        <TBFab icon={I.Plus}/>
        <TBFab icon={I.Plus} size="small"/>
        <TBFab icon={I.Plus} label="New call"/>
        <TBFab icon={I.Camera} color="tonal"/>
      </div>
    </Example>
  );
}

function ExTextField() {
  const [v, setV] = useStateSe('John Smith');
  const [pwd, setPwd] = useStateSe('');
  return (
    <Example title="Text fields (outlined)" desc="Floating label collapses to the border on focus or fill. Use leading icons sparingly — only when they add type-level clarity (phone, email, location).">
      <div className="col" style={{ background: 'var(--tb-surface)', padding: 16, borderRadius: 12, border: '1px solid var(--tb-border)' }}>
        <TBTextField label="Driver name" value={v} onChange={setV} leadingIcon={I.User}/>
        <TBTextField label="Phone" value="" placeholder="(810) 555-0188" leadingIcon={I.Phone} type="tel"/>
        <TBTextField label="Password" value={pwd} onChange={setPwd} type="password" leadingIcon={I.Lock} trailingIcon={I.Eye}/>
        <TBTextField label="VIN" value="19UUA65506A059978" supporting="17 characters · scannable"/>
        <TBTextField label="Plate" value="" error="Plate is required"/>
        <TBTextField label="Notes" value="" multiline rows={3} placeholder="Anything dispatch should know"/>
      </div>
    </Example>
  );
}

function ExSelectionControls() {
  const [s1, setS1] = useStateSe(true);
  const [s2, setS2] = useStateSe(false);
  const [c1, setC1] = useStateSe(true);
  const [c2, setC2] = useStateSe(false);
  const [r, setR] = useStateSe('cash');
  return (
    <Example title="Switches, checkboxes, radios" desc="Use a switch for binary state with an immediate effect (clock-in, notifications). Checkboxes for multi-select lists. Radios when the selection is exclusive and visible.">
      <div className="col">
        <div className="row">
          <TBSwitch checked={s1} onChange={setS1}/>
          <span style={{ fontSize: 13 }}>Checked in</span>
        </div>
        <div className="row">
          <TBSwitch checked={s2} onChange={setS2}/>
          <span style={{ fontSize: 13, color: 'var(--slate-11)' }}>Allow new calls</span>
        </div>
        <div className="row">
          <TBCheckbox checked={c1} onChange={setC1}/>
          <span style={{ fontSize: 13 }}>Send arrival text</span>
          <TBCheckbox checked={c2} onChange={setC2}/>
          <span style={{ fontSize: 13 }}>Photo receipt</span>
          <TBCheckbox indeterminate onChange={() => {}}/>
          <span style={{ fontSize: 13 }}>Indeterminate</span>
        </div>
        <div className="row">
          <TBRadio checked={r==='cash'} onChange={() => setR('cash')}/>
          <span style={{ fontSize: 13 }}>Cash</span>
          <TBRadio checked={r==='card'} onChange={() => setR('card')}/>
          <span style={{ fontSize: 13 }}>Card</span>
          <TBRadio checked={r==='account'} onChange={() => setR('account')}/>
          <span style={{ fontSize: 13 }}>Account</span>
        </div>
      </div>
    </Example>
  );
}

function ExChips() {
  const [sel, setSel] = useStateSe(new Set(['active']));
  const toggle = k => { const n = new Set(sel); n.has(k) ? n.delete(k) : n.add(k); setSel(n); };
  return (
    <Example title="Chips" desc="Filter chips for list filtering (toggleable), assist chips for quick actions, input chips for selected values that can be removed.">
      <div className="col">
        <div className="row">
          {['waiting','active','completed','canceled'].map(k => (
            <TBChip key={k} selected={sel.has(k)} onClick={() => toggle(k)}>{k.charAt(0).toUpperCase()+k.slice(1)}</TBChip>
          ))}
        </div>
        <div className="row">
          <TBChip variant="assist" leadingIcon={I.Plus}>Add photo</TBChip>
          <TBChip variant="assist" leadingIcon={I.Scan}>Scan VIN</TBChip>
          <TBChip variant="assist" leadingIcon={I.Navigation}>Get directions</TBChip>
        </div>
        <div className="row">
          <TBChip variant="input" onRemove={() => {}}>Saint Clair</TBChip>
          <TBChip variant="input" onRemove={() => {}}>Marysville</TBChip>
          <TBChip variant="input" onRemove={() => {}}>Last 7 days</TBChip>
        </div>
      </div>
    </Example>
  );
}

function ExCards() {
  return (
    <Example title="Cards" desc="Outlined card by default for dense lists; elevated when the card needs to stand off the background (e.g., dialogs, popovers, callouts).">
      <div className="col">
        <TBCard>
          <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>Outlined</div>
          <div style={{ fontSize: 13, color: 'var(--slate-11)' }}>1px slate-alpha border, no shadow. Default for in-app cards.</div>
        </TBCard>
        <TBCard elevated>
          <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>Elevated</div>
          <div style={{ fontSize: 13, color: 'var(--slate-11)' }}>Soft shadow that deepens on hover/press. Use for raised actions.</div>
        </TBCard>
      </div>
    </Example>
  );
}

function ExListItem() {
  return (
    <Example title="List items" desc="Single-line for dense lists (settings, navigation), two-line when supporting text materially helps scanning.">
      <div style={{ background: 'var(--tb-surface)', borderRadius: 12, border: '1px solid var(--tb-border)', overflow: 'hidden' }}>
        <TBListItem leading={<I.Truck size={20}/>} headline="Dispatching" trailing={<I.ChevronRight size={18}/>}/>
        <TBListItem twoLine leading={<I.Lock size={20}/>} headline="Impounds" supporting="3 active · 8 ready for release" trailing={<I.ChevronRight size={18}/>}/>
        <TBListItem twoLine leading={<I.MessageCircle size={20}/>} headline="Chats" supporting="Dispatch · 2 new" trailing={<span style={{ background: 'var(--red-9)', color: 'white', fontSize: 11, fontWeight: 700, padding: '2px 7px', borderRadius: 99 }}>2</span>}/>
        <TBListItem leading={<I.Settings size={20}/>} headline="Settings" trailing={<I.ChevronRight size={18}/>} divider={false}/>
      </div>
    </Example>
  );
}

function ExAppBar() {
  return (
    <Example title="Top app bar" span={2}
             desc="Towbook keeps the brand-blue (primary) variant for top-level destinations — it's a strong wayfinding signal in a glove-box-glance app. Use the surface variant for detail and modal screens where the brand isn't carrying weight.">
      <div className="row" style={{ alignItems: 'flex-start' }}>
        <TBPhone width={320} height={220} scale={0.85}
          appBar={<TBAppBar variant="primary" title="Dispatching" trailing={[
            { icon: I.Search }, { icon: I.Filter }, { icon: I.Refresh }
          ]}/>}
          label="Primary · top-level"
        />
        <TBPhone width={320} height={220} scale={0.85}
          appBar={<TBAppBar variant="surface" title="Call #3176" onBack={() => {}} trailing={[{ icon: I.Edit }]}/>}
          label="Surface · detail"
        />
        <TBPhone width={320} height={220} scale={0.85}
          appBar={<TBAppBar variant="surface" size="medium" title="Equipment Inspection" onBack={() => {}}/>}
          label="Medium · 2-line"
        />
      </div>
    </Example>
  );
}

function ExTabs() {
  const [v, setV] = useStateSe('active');
  return (
    <Example title="Tabs" desc="Primary tabs sit on the app bar background. Counts are inline pills with white-on-blue (or muted-on-surface) treatment.">
      <div style={{ background: 'var(--tb-primary)', borderRadius: 8, overflow: 'hidden' }}>
        <TBTabs variant="primary" value={v} onChange={setV} scrollable items={[
          { value: 'waiting', label: 'Waiting', count: 4 },
          { value: 'active', label: 'Active', count: 3 },
          { value: 'completed', label: 'Completed' },
          { value: 'canceled', label: 'Canceled' },
        ]}/>
      </div>
    </Example>
  );
}

function ExSubNav() {
  const [v, setV] = useStateSe('active');
  const items = [
    { value: 'all',         label: 'All',          count: 47 },
    { value: 'waiting',     label: 'Waiting',      count: 4 },
    { value: 'active',      label: 'Active',       count: 12 },
    { value: 'enroute',     label: 'En route',     count: 5 },
    { value: 'onscene',     label: 'On scene',     count: 3 },
    { value: 'towing',      label: 'Towing',       count: 4 },
    { value: 'completed',   label: 'Completed',    count: 19 },
    { value: 'canceled',    label: 'Canceled' },
    { value: 'impounded',   label: 'Impounded',    count: 8 },
    { value: 'released',    label: 'Released' },
    { value: 'storage',     label: 'In storage' },
    { value: 'auctioned',   label: 'Auctioned' },
  ];
  return (
    <Example
      title="Sub nav (scrollable, blue underline)"
      desc="Surface-level secondary navigation that grows beyond the viewport width. Selected item is brand-blue with a 2px underline; edge fades hint that more content is available. Drag horizontally to scroll — the active tab auto-scrolls into view on selection."
    >
      <TBPhone width={360} height={300} scale={0.9}
        appBar={<TBAppBar variant="primary" title="Dispatching" leading={I.Menu} actions={[I.Search, I.Filter]}/>}
        label="Drag horizontally to scroll"
      >
        <TBSubNav items={items} value={v} onChange={setV}/>
        <div style={{ padding: 20, fontSize: 13, color: 'var(--tb-on-surface-muted)' }}>
          Showing <b style={{ color: 'var(--tb-on-surface)' }}>{items.find(i => i.value === v)?.label}</b> calls.
        </div>
      </TBPhone>

      <div style={{ marginTop: 12, padding: '10px 14px', background: 'var(--slate-2)', borderRadius: 8, fontSize: 12, color: 'var(--slate-11)', lineHeight: 1.55 }}>
        <b style={{ color: 'var(--slate-12)' }}>Compose mapping:</b>{' '}
        <code style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5 }}>ScrollableTabRow</code> with custom <code style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5 }}>indicator</code> = 2dp underline at <code style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5 }}>colorScheme.primary</code>. Tab content padding 16dp horizontal, 44dp height. Edge fades are decorative; arrow IconButtons live on the parent and only render when overflow is present.
      </div>
    </Example>
  );
}

function ExDialog() {
  const [open, setOpen] = useStateSe(false);
  return (
    <Example title="Dialog (alert)" desc="Centered, with optional icon. Two actions max — destructive on the right.">
      <TBPhone width={320} height={420} scale={0.85}
        appBar={<TBAppBar variant="surface" title="Call #3176" onBack={() => {}}/>}
        label="Tap the button below"
      >
        <div style={{ padding: 20 }}>
          <TBButton variant="destructive" icon={I.Trash} onClick={() => setOpen(true)}>Cancel call</TBButton>
        </div>
        <TBDialog open={open}
          icon={I.AlertCircle}
          title="Cancel this call?"
          actions={<>
            <TBButton variant="text" onClick={() => setOpen(false)}>Keep</TBButton>
            <TBButton variant="destructive" onClick={() => setOpen(false)}>Cancel call</TBButton>
          </>}
          onDismiss={() => setOpen(false)}>
          The customer will be notified and the call will move to the canceled tab.
        </TBDialog>
      </TBPhone>
    </Example>
  );
}

function ExSheet() {
  const [open, setOpen] = useStateSe(false);
  return (
    <Example title="Bottom sheet" desc="Modal sheets hold contextual choices — status updates, action menus, filter pickers. Drag handle is always visible.">
      <TBPhone width={320} height={420} scale={0.85}
        appBar={<TBAppBar variant="primary" title="Dispatching"/>}
        label="Tap the FAB"
      >
        <div style={{ padding: 20, color: 'var(--slate-11)', fontSize: 13 }}>List content…</div>
        <div style={{ position: 'absolute', right: 16, bottom: 16 }}>
          <TBFab icon={I.Plus} onClick={() => setOpen(true)}/>
        </div>
        <TBBottomSheet open={open} onDismiss={() => setOpen(false)} title="Update status">
          {['waiting','enroute','onscene','towing','completed','canceled'].map(s => (
            <button key={s} onClick={() => setOpen(false)} style={{
              width: '100%', display: 'flex', alignItems: 'center', gap: 12,
              padding: '14px 24px', border: 0, background: 'transparent', cursor: 'pointer',
            }}>
              <TBStatusPill status={s}/>
              <span style={{ flex: 1 }}/>
              <I.ChevronRight size={18} color="var(--slate-10)"/>
            </button>
          ))}
        </TBBottomSheet>
      </TBPhone>
    </Example>
  );
}

function ExSnackbar() {
  const [open, setOpen] = useStateSe(false);
  React.useEffect(() => {
    if (!open) return;
    const t = setTimeout(() => setOpen(false), 3000);
    return () => clearTimeout(t);
  }, [open]);
  return (
    <Example title="Snackbar" desc="Transient confirmation, with optional single action (Undo, View). Auto-dismiss in 3–4s.">
      <TBPhone width={320} height={300} scale={0.85}
        appBar={<TBAppBar variant="primary" title="Inbox"/>}
        label="Tap to trigger"
      >
        <div style={{ padding: 20 }}>
          <TBButton onClick={() => setOpen(true)}>Mark cleared</TBButton>
        </div>
        <TBSnackbar open={open} action={{ label: 'Undo', onClick: () => setOpen(false) }}>
          Call #3206 cleared.
        </TBSnackbar>
      </TBPhone>
    </Example>
  );
}

function ExProgress() {
  return (
    <Example title="Progress">
      <div className="col">
        <TBLinearProgress indeterminate/>
        <TBLinearProgress value={0.4}/>
        <div className="row" style={{ alignItems: 'center', gap: 16 }}>
          <TBSpinner/>
          <span style={{ fontSize: 13, color: 'var(--slate-11)' }}>Loading…</span>
        </div>
      </div>
    </Example>
  );
}

// ═════════════════════════════════════════════════════════════
// Towbook patterns
// ═════════════════════════════════════════════════════════════
function PatternsPage() {
  return (
    <Page eyebrow="03 · Towbook patterns"
          title="Patterns"
          lede="Composite components built from foundations. These are the things you'll touch most when building screens — they encapsulate the operational vocabulary (statuses, calls, drivers, inspections).">

      <Section kicker="Pattern · 01" title="Status pill"
               desc="A small but loud component. The dot uses the solid status color; background and foreground use the tinted pair for legibility.">
        <div className="example">
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            {['waiting','enroute','onscene','towing','completed','canceled'].map(s => (
              <TBStatusPill key={s} status={s}/>
            ))}
          </div>
          <div className="note" style={{ marginTop: 12 }}>
            Pills are <strong>readable, not decorative</strong>. Avoid stacking multiple statuses; if a state can be both "On scene" and "Waiting on customer," the secondary nuance goes in supporting text.
          </div>
        </div>
      </Section>

      <Section kicker="Pattern · 02" title="Call card"
               desc="The single most important pattern in the app — every dispatch list is a stack of these. The colored top strip echoes the status; the number tag duplicates that color so the card scans top-down even on a scroll-blur.">
        <div className="example" style={{ alignItems: 'flex-start' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(360px, 1fr))', gap: 16 }}>
            {SAMPLE_CALLS.map(c => (
              <div key={c.id} style={{ borderRadius: 12, overflow: 'hidden', border: '1px solid var(--tb-border)' }}>
                <TBCallCard call={c}/>
              </div>
            ))}
          </div>
        </div>
      </Section>

      <Section kicker="Pattern · 03" title="Driver row, inspection row, photo tile">
        <div className="examples">
          <Example title="Driver row" desc="Used in driver picker sheets, the map driver list, and chat recipients.">
            <div style={{ background: 'var(--tb-surface)', borderRadius: 12, border: '1px solid var(--tb-border)', overflow: 'hidden' }}>
              <TBDriverRow name="Lesa Brown" unit="3" status="onscene" distance="2.4 mi"/>
              <TBDriverRow name="Will Smith" unit="7" status="enroute" distance="6.1 mi"/>
              <TBDriverRow name="Eric Brown" unit="12" status="towing" distance="—"/>
              <TBDriverRow name="Marcus Hill" unit="4" status="waiting" distance="0.8 mi"/>
            </div>
          </Example>
          <Example title="Inspection row" desc="Pass / Fail / N/A as a single segmented selector. Camera button shows a count badge when photos are attached.">
            <div style={{ background: 'var(--tb-surface)', borderRadius: 12, border: '1px solid var(--tb-border)', overflow: 'hidden' }}>
              <TBInspectionRow label="Engine oil level" value="pass"/>
              <TBInspectionRow label="Brake fluid level" value="fail" photoCount={1}/>
              <TBInspectionRow label="Boom & winch operation" value="na"/>
              <TBInspectionRow label="Wheel lift function"/>
            </div>
          </Example>
          <Example title="Photo capture tiles" desc="Used on call detail and inspection failure rows. Dashed border = empty slot; count badge surfaces multiple shots.">
            <div className="row">
              <TBPhotoTile label="Front"/>
              <TBPhotoTile src="https://images.unsplash.com/photo-1494976388531-d1058494cdd8?w=200" count={3}/>
              <TBPhotoTile src="https://images.unsplash.com/photo-1583121274602-3e2820c69888?w=200"/>
              <TBPhotoTile label="Add"/>
            </div>
          </Example>
          <Example title="Detail rows" desc="Used in call detail to lay out plate, VIN, contact, etc. Trailing slot accepts an action (Scan, Call) without breaking row height.">
            <div style={{ background: 'var(--tb-surface)', borderRadius: 12, border: '1px solid var(--tb-border)', overflow: 'hidden' }}>
              <TBDetailRow icon={I.Hash} label="Plate" value="XDAN / MI"/>
              <TBDetailRow icon={I.Scan} label="VIN" value="19UUA65506A059978" action={<TBButton variant="text" size="sm">Scan</TBButton>}/>
              <TBDetailRow icon={I.User} label="Driver" value="Lesa Brown — Unit #3"/>
              <TBDetailRow icon={I.KeyRound} label="Keys" value="Yes"/>
            </div>
          </Example>
        </div>
      </Section>

      <Section kicker="Pattern · 04" title="Bottom action bar"
               desc="Persistent action set on detail screens (call detail, impound detail). Sits below content, above the gesture nav. 4-icon max; spill into a More menu beyond that.">
        <div className="example">
          <TBBottomActionBar items={[
            { icon: I.Refresh, label: 'Change Status' },
            { icon: I.Camera, label: 'Add Photo' },
            { icon: I.Map, label: 'Show Map' },
            { icon: I.Layers, label: 'More' },
          ]}/>
        </div>
      </Section>

      <Section kicker="Pattern · 05" title="Pull-to-refresh"
               desc="Standard Material 3 refresh — pulls down to a 36px circle that spins on release.">
        <div className="example">
          <PullDemo/>
        </div>
      </Section>
    </Page>
  );
}

function PullDemo() {
  const [state, setState] = useStateSe('idle');
  return (
    <div className="col">
      <div className="row">
        <TBButton variant="outlined" onClick={() => setState('pulling')}>Show pulling</TBButton>
        <TBButton variant="outlined" onClick={() => { setState('refreshing'); setTimeout(() => setState('idle'), 2000); }}>Trigger refresh</TBButton>
        <TBButton variant="text" onClick={() => setState('idle')}>Reset</TBButton>
      </div>
      <div style={{ background: 'var(--tb-surface-1)', borderRadius: 12, overflow: 'hidden', border: '1px solid var(--tb-border)' }}>
        <TBPullToRefresh pulling={state==='pulling'} refreshing={state==='refreshing'}/>
        <div style={{ padding: '16px', fontSize: 13, color: 'var(--slate-11)' }}>List content below…</div>
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// Screen archetypes / interactive flows
// ═════════════════════════════════════════════════════════════
function ScreensPage({ checkedIn, onCheckedInChange }) {
  return (
    <Page eyebrow="04 · Screens"
          title="Screen archetypes"
          lede="Interactive worked examples — every component composed into a real flow. Use them as a reference for how the system fits together, and tap through the same way a driver would.">

      <Section kicker="Flow · 01" title="Nav drawer"
               desc="Pulled from the left edge. Header has driver identity + clock-in toggle, body has navigation, footer has settings and log out.">
        <div className="example">
          <TBPhone width={320} height={680} scale={0.85}
            label="Drag-style left drawer"
          >
            <NavDrawerScreen checkedIn={checkedIn} onCheckedInChange={onCheckedInChange}/>
          </TBPhone>
        </div>
      </Section>

      <Section kicker="Flow · 02" title="Dispatch list"
               desc="Top-level destination. Tabs across the app bar, call cards in a vertically dense list, FAB to create. Tap a card to open detail; tap Update Status on a card to open a sheet.">
        <DispatchListInteractive/>
      </Section>

      <Section kicker="Flow · 03" title="Call detail (#3176)"
               desc="The deep-detail view: vehicle header, address with directions, contacts, vehicle info, timeline, photos, and a bottom action bar. The status update sheet is reachable from Change Status.">
        <div className="example">
          <TBPhone width={320} height={760} scale={0.85}
            appBar={<TBAppBar variant="surface" title="#3176" centered onBack={() => {}} trailing={[{ icon: I.Edit }, { icon: I.MapPin }]}/>}
            label="Detail screen"
          >
            <CallDetailScreen/>
          </TBPhone>
        </div>
      </Section>

      <Section kicker="Flow · 04" title="Map"
               desc="Stylized map with status-colored pins. Filter chips at the top toggle drivers vs. calls; tapping a pin opens an info card with quick actions.">
        <div className="example">
          <TBPhone width={320} height={680} scale={0.85}
            appBar={<TBAppBar variant="primary" title="Map" trailing={[{ icon: I.Search }, { icon: I.Filter }]}/>}
            label="Map screen"
          >
            <MapScreen/>
          </TBPhone>
        </div>
      </Section>

      <Section kicker="Flow · 05" title="Login & Equipment Inspection"
               desc="Two utility screens in their full archetypes — form and progressive checklist.">
        <div className="examples">
          <Example title="Login (form archetype)" desc="No app bar. Brand mark, headline, fields, primary CTA, secondary text link.">
            <TBPhone width={320} height={620} scale={0.82} label="Sign in">
              <LoginScreen/>
            </TBPhone>
          </Example>
          <Example title="Equipment inspection (checklist archetype)" desc="Header with progress, sectioned list of inspection rows, sticky submit at the bottom.">
            <TBPhone width={320} height={620} scale={0.82}
              appBar={<TBAppBar variant="surface" title="Equipment Inspection" onBack={() => {}} trailing={[{ icon: I.Info }]}/>}
              label="Inspection">
              <InspectionScreen/>
            </TBPhone>
          </Example>
        </div>
      </Section>
    </Page>
  );
}

function DispatchListInteractive() {
  const [tab, setTab] = useStateSe('active');
  const [refreshing, setRefreshing] = useStateSe(false);
  const [callOpen, setCallOpen] = useStateSe(false);
  const triggerRefresh = () => { setRefreshing(true); setTimeout(() => setRefreshing(false), 1500); };
  return (
    <div className="example">
      <div className="row" style={{ marginBottom: 4 }}>
        <TBButton variant="outlined" size="sm" icon={I.Refresh} onClick={triggerRefresh}>Pull to refresh</TBButton>
        <TBButton variant="outlined" size="sm" icon={I.Eye} onClick={() => setCallOpen(true)}>Open a call</TBButton>
        <span style={{ marginLeft: 'auto', fontSize: 12, color: 'var(--slate-11)' }}>Tabs and cards are interactive — try them.</span>
      </div>
      <div className="row" style={{ alignItems: 'flex-start' }}>
        <TBPhone width={360} height={760} scale={0.85}
          appBar={<TBAppBar variant="primary" title="Dispatching" trailing={[
            { icon: I.Search }, { icon: I.Filter }, { icon: I.Refresh, onClick: triggerRefresh }
          ]}/>}
          label="Dispatch list"
        >
          <DispatchListScreen
            tab={tab} onTabChange={setTab}
            refreshing={refreshing}
            onOpenCall={() => setCallOpen(true)}
          />
        </TBPhone>
        <TBPhone width={360} height={760} scale={0.85}
          appBar={<TBAppBar variant="surface" title="#3176" centered onBack={() => setCallOpen(false)} trailing={[{ icon: I.Edit }, { icon: I.MapPin }]}/>}
          label={callOpen ? 'Call open' : 'Tap any card to open'}
        >
          {callOpen ? <CallDetailScreen onBack={() => setCallOpen(false)}/> : (
            <div style={{ padding: 32, textAlign: 'center', color: 'var(--slate-11)' }}>
              <div style={{
                width: 56, height: 56, borderRadius: '50%',
                background: 'var(--blue-3)', color: 'var(--blue-11)',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16,
              }}><I.Eye size={24}/></div>
              <div style={{ fontSize: 14 }}>Tap a call card on the left to open detail.</div>
            </div>
          )}
        </TBPhone>
      </div>
    </div>
  );
}

Object.assign(window, { FoundationsPage, ComponentsPage, PatternsPage, ScreensPage });
