// Hi-fi overlays: routine slide-over + add/edit modal + person/link/spec modals.

const { FONT_DISPLAY: OV_DISPLAY, FONT_BODY: OV_BODY, FONT_MONO: OV_MONO } = window.HIFI;

const CONTACT_CATS = [
  'General Contractor', 'Plumbing', 'Electrical', 'HVAC', 'Pool',
  'Water Treatment', 'Landscaping', 'Smart Home & Security',
  'Cabinetry & Counters', 'Appliance Repair', 'Other',
];
const FREQ_OPTS = ['Weekly', 'Every 2 weeks', 'Monthly', 'Every 2 months', 'Quarterly', 'Twice yearly', 'Annually', 'Per mfr schedule'];
const SEASON_OPTS = ['Year-round', 'Spring', 'Summer', 'Fall', 'Winter', 'Spring / Fall', '—'];
const WHO_OPTS = ['Owner', 'Contractor', 'Owner / Contractor'];
const REMINDER_UNIT_OPTS = [
  { value: 'days', label: 'days' },
  { value: 'weeks', label: 'weeks' },
  { value: 'months', label: 'months' },
];

// Two-input "X weeks before" reminder picker. Setting value to 0 / blank clears it.
const ReminderField = ({ t, label, value, onChange }) => {
  const v = value || { value: '', unit: 'weeks' };
  const setV = (val) => onChange({ value: val === '' ? '' : Math.max(0, Number(val) || 0), unit: v.unit || 'weeks' });
  const setU = (u) => onChange({ value: v.value || '', unit: u });
  return (
    <div>
      <div style={{ fontSize: 12, color: t.inkSoft, marginBottom: 5, fontWeight: 500 }}>{label}</div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'stretch' }}>
        <input type="number" min="0" value={v.value === undefined || v.value === null ? '' : v.value}
          placeholder="e.g. 2"
          onChange={e => setV(e.target.value)}
          style={{
            width: 90, padding: '9px 12px',
            background: t.inputBg, border: `1px solid ${t.border}`,
            borderRadius: 9, fontSize: 14, color: t.ink, outline: 'none',
            fontFamily: 'inherit', boxSizing: 'border-box',
          }}/>
        <div style={{ flex: 1 }}>
          <SelectInput t={t} value={v.unit} onChange={setU} options={REMINDER_UNIT_OPTS}/>
        </div>
        <span style={{ alignSelf: 'center', fontSize: 12.5, color: t.inkFaint, padding: '0 4px' }}>before due</span>
      </div>
      <div style={{ fontSize: 11.5, color: t.inkFaint, marginTop: 5 }}>
        Leave blank for no reminder. Shows on the calendar and in your notifications.
      </div>
    </div>
  );
};

// ---------- Shared modal shell ----------
const ModalShell = ({ t, title, onClose, footer, children, width = 560 }) => (
  <>
    <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(20,18,12,0.32)', zIndex: 40 }}/>
    <div style={{
      position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', zIndex: 41,
      width, maxHeight: '86%',
      background: t.card, border: `1px solid ${t.border}`, borderRadius: 16,
      boxShadow: '0 24px 70px rgba(20,18,12,0.22)',
      display: 'flex', flexDirection: 'column', overflow: 'hidden',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '20px 22px', borderBottom: `1px solid ${t.border}` }}>
        <div style={{ fontFamily: OV_DISPLAY, fontSize: 22, fontWeight: 600, letterSpacing: -0.5, color: t.ink }}>{title}</div>
        <IconBtn t={t} kind="plus" onClick={onClose} title="Close" style={{ transform: 'rotate(45deg)' }}/>
      </div>
      <div style={{ flex: 1, overflowY: 'auto', padding: 22, display: 'flex', flexDirection: 'column', gap: 14 }}>{children}</div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 8, padding: '16px 22px', borderTop: `1px solid ${t.border}` }}>{footer}</div>
    </div>
  </>
);

