/* Book with Toni — Direction B demo · availability model + booking flow */
const OWNER_OFFSET = 1; // Lagos, no DST
const CITIES = [
  ['Lagos','Africa/Lagos'],['London','Europe/London'],['Berlin','Europe/Berlin'],
  ['Nairobi','Africa/Nairobi'],['Dubai','Asia/Dubai'],['New York','America/New_York'],
  ['San Francisco','America/Los_Angeles'],['Singapore','Asia/Singapore'],
];
const TYPES = [
  { id:'discovery', name:'Discovery call', dur:30, durLabel:'30 min', who:'Usually a prospective client',
    line:'Thirty minutes to hear what you’re working on and work out whether I’m the right person for it.',
    head:['Discovery','call.'], lede:'Thirty minutes to hear what you’re working on and work out whether I’m the right person for it. No preparation needed — turn up with the problem as it actually is.', listed:true },
  { id:'brainstorm', name:'Brainstorming session', dur:60, durLabel:'45–60 min', who:'Anyone with a problem worth an hour',
    line:'One problem, thought through properly. Bring the messy version.',
    head:['Let’s think','about it properly.'], lede:'One problem, thought through properly — positioning, a product decision, a strategy that isn’t landing. Bring the messy version; that’s the useful one.', listed:true },
  { id:'checkin', name:'Project check-in', dur:30, durLabel:'30 min', who:'Existing clients',
    line:'Where things stand: progress, decisions, anything blocking.',
    head:['Check-in.'], lede:'Thirty minutes on where things stand: progress, decisions, anything blocking.', listed:true, kicker:'Sunbird Group · Growth sprint', prefill:true },
  { id:'kickoff', name:'Project kickoff', dur:30, durLabel:'30 min', who:'Starting a project or workstream',
    line:'Scope, sequence, who does what, and what we’ll have in a month.',
    head:['Kickoff.'], lede:'Thirty minutes to start properly — scope, sequence, who does what, and what we’ll have in a month. Short on purpose: we decide, we don’t drift.', listed:true, kicker:'Loomi Co. · Skincare launch' },
  { id:'quick', name:'Quick call', dur:15, durLabel:'15 min', who:'Faster said than typed',
    line:'Fifteen minutes for the thing that’s faster said than typed.',
    head:['Quick','call.'], lede:'Fifteen minutes for the thing that’s faster said than typed.', listed:true, prefill:true, flat:true },
];
const WINDOWS = { 1:[[9,13],[15,17]], 2:[[9,13]], 3:[[10,16]], 4:[[9,12],[14,16]], 5:[], 6:[], 0:[] };
const NOTICE_H = 18, HORIZON_W = 8;

const pad = n => String(n).padStart(2,'0');
const ownerDate = d => `${d.getUTCFullYear()}-${pad(d.getUTCMonth()+1)}-${pad(d.getUTCDate())}`;
function makeSlot(y,m,d,h,min){ return new Date(Date.UTC(y,m,d,h-OWNER_OFFSET,min)); }

function buildDays(type, closedKeys){
  const step = type.dur <= 30 ? 45 : type.dur <= 60 ? 60 : 90;
  const now = Date.now(), earliest = now + NOTICE_H*3600e3;
  const out = [];
  const cursor = new Date();
  for(let i=0;i<HORIZON_W*7;i++){
    const dt = new Date(cursor.getTime() + i*86400e3);
    const y = dt.getFullYear(), m = dt.getMonth(), d = dt.getDate();
    const key = `${y}-${pad(m+1)}-${pad(d)}`;
    const wd = new Date(Date.UTC(y,m,d)).getUTCDay();
    const wins = closedKeys.has(key) ? [] : (WINDOWS[wd]||[]);
    const slots = [];
    wins.forEach(([ws,we])=>{
      for(let t = ws*60; t + type.dur <= we*60; t += step){
        const s = makeSlot(y,m,d,Math.floor(t/60), t%60);
        if(s.getTime() >= earliest) slots.push(s);
      }
    });
    out.push({ key, y, m, d, wd, date:new Date(Date.UTC(y,m,d,12)), slots });
  }
  return out;
}

