/* Exported Promotions workspace, backed by recorded promotions and sales. */
(function () {
  const {useState,useEffect} = React;
  const cash = n => n == null ? '—' : '$' + (n/100).toLocaleString('en-AU',{minimumFractionDigits:2,maximumFractionDigits:2});
  const pct = n => n == null ? '—' : (n>0?'+':'') + Number(n).toFixed(1) + '%';
  const date = s => s ? String(s).slice(0,10).split('-').reverse().join('/') : '—';
  const days = (a,b) => Math.round((Date.parse(b)-Date.parse(a))/86400000);
  const addDays = (s,n) => new Date(Date.parse(s+'T00:00:00Z')+n*86400000).toISOString().slice(0,10);
  const I = props => <window.OIcon {...props}/>;
  const K = props => <window.KpiCard {...props}/>;
  const Note = ({children}) => <div className="pc-note"><I name="info"/><div>{children}</div></div>;
  const Empty = ({children}) => <div className="xp-empty">{children}</div>;
  const State = ({value}) => {const tones={live:'paid',scheduled:'brand',draft:'hold',paused:'void',ended:'flat',cancelled:'flat'};return <span className={'badge badge--'+(tones[value]||'flat')}><span className="badge-dot"/>{value ? value[0].toUpperCase()+value.slice(1) : 'Unknown'}</span>;};
  const Where = ({where}) => <span className={'pg-where pg-where--'+where}>{where==='basket'?'Register rule':'Shelf price'}</span>;
  function Card({title,sub,children,className=''}) {return <section className={'off-table pg-card '+className}><div className="pg-card-h">{title}</div>{sub&&<div className="pg-card-s">{sub}</div>}{children}</section>;}
  function Table({heads,columns,children}) {return <div className="pg-live-table-wrap"><div className="off-grid" style={{gridTemplateColumns:columns}}>{heads.map((h,i)=><div key={i} className="off-grid-headcell">{h}</div>)}{children}</div></div>;}
  const Cell = ({children,num=false}) => <div className={'off-grid-cell'+(num?' off-cell-num':'')} style={{whiteSpace:'normal'}}>{children}</div>;
  function All({d,open,create}) {
    const [filter,setFilter]=useState('live');
    const all=d.promotions||[], live=all.filter(p=>p.state==='live'), funded=all.filter(p=>p.funded);
    const filters=[['live','Live',p=>p.state==='live'],['scheduled','Scheduled',p=>p.state==='scheduled'],['paused','Paused',p=>p.state==='paused'],['draft','Draft',p=>p.state==='draft'],['ended','Ended',p=>['ended','cancelled'].includes(p.state)],['basket','Register rules',p=>p.where==='basket'],['funded','Supplier funded',p=>!!p.funded],['all','Everything',()=>true]];
    const shown=all.filter(filters.find(f=>f[0]===filter)[2]);
    const start=addDays(d.today,-7), visible=all.filter(p=>!['draft','cancelled'].includes(p.state)&&days(start,p.endsOn)>=0&&days(start,p.startsOn)<42);
    return <>
      <div className="off-kpi-grid"><K label="Live now" value={live.length} delta={{text:live.filter(p=>p.where==='basket').length+' are register rules, not shelf prices'}}/><K label="Ending within 7 days" value={live.filter(p=>days(d.today,p.endsOn)<=7).length} delta={{text:'The recorded base price resumes when the offer ends'}}/><K label="Supplier funded" value={funded.length} delta={{text:'Claim amounts require recorded redemption evidence'}}/><K label="From the expiry ladder" value={d.clearanceCount??'—'} delta={{text:d.clearanceCount==null?'Promotion origin is not recorded':'Reported separately from marketing offers'}}/></div>
      <div className="off-table pg-cal"><div className="pg-cal-h"><div><div className="pg-card-h">Six weeks out</div><div className="pg-card-s">Dates and overlaps across recorded promotions. Open a bar to inspect its offer.</div></div></div><div className="pg-weeks">{Array.from({length:6},(_,i)=><div className="pg-week" key={i}>{date(addDays(start,i*7)).slice(0,5)}</div>)}</div><div className="pg-track"><div className="pg-today" style={{left:(100/6)+'%'}}><span>today</span></div>{visible.map(p=>{const a=Math.max(0,days(start,p.startsOn)),b=Math.min(42,days(start,p.endsOn)+1);return <div className="pg-bar-row" key={p.id}><button className={'pg-bar pg-bar--'+p.state} title={p.name+' · '+date(p.startsOn)+' – '+date(p.endsOn)} style={{left:a/42*100+'%',width:Math.max(1,b-a)/42*100+'%'}} onClick={()=>open(p)}><span>{p.name}</span></button></div>;})}{!visible.length&&<Empty>Nothing scheduled or live in this window.</Empty>}</div></div>
      <div className="off-table"><div className="off-table-toolbar"><div className="off-filters">{filters.map(([id,label,pred])=><button key={id} className={'off-filter'+(filter===id?' off-filter--active':'')} onClick={()=>setFilter(id)}>{label}<span className="off-filter-count">{all.filter(pred).length}</span></button>)}</div><button className="btn btn--primary btn--sm" style={{marginLeft:'auto'}} onClick={create}><I name="plus"/> New promotion</button></div>
        <Table heads={['Promotion','Mechanic','Applies to','Stores','Runs','Delivered as','State','']} columns="minmax(210px,1.6fr) 150px 130px minmax(150px,1fr) 120px 128px 110px 96px">{shown.map(p=><div className="off-grid-row" key={p.id} onClick={()=>open(p)}><Cell><b>{p.name}</b>{p.funded&&<span className="pg-fund">funded</span>}<small className="pg-live-muted">{p.id}</small></Cell><Cell>{p.mechanicLabel}<small className="pg-live-muted">{p.say}</small></Cell><Cell><span className="pg-live-scope">{p.scopeKind==='all'?'Group':p.scopeKind}</span><small className="pg-live-muted">{p.scopeLabel}</small></Cell><Cell>{p.siteName||d.siteName||'Organisation'}</Cell><Cell>{date(p.startsOn)} – {date(p.endsOn)}{p.state==='live'&&<small className="pg-live-muted">{days(d.today,p.endsOn)} days left</small>}</Cell><Cell><Where where={p.where}/></Cell><Cell><State value={p.state}/></Cell><Cell><button className="btn btn--secondary btn--sm" onClick={e=>{e.stopPropagation();open(p);}}>Open</button></Cell></div>)}</Table>{!shown.length&&<Empty>{all.length?'Nothing matches that filter.':'No promotions yet. Create a draft to begin.'}</Empty>}
      </div>
    </>;
  }
  function Register({d,open}) {
    const [lines,setLines]=useState([]),[options,setOptions]=useState([]),[query,setQuery]=useState(''),[result,setResult]=useState(null),[error,setError]=useState(null),[busy,setBusy]=useState(false);
    useEffect(()=>{let alive=true;window.OfficeAPI.promotionScopeOptions().then(o=>{if(alive)setOptions(o.products||[]);}).catch(e=>{if(alive)setError(e.message);});return()=>{alive=false;};},[]);
    useEffect(()=>{let alive=true;if(!lines.length){setResult(null);setBusy(false);return;}setBusy(true);setResult(null);const t=setTimeout(()=>window.OfficeAPI.simulatePromotions({siteId:d.siteId,lines}).then(x=>{if(alive){setResult(x);setError(null);}}).catch(e=>{if(alive)setError(e.message);}).finally(()=>{if(alive)setBusy(false);}),150);return()=>{alive=false;clearTimeout(t);};},[JSON.stringify(lines),d.siteId]);
    const live=(d.promotions||[]).filter(p=>p.state==='live'),prices=live.filter(p=>p.where==='price'),rules=live.filter(p=>p.where==='basket');
    const add=id=>{setLines(prev=>prev.some(l=>l.productId===id)?prev.map(l=>l.productId===id?{...l,qty:l.qty+1}:l):[...prev,{productId:id,qty:1}]);setQuery('');};
    const change=(id,delta)=>setLines(prev=>prev.map(l=>l.productId===id?{...l,qty:l.qty+delta}:l).filter(l=>l.qty>0));
    return <><Note>Price offers are stored as promotion prices; supported basket offers are stored as rules. This view reads the publication records and simulates the supported register calculations.</Note><div className="pg-till"><div className="pg-tcol">
      <Card title={'Prices published · '+(d.siteName||'current scope')} sub="Recorded publication state; terminal delivery is not acknowledged here."><div className="pg-plist">{prices.map(p=><div className="pg-pitem" key={p.id}><div><button className="pg-linkbtn" onClick={()=>open(p)}>{p.name}</button><div className="pg-pitem-s">{p.lineCount} lines · {p.say}</div></div><Where where="price"/></div>)}{!prices.length&&<Empty>No live price promotions.</Empty>}</div></Card>
      <Card title="Rules the till evaluates" sub="The published rules supported by the current register release."><div className="pg-plist">{rules.map(p=><div className="pg-pitem" key={p.id}><div><button className="pg-linkbtn" onClick={()=>open(p)}>{p.name}</button><div className="pg-pitem-s">{p.say}</div>{p.prompt&&<div className="pg-prompt">{p.prompt}</div>}</div><Where where="basket"/></div>)}{!rules.length&&<Empty>No live basket rules.</Empty>}</div><div className="pg-offline"><I name="info"/><span>{d.till?.note||'Publication records are available; individual register delivery acknowledgements are not.'}</span></div></Card>
      <Card title="Where each live promotion is intended to appear"><Table heads={['Promotion','ESL','Ticket','Display','Online','Catalogue','Prompt']} columns="minmax(150px,1.5fr) repeat(6,60px)">{live.map(p=><div className="off-grid-row" key={p.id}><Cell>{p.name}</Cell>{['esl','ticket','cfd','online','cat','prompt'].map(c=><Cell key={c}><span className={'xp-yn '+((p.channels||[]).includes(c)?'is-y':'is-n')}><I name={(p.channels||[]).includes(c)?'check':'x'} width={10}/></span></Cell>)}</div>)}</Table><div className="pg-card-s">Selected channels describe intent; they do not prove delivery.</div></Card>
    </div><div className="pg-tcol"><Card title="What the register would do" sub="Choose real products and change quantities to inspect the supported rules." className="pg-basket">
      <label className="pg-live-field">Add a product<input className="input" aria-label="Find basket product" placeholder="Product name or SKU…" value={query} onChange={e=>setQuery(e.target.value)}/></label>{query.trim()&&<div className="pg-add">{options.filter(p=>(p.name+' '+(p.sku||'')).toLowerCase().includes(query.toLowerCase())).slice(0,8).map(p=><button key={p.id} onClick={()=>add(p.id)}>{p.name}</button>)}</div>}
      {error&&<Note>{error}</Note>}{busy&&<div role="status" className="pg-card-s">Evaluating the current basket…</div>}
      <div className="pg-blines">{lines.map(l=>{const r=result?.lines?.find(x=>x.productId===l.productId),p=options.find(x=>x.id===l.productId);return <div className="pg-bline" key={l.productId}><div className="pg-bqty"><button aria-label={'Remove one '+(p?.name||l.productId)} onClick={()=>change(l.productId,-1)}><I name="minus" width={12}/></button><span>{l.qty}</span><button aria-label={'Add one '+(p?.name||l.productId)} onClick={()=>change(l.productId,1)}><I name="plus" width={12}/></button></div><div style={{flex:1}}><div className="pg-bline-n">{r?.name||p?.name||l.productId}</div><div className="pg-bline-s">{r?cash(r.unitCents)+' each':'Awaiting calculation'}</div></div><div className="pg-bline-v"><strong>{busy?'…':cash(r?.totalCents)}</strong></div></div>;})}{!lines.length&&<Empty>Add a product to start a basket.</Empty>}</div>
      <div className="pg-events">{(result?.appliedRules||[]).map((r,i)=><div className="pg-event pg-event--rule" key={r.id||i}><I name="box"/><div><div className="pg-event-n">{r.name||r.description||'Basket rule'}</div><div className="pg-event-s">{r.note||r.ruleId}</div></div><strong>{cash(r.discountCents??r.savedCents)}</strong></div>)}</div>
      <div className="pg-total"><div><span>Before promotions</span><strong>{cash(result?.subtotalCents)}</strong></div><div><span>Saved</span><strong>{cash(result?.discountCents)}</strong></div><div className="pg-total-g"><span>To pay</span><strong>{cash(result?.totalCents)}</strong></div></div>{(result?.limitations||[]).map((n,i)=><div className="pg-receipt-note" key={i}>{n}</div>)}
    </Card></div></div></>;
  }
  function Overlaps({d,open}) {
    const c=d.conflicts||{},s=c.counts||{},rows=c.rows||[];
    return <><div className="off-kpi-grid"><K label="Lines with more than one promotion" value={s.overlapping??rows.length} delta={{text:d.siteName||'Current scope'}}/><K label="Two shelf prices competing" value={s.price??0} delta={{text:'Inspect publication ownership before changing an offer'}}/><K label="Price plus a register rule" value={s.mixed??0} delta={{text:'Separate publication fields and calculations'}}/><K label="Below the cost floor" value={s.belowCost??'—'} delta={{text:'Only where a recorded unit cost is available'}}/></div><Note>{c.policy||'Overlaps use the current publication model.'}</Note><div className="pg-clashes">{rows.map((r,i)=><Card key={r.productId||i} title={r.name||r.productName||'Product'} sub={(r.sku||'')+' · '+cash(r.beforeCents)}><div className="pg-cands">{(r.candidates||r.promotions||[]).map(p=><div key={p.id||p.promotionId} className={'pg-cand'+(p.winner?' is-win':'')}><span className="pg-cand-b">{p.where==='basket'?'basket':'snapshot'}</span><div style={{flex:1}}><button className="pg-linkbtn" onClick={()=>open({id:p.id||p.promotionId})}>{p.name}</button><div className="pg-cand-s">{p.say||p.where}</div></div><strong>{cash(p.priceCents??p.promoCents)}</strong></div>)}</div><div className="xp-note">Current stored unit price: {cash(r.effectiveCents)}{r.belowCost ? " · below recorded cost floor " + cash(r.floorCents) : ""}. {(r.trace||[]).join(" ")}{r.note||""}</div></Card>)}</div>{!rows.length&&<Empty>No overlapping publication records in this scope.</Empty>}</>;
  }
  function Group({d,open}) {
    const [tab,setTab]=useState('stores'),g=d.group||{},sites=g.sites||[];
    const tabs=[['stores','By store'],['diverge','Price divergence'],['risk','Funding at risk'],['patchy','Uneven coverage']];
    const active=(d.promotions||[]).filter(p=>['live','scheduled'].includes(p.state));
    return <><div className="off-kpi-grid"><K label="Live across the group" value={active.filter(p=>p.state==='live').length} delta={{text:sites.length+' authorised stores'}}/><K label="Lines priced differently between stores" value={g.divergence?.length??'—'} delta={{text:'Requires independently stored site prices'}}/><K label="Co-op claims at risk" value={g.fundingAtRisk?.length??'—'} delta={{text:'Requires recorded redemption attribution'}}/><K label="Group GP given up per unit" value={cash(g.givenUpCents)} delta={{text:'Only when the promoted unit basket is measurable'}}/></div><Note>{g.note||'Promotion ownership and the price-delivery scope are shown separately.'}</Note><div className="off-table"><div className="off-table-toolbar"><div className="off-filters">{tabs.map(([k,l])=><button key={k} className={'off-filter'+(tab===k?' off-filter--active':'')} onClick={()=>setTab(k)}>{l}</button>)}</div></div>
      {tab==='stores'?<Table heads={['Store','Live','Scheduled','Funded','Publication scope']} columns="minmax(180px,1fr) 100px 100px 100px minmax(250px,1.4fr)">{sites.map(s=><div className="off-grid-row" key={s.siteId}><Cell><b>{s.siteName}</b></Cell><Cell num>{s.liveCount??0}</Cell><Cell num>{s.scheduledCount??0}</Cell><Cell num>{s.fundedCount??0}</Cell><Cell>Promotion owner · price profiles apply across the organisation</Cell></div>)}</Table>:tab==='patchy'?<><Table heads={['Promotion','Owning store','State','']} columns="minmax(240px,1.6fr) minmax(180px,1fr) 120px 96px">{active.map(p=><div className="off-grid-row" key={p.id}><Cell>{p.name}</Cell><Cell>{p.siteName||p.siteId}</Cell><Cell><State value={p.state}/></Cell><Cell><button className="btn btn--secondary btn--sm" onClick={()=>open(p)}>Open</button></Cell></div>)}</Table>{!active.length&&<Empty>No live or scheduled promotions.</Empty>}</>:<Empty>{tab==='diverge'?'Independent store promotion prices are not recorded by the current organisation-wide profile model.':'Recorded sales do not identify which funded promotion won, so realised funding loss cannot be calculated.'}</Empty>}
    </div></>;
  }
  function Performance({d,open}) {
    const p=d.performance||{},rows=p.rows||[],s=p.summary||{},measured=rows.filter(r=>r.gpDeltaCents!=null),best=measured.slice().sort((a,b)=>b.gpDeltaCents-a.gpDeltaCents)[0];
    return <><div className="off-kpi-grid"><K label="Promotions in profit" value={measured.length?measured.filter(r=>r.gpDeltaCents>0).length+' of '+measured.length:'—'} delta={{text:'Measured scope GP versus the stated baseline'}}/><K label="Net GP effect" value={cash(s.gpDeltaCents)} delta={{text:'Comparison only; not a causal lift estimate'}}/><K label="Best performer" value={cash(best?.gpDeltaCents)} delta={{text:best?.name||'No measured comparison yet'}}/><K label="Clearance recovered" value={cash(s.clearanceRecoveredCents)} delta={{text:'Clearance origin is not recorded'}}/></div><Card title="Baseline method" sub="The comparison uses recorded sales before each promotion, scaled to its measured duration."><div className="pg-bmethods"><button className="pg-bm is-on" aria-pressed="true"><div className="pg-bm-l">Trailing eight weeks</div><div className="pg-bm-d">Daily rate across the 56 days before the promotion.</div></button></div><div className="xp-note">{p.basisNote}</div></Card>
      <div className="off-table"><div className="off-table-toolbar"><b>Against trailing eight weeks</b></div><Table heads={['Promotion','Units','Baseline','Unit lift','GP','GP vs baseline','Read']} columns="minmax(210px,1.6fr) 110px 110px 110px 120px 120px minmax(180px,1.1fr)">{rows.map(r=><div className="off-grid-row" key={r.promotionId}><Cell><button className="pg-linkbtn" onClick={()=>open({id:r.promotionId})}>{r.name||d.promotions.find(p=>p.id===r.promotionId)?.name}</button><small className="pg-live-muted">{date(r.period?.from)} – {date(r.period?.to)}</small></Cell><Cell num>{r.scopeUnits??'—'}</Cell><Cell num>{r.baselineUnits==null?'—':Number(r.baselineUnits).toFixed(1)}</Cell><Cell num>{pct(r.liftPct)}</Cell><Cell num>{cash(r.recordedGpCents)}</Cell><Cell num>{cash(r.gpDeltaCents)}</Cell><Cell>{r.note||'Sales in scope during the offer; not verified promotion redemptions.'}</Cell></div>)}</Table>{!rows.length&&<Empty>No promotion period has recorded sales to compare yet.</Empty>}</div></>;
  }
  function Funding({d,refresh}) {
    const f=d.funding||{},s=f.summary||{},rows=f.rows||[];
    const [selected,setSelected]=useState(null),[status,setStatus]=useState('open'),[amount,setAmount]=useState(''),[units,setUnits]=useState(''),[reference,setReference]=useState(''),[note,setNote]=useState(''),[busy,setBusy]=useState(false),[error,setError]=useState(null);
    const edit=r=>{setSelected(r);setStatus(r.record?.status||'open');setAmount(r.record?.amountCents==null?'':String(r.record.amountCents/100));setUnits(r.record?.units==null?'':String(r.record.units));setReference(r.record?.reference||'');setNote(r.record?.note||'');setError(null);};
    const save=async()=>{if(!amount.trim()||!Number.isFinite(Number(amount))||Number(amount)<0){setError('Enter the documented claim amount.');return;}if(!note.trim()){setError('Add a note identifying the supporting evidence.');return;}setBusy(true);setError(null);try{await window.OfficeAPI.savePromotionFundingRecord(selected.promotionId,{revision:selected.record?.revision??selected.revision??'default',status,amountCents:Math.round(Number(amount)*100),units:units===''?null:Number(units),reference:reference||null,note:note||null});setSelected(null);refresh();}catch(e){setError(e.message);}finally{setBusy(false);}};
    return <><div className="off-kpi-grid"><K label="Claimable" value={cash(s.claimableCents)} delta={{text:'Requires evidence of eligible redemptions'}}/><K label="Not yet claimed" value={cash(s.recordedOpenCents)} delta={{text:'Amounts entered from supporting documents'}}/><K label="Submitted" value={cash(s.recordedSubmittedCents)} delta={{text:'Recorded submissions awaiting receipt'}}/><K label="Received" value={cash(s.recordedReceivedCents)} delta={{text:'Manually recorded credits or payments'}}/></div><Note>{f.basisNote}</Note><div className="off-table"><div className="off-table-toolbar"><b>Co-op deals</b></div><Table heads={['Promotion','Supplier','Deal ref','They fund','Scope units','Claim value','State','']} columns="minmax(200px,1.5fr) 130px 120px 100px 110px 120px 130px 110px">{rows.map(r=><div className="off-grid-row" key={r.promotionId}><Cell><b>{r.name||d.promotions.find(p=>p.id===r.promotionId)?.name}</b></Cell><Cell>{r.supplier}</Cell><Cell>{r.ref||'—'}</Cell><Cell num>{cash(r.perCents)}</Cell><Cell num>{r.scopeUnits??'—'}</Cell><Cell num>{cash(r.record?.amountCents)}</Cell><Cell>{r.record?.status||'No claim recorded'}</Cell><Cell><button className="btn btn--secondary btn--sm" onClick={()=>edit(r)}>Record claim</button></Cell></div>)}</Table>{!rows.length&&<Empty>No supplier-funded promotions in this scope.</Empty>}</div>
      {selected&&<div className="pg-live-modal-backdrop"><section role="dialog" aria-modal="true" aria-label="Record supplier claim" className="off-table pg-card pg-live-modal"><div className="off-card-header"><h3 className="off-card-title">Record supplier claim</h3><button className="btn btn--ghost btn--sm" disabled={busy} onClick={()=>setSelected(null)}>Close</button></div><Note>This records a claim you have documented. It does not send a claim or create a supplier credit.</Note><fieldset disabled={busy} className="pg-live-form"><label>Status<select className="input" value={status} onChange={e=>setStatus(e.target.value)}><option value="open">Not yet claimed</option><option value="submitted">Submitted</option><option value="received">Received</option></select></label><label>Documented amount ($)<input className="input" type="number" min="0" step=".01" value={amount} onChange={e=>setAmount(e.target.value)}/></label><label>Eligible units (optional)<input className="input" type="number" min="0" step="1" value={units} onChange={e=>setUnits(e.target.value)}/></label><label>Claim or credit reference<input className="input" value={reference} onChange={e=>setReference(e.target.value)}/></label><label>Evidence / note<textarea className="input" value={note} onChange={e=>setNote(e.target.value)}/></label>{error&&<div role="alert">{error}</div>}<button className="btn btn--primary btn--sm" onClick={save}>{busy?'Saving…':'Save record'}</button></fieldset></section></div>}
    </>;
  }
  function PromotionsWorkspace() {
    const {setScreen,setScreenState,screenState={},stores=[],activeStoreId}=window.useOffice();
    const [tab,setTab]=useState(screenState.promotionTab||'all'),[d,setData]=useState(null),[error,setError]=useState(null),[busy,setBusy]=useState(true),[reload,setReload]=useState(0),[delivery,setDelivery]=useState(false);
    useEffect(()=>{let alive=true;setBusy(true);setError(null);window.OfficeAPI.promotionsWorkspace({siteId:activeStoreId||undefined}).then(x=>{if(alive)setData(x);}).catch(e=>{if(alive)setError(e.message||'Could not load promotions.');}).finally(()=>{if(alive)setBusy(false);});return()=>{alive=false;};},[reload,activeStoreId]);
    const open=p=>{setScreenState(s=>({...s,promotionId:p.id}));setScreen('promotionDetail');};
    const create=()=>{setScreenState(s=>({...s,promotionEditId:null,promotionRerunOf:null}));setScreen('promotionNew');};
    const print=()=>{setScreenState(s=>({...s,promotionTicketId:null}));setScreen('promoTickets');};
    const tabs=[['all','All promotions'],['till','At the register'],['clash','Overlaps'],['group','Across the group'],['perf','Did it work'],['fund','Supplier funding']];
    const Body={all:All,till:Register,clash:Overlaps,group:Group,perf:Performance,fund:Funding}[tab];
    return <div className="off-screen off-promotions-screen"><header className="off-screen-header"><div className="off-screen-header-meta"><span className="off-screen-eyebrow">Pricing · {d?.siteName||stores.find(s=>s.id===activeStoreId)?.name||'current organisation'}</span><h2 className="off-screen-title">Promotions</h2><div className="off-muted" style={{fontSize:13,marginTop:4}}>Authored here, run at the register. Some promotions are a price, others are a rule the till evaluates against the whole basket.</div></div><div className="off-screen-actions"><button className="btn btn--ghost btn--sm" onClick={print}><I name="printer"/> Print tickets</button><button className="btn btn--secondary btn--sm" onClick={()=>{setDelivery(v=>!v);setReload(k=>k+1);}}><I name="transfer"/> Register status</button></div></header><nav className="off-subtabs" aria-label="Promotions">{tabs.map(([k,l])=><button key={k} className={'off-subtab'+(tab===k?' off-subtab--active':'')} aria-current={tab===k?'page':undefined} onClick={()=>{setTab(k);setScreenState(s=>({...s,promotionTab:k}));}}>{l}</button>)}</nav><div className="off-screen-body off-promotions-body">{error&&<div role="alert"><Note>{error}</Note><button className="btn btn--secondary btn--sm" onClick={()=>setReload(k=>k+1)}>Retry</button></div>}{busy&&<div role="status" className="pg-card-s">Loading recorded promotions…</div>}{delivery&&<Note>{d?.till?.note||'Published records sync through the existing register feed. Individual register acknowledgements are unavailable.'} Drafts are not published by this check.</Note>}{d&&<Body d={d} open={open} create={create} refresh={()=>setReload(k=>k+1)}/>}</div></div>;
  }
  window.PromotionsWorkspace=PromotionsWorkspace;
  window.OFFICE_SCREENS=Object.assign(window.OFFICE_SCREENS||{},{promotions:PromotionsWorkspace});
})();