const Hint = ({ t, children }) => <span style={{ fontSize: 12, color: t.inkFaint, marginRight: 'auto' }}>{children}</span>;

// ---------- Per-routine calendar sync row (slide-over footer) ----------
const RoutineSyncRow = ({ t, r, nav }) => {
  const g = (window.Account.current().calendar || {}).google;
  if (!g) {
    return (
      <div style={{ padding: '12px 22px', borderTop: `1px solid ${t.border}`, display: 'flex', alignItems: 'center', gap: 10, background: t.paper }}>
        <span style={{ width: 30, height: 30, borderRadius: 8, background: t.inputBg, border: `1px solid ${t.border}`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: t.inkFaint, flex: '0 0 auto' }}><HIcon kind="cal" size={15}/></span>
        <div style={{ flex: 1, fontSize: 12.5, color: t.inkSoft }}>Connect a calendar to sync this routine</div>
        <Btn t={t} onClick={() => nav.go('profile')}>Connect</Btn>
      </div>
    );
  }
  return (
    <div style={{ padding: '12px 22px', borderTop: `1px solid ${t.border}`, display: 'flex', alignItems: 'center', gap: 10, background: t.paper }}>
      <span style={{ width: 30, height: 30, borderRadius: 8, background: '#2f6fdb', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}><HIcon kind="cal" size={15}/></span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 600, color: t.ink }}>Google Calendar</div>
        <div style={{ fontSize: 11.5, color: t.inkSoft, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.synced ? `On “${g.target}” · ${g.lead}` : 'Not syncing this routine'}</div>
      </div>
      <button onClick={() => { window.Hub.toggleSync(r.id); nav.refresh(); }} style={{
        display: 'inline-flex', alignItems: 'center', gap: 6, padding: '7px 12px', borderRadius: 9, cursor: 'pointer',
        fontFamily: OV_BODY, fontSize: 12.5, fontWeight: 500, flex: '0 0 auto',
        border: `1px solid ${r.synced ? t.ok : t.border}`,
        background: r.synced ? t.okBg : t.card, color: r.synced ? t.ok : t.ink,
      }}>{r.synced ? <><HIcon kind="check" size={13}/> Synced</> : <><HIcon kind="plus" size={13}/> Add to calendar</>}</button>
    </div>
  );
};