const fmt = (date, tz, opts) => new Intl.DateTimeFormat('en-GB',{ timeZone:tz, ...opts }).format(date);
const timeIn = (date, tz) => fmt(date, tz, { hour:'2-digit', minute:'2-digit', hour12:false });
const offsetLabel = tz => {
  const s = new Intl.DateTimeFormat('en-GB',{ timeZone:tz, timeZoneName:'shortOffset' }).format(new Date());
  const m = s.match(/GMT[+-]?\d*/);
  return (m ? m[0] : 'GMT').replace('GMT+0','GMT').replace(/GMT$/,'GMT+0');
};
const WD = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
const MO = ['January','February','March','April','May','June','July','August','September','October','November','December'];
const longDay = day => `${WD[day.wd]==='Sun'?'Sunday':({Mon:'Monday',Tue:'Tuesday',Wed:'Wednesday',Thu:'Thursday',Fri:'Friday',Sat:'Saturday'})[WD[day.wd]]} ${day.d} ${MO[day.m]}`;
const shortDay = day => `${WD[day.wd]} ${day.d}`;
const groupOf = (date,tz) => { const h = +timeIn(date,tz).slice(0,2); return h < 12 ? 'Morning' : h < 17 ? 'Afternoon' : 'Evening'; };

/* ── small components ───────────────────────────────────────── */
function Mark({ who='Toni Dada · Growth Strategy & Execution' }){
  return <div className="mark"><img src="uploads/enterscale logo white.png" alt="Enterscale"/><i></i><span className="who">{who}</span></div>;
}
function Field({ label, optional, value, onChange, onBlur, error, textarea, placeholder, type='text', autoFocus, inputMode, autoComplete }){
  const id = React.useId();
  const P = textarea ? 'textarea' : 'input';
  return (
    <div className="fld">
      <label htmlFor={id}>{label}{optional && <span> optional</span>}</label>
      <P id={id} className={'in'+(textarea?' ta':'')+(error?' err':'')} value={value} placeholder={placeholder}
         type={textarea?undefined:type} inputMode={inputMode} autoComplete={autoComplete} autoFocus={autoFocus}
         aria-invalid={!!error} aria-describedby={error?id+'-e':undefined}
         onChange={e=>onChange(e.target.value)} onBlur={onBlur} rows={textarea?3:undefined}/>
      {error && <p className="msg" id={id+'-e'}>{error}</p>}
    </div>
  );
}
function Guests({ guests, setGuests, hostEmail, max=4 }){
  const [open,setOpen] = React.useState(guests.length>0);
  const [val,setVal] = React.useState('');
  const [err,setErr] = React.useState(null);
  const [foc,setFoc] = React.useState(false);
  const ref = React.useRef(null);
  function add(){
    const e = val.trim().toLowerCase();
    if(!e) return;
    if(!/^[^\s@]+@[^\s@]+\.[a-z]{2,}$/i.test(e)) return setErr('That email looks incomplete — check for a missing dot or letter.');
    if(e === (hostEmail||'').toLowerCase()) return setErr('That’s you — you’re already on it.');
    if(guests.includes(e)) return setErr('Already on the invitation.');
    setGuests([...guests, e]); setVal(''); setErr(null);
    if(ref.current) ref.current.focus();
  }
  if(!open) return (
    <div className="guests">
      <button className="gopen" onClick={()=>{setOpen(true); setTimeout(()=>ref.current&&ref.current.focus(),0)}}>+ Bring someone else</button>
      <p className="gnote">They’ll get the same invitation and Meet link. You can also just forward it later.</p>
    </div>
  );
  return (
    <div className="guests">
      <p className="lbl">Others joining <span style={{letterSpacing:'.02em',textTransform:'none',fontSize:11,color:'var(--t3)',fontWeight:400}}>optional</span></p>
      {guests.map(g=>(
        <div className="grow" key={g}>
          <span className="em">{g}</span>
          <button className="rm" onClick={()=>setGuests(guests.filter(x=>x!==g))} aria-label={'Remove '+g}>remove</button>
        </div>
      ))}
      {guests.length < max ? (
        <>
          <div className={'gadd'+(foc?' foc':'')}>
            <input ref={ref} type="email" inputMode="email" placeholder="name@company.com" value={val}
              onFocus={()=>setFoc(true)} onBlur={()=>{setFoc(false); if(val.trim()) add()}}
              onChange={e=>{setVal(e.target.value); if(err) setErr(null)}}
              onKeyDown={e=>{ if(e.key==='Enter'||e.key===','){ e.preventDefault(); add() } }}
              aria-label="Add someone by email"/>
            <button className="go" onClick={add}>Add</button>
          </div>
          {err ? <p className="msg">{err}</p> :
            <p className="gnote">Enter, or a comma, adds them. Up to {max} people besides you — they’ll get the invitation and the Meet link.</p>}
        </>
      ) : <p className="gnote">That’s the most this meeting takes. Anyone else can be added by replying to the invitation.</p>}
    </div>
  );
}
function Skeletons(){
  return (
    <div aria-hidden="true">
      <div className="sk line" style={{width:200,marginBottom:16}}></div>
      <div className="rail-wrap"><div className="rail">{[0,1,2,3,4,5,6].map(i=><div key={i} className="sk skday"></div>)}</div></div>
      <div className="sk line" style={{width:240,height:22,margin:'30px 0 18px'}}></div>
      <div className="sk line" style={{width:80,marginBottom:12}}></div>
      <div className="slots">{[0,1,2,3,4,5].map(i=><div key={i} className="sk skslot"></div>)}</div>
    </div>
  );
}
function StateBlock({ title, body, action, onAction }){
  return (
    <div className="state">
      <h3>{title}</h3>
      {body && <p>{body}</p>}
      {action && <button className="act" onClick={onAction}>{action}</button>}
    </div>
  );
}

/* ── timezone control ───────────────────────────────────────── */
function TzControl({ tz, setTz }){
  const [open,setOpen] = React.useState(false);
  const name = (CITIES.find(c=>c[1]===tz)||['Lagos'])[0];
  return (
    <>
      <button className="tzbtn" onClick={()=>setOpen(true)}>Times in {name} ({offsetLabel(tz)}) <span>change</span></button>
      {open && (
        <div className="scrim" onClick={()=>setOpen(false)}>
          <div className="sheet" role="dialog" aria-label="Choose a timezone" onClick={e=>e.stopPropagation()}>
            <div className="sheethead"><h3>Show times in</h3><button className="x" onClick={()=>setOpen(false)}>Close</button></div>
            <div className="tzl">
              {CITIES.map(([c,z])=>(
                <button key={z} className={'tzr'+(z===tz?' on':'')} onClick={()=>{setTz(z);setOpen(false)}}>
                  <span className="c">{c}</span><span>{offsetLabel(z)}{z===tz?' · current':''}</span>
                </button>
              ))}
            </div>
          </div>
        </div>
      )}
    </>
  );
}

/* ── month sheet ────────────────────────────────────────────── */
function MonthSheet({ days, monthOffset, selectedKey, onPick, onClose }){
  const [off,setOff] = React.useState(monthOffset);
  const base = new Date(); base.setDate(1); base.setMonth(base.getMonth()+off);
  const y = base.getFullYear(), m = base.getMonth();
  const first = new Date(Date.UTC(y,m,1)).getUTCDay();
  const lead = (first+6)%7;
  const total = new Date(Date.UTC(y,m+1,0)).getUTCDate();
  const map = {}; days.forEach(d=>map[d.key]=d);
  const cells = [];
  for(let i=0;i<lead;i++) cells.push(null);
  for(let d=1;d<=total;d++) cells.push(map[`${y}-${pad(m+1)}-${pad(d)}`] || { key:`x${d}`, d, slots:[] });
  return (
    <div className="scrim" onClick={onClose}>
      <div className="sheet" role="dialog" aria-label="Choose a date" onClick={e=>e.stopPropagation()}>
        <div className="sheethead">
          <h3>{MO[m]} {y}</h3>
          <div className="mnav">
            <button onClick={()=>setOff(o=>Math.max(0,o-1))} aria-label="Previous month">‹</button>
            <button onClick={()=>setOff(o=>Math.min(2,o+1))} aria-label="Next month">›</button>
            <button className="x" onClick={onClose}>Close</button>
          </div>
        </div>
        <div className="mgrid" role="grid">
          {['M','T','W','T','F','S','S'].map((h,i)=><div key={i} className="h">{h}</div>)}
          {cells.map((c,i)=> c===null ? <div key={i}></div> : (
            <button key={i} className={'mc'+(c.slots.length?'':' off')+(c.key===selectedKey?' sel':'')}
              disabled={!c.slots.length} onClick={()=>{onPick(c);onClose()}}
              aria-label={c.slots.length?`${c.d} ${MO[m]}, ${c.slots.length} times`:`${c.d} ${MO[m]}, no times`}>
              <span className="tnum">{c.d}</span>
              <i className="ind" style={{width: c.slots.length>4?18:c.slots.length>2?12:6}}></i>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ── the booking flow ───────────────────────────────────────── */
function Booking({ demo, tz, setTz }){
  const [typeId,setTypeId] = React.useState(demo.entry);
  const [step,setStep] = React.useState(demo.entry ? 'when' : 'select');
  const [dayKey,setDayKey] = React.useState(null);
  const [slotIso,setSlotIso] = React.useState(null);
  const [weekStart,setWeekStart] = React.useState(0);
  const [loading,setLoading] = React.useState(true);
  const [pending,setPending] = React.useState(false);
  const [taken,setTaken] = React.useState(false);
  const [month,setMonth] = React.useState(false);
  const [showAll,setShowAll] = React.useState(false);
  const [form,setForm] = React.useState({});
  const [guests,setGuests] = React.useState([]);
  const [errs,setErrs] = React.useState({});
  const [booked,setBooked] = React.useState(null);
  const live = React.useRef(null);

  const type = TYPES.find(t=>t.id===typeId);
  const closedKeys = React.useMemo(()=>{
    const s = new Set();
    if(demo.noWeek){ for(let i=0;i<7;i++){ const d=new Date(Date.now()+i*86400e3); s.add(`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`) } }
    return s;
  },[demo.noWeek]);
  const days = React.useMemo(()=> type ? buildDays(type, closedKeys) : [], [typeId, closedKeys]);
  const available = days.filter(d=>d.slots.length);
  const day = days.find(d=>d.key===dayKey) || null;
  const slot = slotIso ? new Date(slotIso) : null;

  React.useEffect(()=>{ // first availability load
    setLoading(true);
    const t = setTimeout(()=>setLoading(false), 850);
    return ()=>clearTimeout(t);
  },[typeId]);

  React.useEffect(()=>{ // land on the first day that has time
    if(loading || !type || dayKey || demo.noWeek) return;
    const first = available[0];
    if(first){ setDayKey(first.key); setWeekStart(Math.max(0, days.indexOf(first) - (days.indexOf(first)%7))) }
  },[loading,typeId,available.length]);

  React.useEffect(()=>{ if(type && type.prefill) setForm(f=>({ name:'Maya Iyer', email:'maya@studio.co', ...f })) },[typeId]);

  const week = days.slice(weekStart, weekStart+7);
  const weekCount = week.filter(d=>d.slots.length).length;
  const nextAvail = available.find(d=> days.indexOf(d) >= weekStart+7);

  function pickType(t){ setTypeId(t.id); setStep('when'); setDayKey(null); setSlotIso(null); setWeekStart(0); setTaken(false) }
  function pickDay(d){ setDayKey(d.key); setSlotIso(null); setTaken(false); setShowAll(false);
    const idx = days.findIndex(x=>x.key===d.key); if(idx>=0) setWeekStart(Math.max(0, idx - (idx%7)));
    if(live.current) live.current.textContent = `${longDay(d)} selected, ${d.slots.length} times available` }
  function pickSlot(s){ setSlotIso(s.toISOString()); setTaken(false);
    if(live.current) live.current.textContent = `${timeIn(s,tz)} selected` }

  function validate(){
    const e = {};
    if(!form.name || form.name.trim().length<2) e.name = 'I need a name for the invitation.';
    if(!form.email || !/^[^\s@]+@[^\s@]+\.[a-z]{2,}$/i.test(form.email)) e.email = 'That email looks incomplete — check for a missing dot or letter.';
    if(type.id==='kickoff' && !(form.k1||'').trim()) e.k1 = 'What are we starting?';
    setErrs(e); return !Object.keys(e).length;
  }
  function confirm(){
    if(step==='details' && !validate()){ if(live.current) live.current.textContent='Some details need a look'; return }
    setPending(true);
    setTimeout(()=>{
      setPending(false);
      if(demo.slotTaken){ setTaken(true); setSlotIso(null); setStep('when');
        if(live.current) live.current.textContent='That time went a moment ago'; return }
      setBooked({ type, slot, form, guests }); setStep('booked');
    }, 900);
  }
  const needsDetails = true;
  const goDetails = ()=> setStep('details');

  /* ---- calendar-down / invalid-link takeovers ---- */
  if(demo.badLink) return (
    <div className="pane single">
      <div className="sr" aria-live="polite"></div>
      <Mark/>
      <StateBlock title="This link isn’t active any more."
        body="The main booking page has everything that is — five conversations, same calendar."
        action="Go to booking page →" onAction={()=>demo.set({ badLink:false, entry:null })}/>
      <div className="divider"></div>
      <p className="hint">No error code, no dead end — every version of this state offers the one route that still works.</p>
    </div>
  );

  /* ---- confirmation ---- */
  if(step==='booked' && booked) return (
    <div className="pane single booked">
      <div className="sr" aria-live="polite" ref={live}></div>
      <div className="ghost" aria-hidden="true">e</div>
      <Mark who="Toni Dada"/>
      <div className="chk" aria-hidden="true"></div>
      <h1 className="big">You’re booked.</h1>
      <dl className="dl">
        <dt>Meeting</dt><dd>{booked.type.name}</dd>
        <dt>When</dt><dd className="tnum">{fmt(booked.slot,tz,{weekday:'long',day:'numeric',month:'long'})}, {timeIn(booked.slot,tz)}–{timeIn(new Date(booked.slot.getTime()+booked.type.dur*60e3),tz)}</dd>
        <dt>Timezone</dt><dd>{(CITIES.find(c=>c[1]===tz)||['Lagos'])[0]} ({offsetLabel(tz)}) — your local time</dd>
        <dt>Where</dt><dd>Google Meet · <span className="or">meet.google.com/rqx-jvhd-ktm</span></dd>
        <dt>Invitation</dt><dd>Sent to {booked.form.email}{booked.guests.length? ` and ${booked.guests.length} other${booked.guests.length>1?'s':''}`:''}</dd>
        {booked.guests.length>0 && <><dt>Also joining</dt><dd>{booked.guests.join(', ')}</dd></>}
      </dl>
      {booked.type.id==='brainstorm' && booked.form.q1 && (
        <div className="echo">
          <p className="h">What we’re thinking about</p>
          <p className="i">“{booked.form.q1}”</p>
          {booked.form.q3 && <p className="i">“{booked.form.q3}”</p>}
          <p className="n">I’ll read this before we meet.</p>
        </div>
      )}
      <div className="acts">
        <button className="act">Add to calendar</button>
        <button className="act">Move or cancel</button>
        <button className="act mut" onClick={()=>{ setBooked(null); setStep(demo.entry?'when':'select'); setSlotIso(null); setGuests([]); setForm(type.prefill?{name:'Maya Iyer',email:'maya@studio.co'}:{}) }}>Start again</button>
      </div>
    </div>
  );

  /* ---- left column ---- */
  const summary = step!=='select' && (
    <div className="sum">
      <div className="r"><dt>Meeting</dt><dd>{type.name}</dd>{!demo.entry && <button className="ch" onClick={()=>{setStep('select');setSlotIso(null)}}>change</button>}</div>
      <div className="r"><dt>Length</dt><dd className="tnum">{type.durLabel}</dd><span></span></div>
      {day && <div className="r"><dt>Day</dt><dd className="tnum">{longDay(day)}</dd><button className="ch" onClick={()=>setStep('when')}>change</button></div>}
      {slot && <div className="r"><dt>Time</dt><dd className="tnum">{timeIn(slot,tz)} · {(CITIES.find(c=>c[1]===tz)||['Lagos'])[0]}</dd><button className="ch" onClick={()=>{setStep('when');setSlotIso(null)}}>change</button></div>}
    </div>
  );

  const left = (
    <div className="L">
      <Mark who={step==='select' ? undefined : 'Toni Dada'}/>
      {type && type.kicker && step!=='select' && <p className="kick">{type.kicker}</p>}
      {step==='select'
        ? <><h1>Let’s find<br/>some <em>time</em>.</h1><p className="lede">Pick one, and I’ll make the time.</p></>
        : <>{!demo.entry && (
             <button className="backlink" onClick={()=>{setStep('select');setSlotIso(null);setDayKey(null);setTaken(false)}}>
               <span aria-hidden="true">←</span> Back
             </button>)}
           <h1 className={type.head.join(' ').length>18?'sm2':''}>{type.head.map((l,i)=><React.Fragment key={i}>{i?<br/>:null}{l}</React.Fragment>)}</h1>
           <p className="meta"><b className="tnum">{type.durLabel}</b><span>·</span><span>{type.who}</span></p>
           <p className="lede">{type.lede}</p>
           {demo.entry && <p className="altlink">Not the right conversation? <a href="#" onClick={e=>{e.preventDefault();demo.set({badLink:false})}}>See all five →</a></p>}</>}
      {step==='select' && (
        <div className="list" role="list">
          {TYPES.map(t=>(
            <button key={t.id} className="mrowb" role="listitem" onClick={()=>pickType(t)}>
              <span className="tx"><span className="n">{t.name}</span><span className="d">{t.line}</span></span>
              <span className="dur tnum">{t.durLabel}<i>→</i></span>
            </button>
          ))}
        </div>
      )}
      {summary}
      <div className="foot"><TzControl tz={tz} setTz={setTz}/><span>toni@enterscale.com</span></div>
    </div>
  );

  /* ---- right column ---- */
  let right;
  if(demo.calDown){
    right = <div className="R"><div className="step mut">Availability</div>
      <StateBlock title="I can’t reach my calendar right now."
        body="So I can’t show you real times — showing times that might be wrong is worse than showing none. Try again in a minute; I’m retrying in the background too."
        action="Try again" onAction={()=>demo.set({calDown:false})}/>
    </div>;
  } else if(step==='when'){
    const flat = type.flat && !showAll;
    const soonest = available.flatMap(d=>d.slots.map(s=>({d,s}))).slice(0,6);
    right = (
      <div className="R">
        <div className="step">{demo.entry?'':'Step 2 — '}{flat?'Soonest six':'Pick a day'}</div>
        {loading ? <Skeletons/> : flat ? (
          <>
            <p className="avail">Next available <b className="tnum">{soonest.length?`${shortDay(soonest[0].d)} at ${timeIn(soonest[0].s,tz)}`:'—'}</b></p>
            <div className="slots flat">
              {soonest.map(({d,s})=>(
                <button key={s.toISOString()} className={'slot wide'+(slotIso===s.toISOString()?' sel':'')} onClick={()=>{setDayKey(d.key);pickSlot(s)}}>
                  <span>{shortDay(d)}</span><span className="tnum">{timeIn(s,tz)}</span>
                </button>
              ))}
            </div>
            <button className="disc" onClick={()=>setShowAll(true)}>See all days ⌄</button>
          </>
        ) : (
          <>
            <p className="avail">
              <b>{MO[week[0].m]} {week[0].y}</b> · {weekCount ? `${weekCount} day${weekCount>1?'s':''} with time this week` : 'nothing open this week'}
              <button className="disc inline" onClick={()=>setMonth(true)}>view month ⌄</button>
            </p>
            <div className="rail-wrap">
              <button className="wnav" onClick={()=>setWeekStart(w=>Math.max(0,w-7))} disabled={weekStart===0} aria-label="Previous week">‹</button>
              <div className="rail" role="listbox" aria-label="Choose a day">
                {week.map(d=>{
                  const isToday = d.key === ownerDate(new Date(Date.now()+OWNER_OFFSET*3600e3));
                  return (
                    <button key={d.key} role="option" aria-selected={d.key===dayKey} disabled={!d.slots.length}
                      className={'day'+(d.slots.length?'':' off')+(d.key===dayKey?' sel':'')}
                      onClick={()=>pickDay(d)}
                      aria-label={`${longDay(d)}, ${d.slots.length?d.slots.length+' times available':'no times'}`}>
                      <span className="wd">{isToday?'Today':WD[d.wd]}</span>
                      <span className="dd tnum">{d.d}</span>
                      <i className="ind" style={{width: d.slots.length>4?18:d.slots.length>2?12:6, opacity:d.slots.length?1:0}}></i>
                    </button>
                  );
                })}
              </div>
              <button className="wnav" onClick={()=>setWeekStart(w=>Math.min(days.length-7,w+7))} aria-label="Next week">›</button>
            </div>
            {taken && <StateBlock title="That time went a moment ago." body="Here’s what’s still open. I’ve left the rest of your choices where they were."/>}
            {!weekCount ? (
              <StateBlock title="Nothing open this week."
                body={nextAvail ? `The next time I have is ${longDay(nextAvail)} — ${nextAvail.slots.length} slots.` : 'My calendar is full through the end of the window. Email me and we’ll find something.'}
                action={nextAvail ? `Jump to ${shortDay(nextAvail)} →` : 'Email toni@enterscale.com →'}
                onAction={()=>nextAvail && pickDay(nextAvail)}/>
            ) : day && day.slots.length ? (
              <>
                <div className="dayhead"><h2>{longDay(day)}</h2><span>{day.slots.length} time{day.slots.length>1?'s':''}</span></div>
                {['Morning','Afternoon','Evening'].map(g=>{
                  const list = day.slots.filter(s=>groupOf(s,tz)===g);
                  if(!list.length) return null;
                  return (
                    <React.Fragment key={g}>
                      <div className="grouplbl">{g}</div>
                      {list.length===1 && <p className="hint one">One time left {g.toLowerCase()==='morning'?'in the morning':'that '+g.toLowerCase()}.</p>}
                      <div className={'slots'+(list.length===1?' loose':'')} role="radiogroup" aria-label={longDay(day)+' '+g}>
                        {list.map(s=>{
                          const on = slotIso===s.toISOString();
                          return <button key={s.toISOString()} role="radio" aria-checked={on}
                            className={'slot tnum'+(on?' sel':'')+(slotIso&&!on?' dim':'')} onClick={()=>pickSlot(s)}>
                            {timeIn(s,tz)}{type.dur>=90?` – ${timeIn(new Date(s.getTime()+type.dur*60e3),tz)}`:''}
                          </button>;
                        })}
                      </div>
                    </React.Fragment>
                  );
                })}
              </>
            ) : <StateBlock title="Pick a day above." body="Days without a rule under them have nothing open."/>}
          </>
        )}
        {slot && (
          <div className="commit">
            <p className="ctanote">Holding {timeIn(slot,tz)} for the next ten minutes. Nothing is booked until you confirm.</p>
            <button className="cta" onClick={goDetails}>{type.id==='brainstorm'?'Continue — three short questions →':`Continue — ${shortDay(day)}, ${timeIn(slot,tz)} →`}</button>
          </div>
        )}
        {month && <MonthSheet days={days} monthOffset={0} selectedKey={dayKey} onPick={pickDay} onClose={()=>setMonth(false)}/>}
      </div>
    );
  } else if(step==='details'){
    const F = (k,props)=> <Field {...props} value={form[k]||''} onChange={v=>setForm(f=>({...f,[k]:v}))}
      onBlur={()=>{ if(errs[k]) validate() }} error={errs[k]}/>;
    right = (
      <div className="R">
        <div className="step">{type.id==='brainstorm'?'Step 3 — So I arrive prepared':'Step 3 — Who’s coming'}</div>
        {type.id==='brainstorm' && <p className="frame1">If you already know what you want to think about, tell me and I’ll come prepared. If I called this one, leave it blank.</p>}
        {type.prefill
          ? <div className="prefill">Booking as <b>{form.name}</b> · {form.email} <button className="ch" onClick={()=>setForm(f=>({...f,name:'',email:''}))}>change</button></div>
          : <>{F('name',{label:'Your name', autoComplete:'name', autoFocus:true})}
             {F('email',{label:'Email', type:'email', inputMode:'email', autoComplete:'email'})}</>}
        {type.id==='discovery' && F('company',{label:'Company', optional:true, placeholder:'Where you work'})}
        {type.id==='brainstorm' && <>
          {F('q1',{label:'What would you like to brainstorm?', optional:true, textarea:true, placeholder:'e.g. how to position a second product without confusing the customers we already have'})}
          {F('q2',{label:'What’s the context?', optional:true, textarea:true, placeholder:'Where you are, what you’ve tried, what’s constraining it.'})}
          {F('q3',{label:'What would make this session useful?', optional:true, textarea:true, placeholder:'A decision, a direction, a shortlist — whatever you’d want to leave with.'})}
        </>}
        {type.id==='kickoff' && F('k1',{label:'What are we starting?', textarea:true, placeholder:'One or two lines on the project.'})}
        {type.id==='checkin' && F('agenda',{label:'Anything you’d like on the agenda?', optional:true, textarea:true, placeholder:'Two or three bullets is perfect.'})}
        {type.id!=='quick' && <Guests guests={guests} setGuests={setGuests} hostEmail={form.email} max={type.id==='kickoff'?6:4}/>}
        <div className="commit">
          <p className="ctanote">{Object.keys(errs).length ? `${Object.keys(errs).length===1?'One detail needs':Object.keys(errs).length+' details need'} a look before I can book it.`
            : `Holding ${timeIn(slot,tz)} · ${type.durLabel}${guests.length?` · ${guests.length+1} attending`:''} · ${(CITIES.find(c=>c[1]===tz)||['Lagos'])[0]}`}</p>
          <button className={'cta'+(pending?' pending':'')} disabled={pending} onClick={confirm}>
            {pending ? 'Booking…' : `Book ${shortDay(day)} ${MO[day.m].slice(0,3)}, ${timeIn(slot,tz)} →`}
          </button>
        </div>
      </div>
    );
  } else {
    right = <div className="R"><div className="step mut">Step 2 — When works for you?</div>
      <p className="hint">Pick a conversation and I’ll show you the days that have time.</p></div>;
  }

  return <div className="pane split">{left}{right}<div className="sr" aria-live="polite" ref={live}></div></div>;
}

Object.assign(window, { Booking, TYPES, CITIES, Mark, offsetLabel, StateBlock });