// ---------- Last completed + history ----------
// Card showing when this routine was last done plus its recent completion log.
const RoutineLastDone = ({ t, r }) => {
  const history = (r.completions || []).slice(0, 5);
  const last = history[0];
  const lastLabel = last ? last.label : (r.last && r.last !== '—' ? r.last : null);
  return (
    <div style={{
      border: `1px solid ${t.border}`, borderRadius: 11, padding: '13px 14px',
      background: t.card,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
        <span style={{
          width: 34, height: 34, borderRadius: 9, flex: '0 0 auto',
          background: lastLabel ? t.okBg : t.inputBg,
          color: lastLabel ? t.ok : t.inkFaint,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}><HIcon kind="check" size={16}/></span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 11, color: t.inkFaint, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase' }}>Last completed</div>
          <div style={{ fontSize: 14.5, color: t.ink, fontWeight: 600, marginTop: 1 }}>
            {lastLabel || <span style={{ color: t.inkFaint, fontWeight: 500 }}>Not yet — it'll log here when you mark it done</span>}
          </div>
        </div>
      </div>
      {history.length > 1 && (
        <div style={{ marginTop: 10, paddingTop: 10, borderTop: `1px solid ${t.divider}`, display: 'flex', flexDirection: 'column', gap: 4 }}>
          <div style={{ fontSize: 11, color: t.inkFaint, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', marginBottom: 2 }}>Recent history</div>
          {history.slice(1).map((h, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12.5, color: t.inkSoft }}>
              <span style={{ width: 5, height: 5, borderRadius: '50%', background: t.inkFaint, flex: '0 0 auto' }}/>
              <span>{h.label}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// ---------- Routine slide-over ----------
const HifiRoutineSlideOver = ({ t, routineId, nav }) => {
  const r = findRoutine(routineId);
  if (!r) return null;
  const a = findAsset(r.asset);
  const c = r.contact ? findContact(r.contact) : null;
  const tone = statusTone(t, r.status);
  const statusLabel = r.status === 'overdue' ? 'Overdue' : r.status === 'soon' ? 'Due soon' : 'On track';
  return (
    <>
      <div onClick={nav.closeOverlays} style={{ position: 'absolute', inset: 0, background: 'rgba(20,18,12,0.28)', zIndex: 30 }}/>
      <div className="hh-overlay-panel" style={{
        position: 'absolute', top: 0, bottom: 0, right: 0, width: 460, zIndex: 31,
        background: t.card, borderLeft: `1px solid ${t.border}`,
        boxShadow: '-8px 0 30px rgba(20,18,12,0.10)',
        display: 'flex', flexDirection: 'column',
      }}>
        <div style={{ padding: '20px 22px 16px', borderBottom: `1px solid ${t.border}` }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <HIcon kind={a ? (CAT_ICON[a.cat] || 'repeat') : 'repeat'} size={16} style={{ color: t.inkSoft }}/>
                <span style={{ fontSize: 12, color: t.inkSoft, fontWeight: 600, letterSpacing: 0.5 }}>ROUTINE</span>
              </div>
              <div style={{ fontFamily: OV_DISPLAY, fontSize: 26, fontWeight: 600, letterSpacing: -0.6, color: t.ink, marginTop: 6, lineHeight: 1.1 }}>{r.task}</div>
            </div>
            <IconBtn t={t} kind="plus" onClick={nav.closeOverlays} title="Close" style={{ transform: 'rotate(45deg)' }}/>
          </div>
          <div style={{ display: 'flex', gap: 7, marginTop: 12, flexWrap: 'wrap', alignItems: 'center' }}>
            <Pill t={t} color={tone.c} bg={tone.bg}>{statusLabel}</Pill>
            <Pill t={t}>{r.freq.split(' · ')[0]}</Pill>
            <Pill t={t}>{r.who}</Pill>
            {r.synced && <Pill t={t} color={t.ok} bg={t.okBg}><HIcon kind="sync" size={11}/> On calendar</Pill>}
          </div>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: 22, display: 'flex', flexDirection: 'column', gap: 14 }}>
          <FormField t={t} label="Linked asset" value={a ? a.name : '—'}/>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <FormField t={t} label="Frequency" value={r.freq}/>
            <FormField t={t} label="Season / timing" value={r.season}/>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <FormField t={t} label="Performed by" value={r.who}/>
            <FormField t={t} label="Linked contact" value={c ? c.co : '—'}/>
          </div>
          {/* Last done is now prominent — sits in its own "Last completed" card with a small history. */}
          <RoutineLastDone t={t} r={r}/>
          <FormField t={t} label="Next due" value={r.nextLabel} status={tone.c}/>
          {/* Reminder row */}
          <div>
            <div style={{ fontSize: 12, color: t.inkSoft, marginBottom: 5, fontWeight: 500 }}>Reminder</div>
            <div style={{
              padding: '9px 12px', background: t.inputBg, border: `1px solid ${t.border}`,
              borderRadius: 9, display: 'flex', alignItems: 'center', gap: 9, minHeight: 38,
            }}>
              {r.reminder && r.reminder.value ? (
                <>
                  <span style={{ width: 24, height: 24, borderRadius: 6, background: t.infoBg, color: t.info, display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
                    <HIcon kind="bell" size={13}/>
                  </span>
                  <span style={{ fontSize: 13.5, color: t.ink }}>{window.Hub.reminderLabel(r)}</span>
                </>
              ) : (
                <span style={{ fontSize: 13, color: t.inkFaint }}>No reminder set</span>
              )}
            </div>
          </div>
          <div>
            <div style={{ fontSize: 12, color: t.inkSoft, marginBottom: 5, fontWeight: 500 }}>Notes</div>
            <EditableNote t={t} value={r.notes} placeholder="Add reminders, product specs, links…"
              onSave={(v) => { window.Hub.update('routine', r.id, { notes: v }); nav.refresh(); }}/>
          </div>
        </div>
        <RoutineSyncRow t={t} r={r} nav={nav}/>
        <div style={{ padding: '14px 22px', borderTop: `1px solid ${t.border}`, display: 'flex', alignItems: 'center', gap: 8 }}>
          {isUnscheduled(r)
            ? <Btn t={t} primary onClick={() => nav.openEdit('routine', r)}><HIcon kind="cal" size={14}/> Schedule</Btn>
            : <Btn t={t} primary onClick={() => nav.completeRoutine(r.id)}><HIcon kind="check" size={14}/> Mark done</Btn>}
          <Btn t={t} onClick={() => nav.openEdit('routine', r)}>Edit</Btn>
          <span style={{ flex: 1 }}/>
          {!isUnscheduled(r) && <Btn t={t} onClick={() => { window.Hub.unscheduleRoutine(r.id); nav.refresh(); }} title="Keep on the asset but take it off the calendar">Remove from calendar</Btn>}
          <Btn t={t} danger onClick={() => nav.openModal('deleteRoutine', { routineId: r.id })} title="Delete routine"><HIcon kind="trash" size={15}/></Btn>
        </div>
      </div>
    </>
  );
};

// ---------- Add / Edit modal ----------
const HifiAddModal = ({ t, modal, nav }) => {
  const isEdit = modal.mode === 'edit';
  const type = modal.type;
  const rec = modal.record;
  const ctx = modal.ctx;

  const titles = isEdit
    ? { asset: 'Edit asset', routine: 'Edit routine', contact: 'Edit contact', todo: 'Edit to-do' }
    : { asset: 'Add asset', routine: 'Add routine', contact: 'Add contact', todo: 'Add to-do' };

  const strip = v => (v === '—' ? '' : (v || ''));
  const initial = isEdit ? {
    asset:   { name: rec.name, cat: rec.cat, make: strip(rec.make), model: strip(rec.model), serial: rec.serial, year: rec.year || '', notes: rec.notes },
    routine: { task: rec.task, asset: rec.asset || '', who: rec.who, freq: rec.freq, season: rec.season, contact: rec.contact || '', reminder: rec.reminder || { value: '', unit: 'weeks' }, notes: rec.notes, dueDate: '' },
    contact: { co: rec.co, cat: rec.cat, website: rec.website || '', phone: rec.phone || '', email: rec.email || '', address: rec.address || '', notes: rec.notes },
    todo:    { title: rec.title, type: rec.type, priority: rec.priority, asset: rec.asset || '', due: rec.due },
  }[type] : {
    asset:   { name: '', cat: '', make: '', model: '', serial: '', year: '', notes: '' },
    routine: { task: '', asset: ctx?.assetId || '', who: '', freq: '', season: '', contact: '', reminder: { value: '', unit: 'weeks' }, notes: '', dueDate: '' },
    contact: { co: '', cat: '', person: '', role: '', phone: '', email: '', notes: '' },
    todo:    { title: '', type: 'Task', priority: 'Normal', due: '', asset: ctx?.assetId || '' },
  }[type];

  const [form, setForm] = React.useState(initial);
  const set = (k) => (v) => setForm(prev => ({ ...prev, [k]: v }));

  const assetOpts = ASSETS.map(a => ({ value: a.id, label: a.name }));
  const contactOpts = CONTACTS.map(c => ({ value: c.id, label: c.co }));

  const requiredKey = { asset: 'name', routine: 'task', contact: 'co', todo: 'title' }[type];
  const valid = (form[requiredKey] || '').trim().length > 0;

  const submit = () => {
    if (!valid) return;
    if (isEdit) {
      const payload = { ...form };
      if (type === 'routine' && !payload.dueDate) delete payload.dueDate; // keep existing schedule
      nav.update(type, rec.id, payload);
    } else {
      nav.create(type, form, ctx);
    }
  };

  return (
    <ModalShell t={t} title={titles[type]} onClose={nav.closeOverlays} footer={<>
      {!valid && <Hint t={t}>Add a {requiredKey === 'co' ? 'company name' : requiredKey} to continue</Hint>}
      <Btn t={t} onClick={nav.closeOverlays}>Cancel</Btn>
      <Btn t={t} primary onClick={submit} style={valid ? {} : { opacity: 0.5, cursor: 'not-allowed' }}>{isEdit ? 'Save changes' : 'Create'}</Btn>
    </>}>
      {type === 'asset' && <>
        <TextInput t={t} label="Name" required marks={2} value={form.name} onChange={set('name')} placeholder="e.g. Furnace"/>
        <SelectInput t={t} label="Category" marks={1} value={form.cat} onChange={set('cat')} options={CATEGORIES} placeholder="Choose a category"/>
        <TextInput t={t} label="Make" marks={1} value={form.make} onChange={set('make')} placeholder="e.g. Carrier"/>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
          <TextInput t={t} label="Model" value={form.model} onChange={set('model')}/>
          <TextInput t={t} label="Serial" value={form.serial} onChange={set('serial')}/>
          <TextInput t={t} label="Year" value={form.year} onChange={set('year')} placeholder="e.g. 2019"/>
        </div>
        <TextArea t={t} label="Notes" value={form.notes} onChange={set('notes')} placeholder="Anything you want to remember…"/>
        <Hint t={t}>** required · * default details we’ll track as a to-do until filled in</Hint>
      </>}

      {type === 'routine' && <>
        <TextInput t={t} label="Task" required value={form.task} onChange={set('task')} placeholder="e.g. Filter replacement"/>
        <SelectInput t={t} label="Linked asset" value={form.asset} onChange={set('asset')} options={assetOpts} placeholder="Choose an asset"/>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <SelectInput t={t} label="Frequency" value={form.freq} onChange={set('freq')} options={FREQ_OPTS} placeholder="How often?"/>
          <TextInput t={t} label={isEdit ? 'Reschedule due date' : 'Next due date'} type="date" value={form.dueDate} onChange={set('dueDate')}/>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <SelectInput t={t} label="Performed by" value={form.who} onChange={set('who')} options={WHO_OPTS} placeholder="Owner or contractor?"/>
          <SelectInput t={t} label="Season" value={form.season} onChange={set('season')} options={SEASON_OPTS} placeholder="When?"/>
        </div>
        <SelectInput t={t} label="Linked contact" value={form.contact} onChange={set('contact')} options={contactOpts} placeholder="Optional" clearable/>
        <ReminderField t={t} label="Reminder" value={form.reminder} onChange={set('reminder')}/>
        <TextArea t={t} label="Notes" value={form.notes} onChange={set('notes')}/>
        {!isEdit && <Hint t={t}>Pick a next due date and a frequency — it’ll show on the calendar and repeat automatically.</Hint>}
      </>}

      {type === 'contact' && <>
        {!isEdit && ctx && ctx.assetId && <Hint t={t}>Links to {(findAsset(ctx.assetId) || {}).name || 'this asset'} once created.</Hint>}
        <TextInput t={t} label="Company name" required value={form.co} onChange={set('co')} placeholder="e.g. Solda Pools"/>
        <SelectInput t={t} label="Category" value={form.cat} onChange={set('cat')} options={CONTACT_CATS} placeholder="Choose a category"/>
        {!isEdit && <>
          <TextInput t={t} label="Contact person" value={form.person} onChange={set('person')} placeholder="optional — you can add more later"/>
          <TextInput t={t} label="Role" value={form.role} onChange={set('role')} placeholder="e.g. service lead, owner, scheduler"/>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <TextInput t={t} label="Phone" value={form.phone} onChange={set('phone')} type="tel"/>
            <TextInput t={t} label="Email" value={form.email} onChange={set('email')} type="email"/>
          </div>
        </>}
        {isEdit && <>
          <TextInput t={t} label="Website" value={form.website} onChange={set('website')} placeholder="example.com"/>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <TextInput t={t} label="Company phone" value={form.phone} onChange={set('phone')} type="tel"/>
            <TextInput t={t} label="Company email" value={form.email} onChange={set('email')} type="email"/>
          </div>
          <TextInput t={t} label="Address" value={form.address} onChange={set('address')} placeholder="street, city, province"/>
        </>}
        <TextArea t={t} label="Notes" value={form.notes} onChange={set('notes')} placeholder="Account #s, scheduling, etc."/>
      </>}

      {type === 'todo' && <>
        <TextInput t={t} label="Title" required value={form.title} onChange={set('title')} placeholder="What needs to happen?"/>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
          <SelectInput t={t} label="Type" value={form.type} onChange={set('type')} options={['Task', 'Info Gap']}/>
          <SelectInput t={t} label="Priority" value={form.priority} onChange={set('priority')} options={['High', 'Normal', 'Low']}/>
          <TextInput t={t} label="Due" value={form.due} onChange={set('due')} placeholder="optional"/>
        </div>
        <SelectInput t={t} label="Linked asset" value={form.asset} onChange={set('asset')} options={assetOpts} placeholder="Optional"/>
      </>}
    </ModalShell>
  );
};

// ---------- Add / edit a person on a contact ----------
const HifiPersonModal = ({ t, modal, nav }) => {
  const c = findContact(modal.contactId);
  const isEdit = modal.personIndex != null;
  const existing = (isEdit && c && c.people && c.people[modal.personIndex]) || {};
  const unGap = v => (isGap(v) ? '' : (v || ''));
  const [form, setForm] = React.useState({
    name: existing.name || '', role: existing.role || '',
    phone: unGap(existing.phone), email: unGap(existing.email),
  });
  const set = (k) => (v) => setForm(prev => ({ ...prev, [k]: v }));
  const valid = form.name.trim().length > 0;
  const save = () => {
    if (!valid) return;
    if (isEdit) nav.updatePerson(modal.contactId, modal.personIndex, form);
    else nav.addPerson(modal.contactId, form);
  };
  return (
    <ModalShell t={t} title={`${isEdit ? 'Edit' : 'Add'} person${c ? ' · ' + c.co : ''}`} onClose={nav.closeOverlays} footer={<>
      {isEdit && <Btn t={t} danger onClick={() => nav.removePerson(modal.contactId, modal.personIndex)} style={{ marginRight: 'auto' }}><HIcon kind="trash" size={14}/> Remove</Btn>}
      {!valid && !isEdit && <Hint t={t}>Add a name to continue</Hint>}
      <Btn t={t} onClick={nav.closeOverlays}>Cancel</Btn>
      <Btn t={t} primary onClick={save} style={valid ? {} : { opacity: 0.5, cursor: 'not-allowed' }}>{isEdit ? 'Save changes' : 'Add person'}</Btn>
    </>}>
      <TextInput t={t} label="Name" required value={form.name} onChange={set('name')} placeholder="e.g. Dave Solda"/>
      <TextInput t={t} label="Role" value={form.role} onChange={set('role')} placeholder="e.g. service lead"/>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <TextInput t={t} label="Phone" value={form.phone} onChange={set('phone')} type="tel"/>
        <TextInput t={t} label="Email" value={form.email} onChange={set('email')} type="email"/>
      </div>
    </ModalShell>
  );
};

// ---------- Link assets to a contact ----------
const HifiLinkAssetModal = ({ t, modal, nav }) => {
  const c = findContact(modal.contactId);
  const direct = new Set((c && c.assets) || []);
  const viaRoutine = new Set(ROUTINES.filter(r => r.contact === modal.contactId).map(r => r.asset));
  return (
    <ModalShell t={t} title={`Link assets${c ? ' · ' + c.co : ''}`} onClose={nav.closeOverlays} footer={<>
      <Hint t={t}>Tap an asset to link or unlink it</Hint>
      <Btn t={t} primary onClick={nav.closeOverlays}>Done</Btn>
    </>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {ASSETS.map(a => {
          const isDirect = direct.has(a.id);
          const isRoutine = viaRoutine.has(a.id);
          const on = isDirect || isRoutine;
          return (
            <div key={a.id} onClick={() => !isRoutine && nav.linkAsset(modal.contactId, a.id)}
              style={{
                display: 'flex', alignItems: 'center', gap: 12, padding: '11px 12px',
                border: `1px solid ${on ? t.accent : t.border}`, borderRadius: 10,
                background: on ? t.okBg : t.card, cursor: isRoutine ? 'default' : 'pointer',
              }}>
              <HIcon kind={CAT_ICON[a.cat] || 'grid'} size={18} style={{ color: t.inkSoft }}/>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, color: t.ink, fontWeight: 500 }}>{a.name}</div>
                <div style={{ fontSize: 12, color: t.inkSoft }}>{a.cat}</div>
              </div>
              {isRoutine && !isDirect && <Pill t={t}>via routine</Pill>}
              <span style={{
                width: 20, height: 20, borderRadius: 6, flex: '0 0 auto',
                border: `1.5px solid ${on ? t.accent : t.border}`,
                background: on ? t.accent : t.inputBg,
                display: 'flex', alignItems: 'center', justifyContent: 'center', color: t.accentInk,
              }}>{on && <HIcon kind="check" size={13}/>}</span>
            </div>
          );
        })}
      </div>
    </ModalShell>
  );
};

// ---------- Link contacts to an asset (reverse of the asset-link modal) ----------
const HifiLinkContactModal = ({ t, modal, nav }) => {
  const a = findAsset(modal.assetId);
  const viaRoutine = new Set(ROUTINES.filter(r => r.asset === modal.assetId).map(r => r.contact).filter(Boolean));
  return (
    <ModalShell t={t} title={`Link contacts${a ? ' · ' + a.name : ''}`} onClose={nav.closeOverlays} footer={<>
      <Hint t={t}>Tap a contact to link or unlink it</Hint>
      <Btn t={t} primary onClick={nav.closeOverlays}>Done</Btn>
    </>}>
      {CONTACTS.length === 0 && (
        <div style={{ textAlign: 'center', padding: '8px 0' }}>
          <div style={{ fontSize: 13, color: t.inkSoft, marginBottom: 12 }}>No contacts yet. Create one and it’ll link to this asset.</div>
          <Btn t={t} primary onClick={() => nav.openAdd('contact', { assetId: modal.assetId })}><HIcon kind="plus" size={13}/> New contact</Btn>
        </div>
      )}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {CONTACTS.map(c => {
          const isDirect = (c.assets || []).includes(modal.assetId);
          const isRoutine = viaRoutine.has(c.id);
          const on = isDirect || isRoutine;
          return (
            <div key={c.id} onClick={() => !isRoutine && nav.linkContact(modal.assetId, c.id)}
              style={{
                display: 'flex', alignItems: 'center', gap: 12, padding: '11px 12px',
                border: `1px solid ${on ? t.accent : t.border}`, borderRadius: 10,
                background: on ? t.okBg : t.card, cursor: isRoutine ? 'default' : 'pointer',
              }}>
              <HIcon kind="phone" size={18} style={{ color: t.inkSoft }}/>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, color: t.ink, fontWeight: 500 }}>{c.co}</div>
                <div style={{ fontSize: 12, color: t.inkSoft }}>{c.cat}</div>
              </div>
              {isRoutine && !isDirect && <Pill t={t}>via routine</Pill>}
              <span style={{
                width: 20, height: 20, borderRadius: 6, flex: '0 0 auto',
                border: `1.5px solid ${on ? t.accent : t.border}`,
                background: on ? t.accent : t.inputBg,
                display: 'flex', alignItems: 'center', justifyContent: 'center', color: t.accentInk,
              }}>{on && <HIcon kind="check" size={13}/>}</span>
            </div>
          );
        })}
      </div>
    </ModalShell>
  );
};

// ---------- Add spec to an asset ----------
const HifiSpecModal = ({ t, modal, nav }) => {
  const a = findAsset(modal.assetId);
  const [form, setForm] = React.useState({ key: '', value: '' });
  const set = (k) => (v) => setForm(prev => ({ ...prev, [k]: v }));
  const valid = form.key.trim().length > 0 && form.value.trim().length > 0;
  return (
    <ModalShell t={t} width={460} title={`Add spec${a ? ' · ' + a.name : ''}`} onClose={nav.closeOverlays} footer={<>
      {!valid && <Hint t={t}>Fill both fields to continue</Hint>}
      <Btn t={t} onClick={nav.closeOverlays}>Cancel</Btn>
      <Btn t={t} primary onClick={() => valid && nav.addSpec(modal.assetId, form.key, form.value)} style={valid ? {} : { opacity: 0.5, cursor: 'not-allowed' }}>Add spec</Btn>
    </>}>
      <TextInput t={t} label="Spec name" required value={form.key} onChange={set('key')} placeholder="e.g. Filter size"/>
      <TextInput t={t} label="Value" required value={form.value} onChange={set('value')} placeholder="e.g. 20x25x5"/>
    </ModalShell>
  );
};

// ---------- Delete routine confirm ----------
const HifiDeleteRoutineModal = ({ t, nav, ctx }) => {
  const r = findRoutine(ctx.routineId);
  if (!r) return null;
  const a = r.asset ? findAsset(r.asset) : null;
  return (
    <ModalShell t={t} width={440} title="Delete routine?" onClose={nav.closeOverlays} footer={<>
      <Btn t={t} onClick={nav.closeOverlays}>Cancel</Btn>
      <Btn t={t} onClick={() => { window.Hub.deleteRoutine(r.id); nav.refresh(); nav.closeOverlays(); }}
        style={{ background: t.overdue, color: '#fff', border: `1px solid ${t.overdue}` }}>Delete routine</Btn>
    </>}>
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
        <span style={{ width: 36, height: 36, borderRadius: 9, flex: '0 0 auto', background: t.overdueBg, color: t.overdue, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><HIcon kind="trash" size={17}/></span>
        <div style={{ fontSize: 13.5, color: t.inkSoft, lineHeight: 1.55 }}>
          Delete <strong style={{ color: t.ink }}>{r.task}</strong>{a ? <> from <strong style={{ color: t.ink }}>{a.name}</strong></> : ''}? It will be removed from the routines calendar{r.synced ? ' and from your connected Google Calendar' : ''}. This can’t be undone.
          <div style={{ marginTop: 8, color: t.inkFaint, fontSize: 12.5 }}>To keep it on the asset but off the calendar, use <strong style={{ color: t.inkSoft }}>Remove from calendar</strong> instead.</div>
        </div>
      </div>
    </ModalShell>
  );
};

Object.assign(window, {
  HifiRoutineSlideOver, HifiAddModal,
  HifiPersonModal, HifiLinkAssetModal, HifiLinkContactModal, HifiSpecModal,
  HifiDeleteRoutineModal,
});
