// ─────────────────────────────────────────────────────────────────────
// UPLOAD RECEIPT — single-screen flow.  Capture → Review → Archive.
//
// Deliberately NOT a wizard. One screen: drop a document, it extracts,
// you glance over what it read, optionally re-assign a line or jot a
// note, and file it. Built for restorers / mechanics / assistants who
// want a receipt into the archive in seconds — not an accounting task.
//
// Line items are assigned INLINE (tap a line → lightweight action sheet:
// one car, several cars, or collection overhead). No percentage math.
// ─────────────────────────────────────────────────────────────────────

const { useState: useRcF, useRef: useRcRef } = React;

// What the archive understands automatically — preview states shown on the
// Capture screen to communicate value BEFORE extraction occurs.
const EXTRACT_FIELDS = [
  { k: 'Vendor',    v: 'Auto-detected', icon: 'Building2' },
  { k: 'Date',      v: 'Auto-detected', icon: 'Calendar' },
  { k: 'Currency',  v: 'Auto-detected', icon: 'Coins' },
  { k: 'Amount',    v: 'Auto-detected', icon: 'CircleDollarSign' },
  { k: 'Category',  v: 'Classified',    icon: 'Tags' },
  { k: 'Tax / VAT', v: 'Parsed',        icon: 'Percent' },
];

const NOTE_CHIPS = [
  'Seller included additional parts not listed on the invoice',
  'Work performed on the matching-numbers engine',
  'Parts purchased but not yet installed',
  'Expense approved by collection owner',
];

// ── header (simple — no step rail) ──────────────────────────────────────
function RcTopBar({ eyebrow, onBack, title = 'Upload Receipt' }) {
  return (
    <div style={{
      padding: '10px 18px 12px', background: P.ink, flex: '0 0 auto',
      display: 'flex', alignItems: 'center', gap: 12, borderBottom: `1px solid ${P.graphite}`,
    }}>
      <button onClick={onBack} aria-label="Back" style={{
        background: P.gold, border: 'none', borderRadius: 999, width: 34, height: 34,
        flexShrink: 0, color: P.ink, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><path d="M19 12H5M5 12l6-6M5 12l6 6" /></svg>
      </button>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontFamily: T.display, fontWeight: 600, fontSize: 15, letterSpacing: '0.02em', color: P.paper, lineHeight: 1.1 }}>{title}</div>
        <RcMono size={8.5} color={P.gold} tracking="0.16em" style={{ marginTop: 3, display: 'block' }}>{eyebrow}</RcMono>
      </div>
      <CAMonogram size={20} color={P.paper} stroke={1.6} />
    </div>
  );
}

// ── small parts for the scalable assignment sheet ───────────────────────

// A vehicle's thumbnail: real hero when we have one, otherwise a quiet
// marque monogram so a list of hundreds stays light.
function MarqueThumb({ v }) {
  if (v && v.hero) {
    return (
      <span style={{ width: 38, height: 48, flexShrink: 0, overflow: 'hidden', border: `1px solid ${P.slate}` }}>
        <PhotoSlot dirId="concours" height={48} tone="dark" src={v.hero} />
      </span>
    );
  }
  const code = (v && v.make ? v.make : '').replace(/[^A-Za-z]/g, '').slice(0, 2).toUpperCase();
  return (
    <span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: T.mono, fontSize: 11, fontWeight: 600, color: P.gold, letterSpacing: '0.04em' }}>{code}</span>
  );
}

// Confidence pill — the archive's certainty, growing as it learns.
function ConfChip({ level }) {
  const high = level === 'High';
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 7px', border: `1px solid ${high ? P.gold : P.slate}`, background: high ? 'rgba(184,144,85,0.12)' : 'transparent' }}>
      <span style={{ width: 5, height: 5, borderRadius: 999, background: high ? P.gold : 'transparent', border: `1px solid ${high ? P.gold : P.mute}` }} />
      <span style={{ fontFamily: T.mono, fontSize: 8, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', color: high ? P.gold : P.mute }}>{high ? 'High confidence' : 'Worth a look'}</span>
    </span>
  );
}

// One selectable vehicle row — radio (single) or checkbox (multi).
function AllocVehRow({ v, multi, selected, onClick, mb = 8 }) {
  return (
    <button onClick={onClick} style={{
      width: '100%', textAlign: 'left', cursor: 'pointer', marginBottom: mb,
      background: selected ? '#171614' : 'transparent', border: `1px solid ${selected ? '#3a3833' : P.slate}`,
      padding: '9px 12px', display: 'flex', alignItems: 'center', gap: 11,
    }}>
      <span style={{
        width: 18, height: 18, flexShrink: 0, borderRadius: multi ? 2 : 999,
        border: `1px solid ${selected ? P.gold : P.slate}`, background: selected ? P.gold : 'transparent',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {selected && (multi
          ? <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke={P.ink} strokeWidth="3.2" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5" /></svg>
          : <span style={{ width: 8, height: 8, borderRadius: 999, background: P.ink }} />)}
      </span>
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: 'block', fontFamily: T.display, fontSize: 14.5, fontWeight: 600, color: P.paper, lineHeight: 1.15, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{v.year} {v.make} {v.model}</span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 3, minWidth: 0 }}>
          <RcMono size={8} color={P.gold} tracking="0.1em" style={{ flexShrink: 0 }}>VIN ···{(v.vin || '').slice(-4)}</RcMono>
          <RcMono size={8} color={v.project ? P.bone : P.mute} tracking="0.06em" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{v.project ? v.project : v.status}</RcMono>
        </span>
      </span>
    </button>
  );
}

// A vehicle already in the split — no checkbox; a gray × on the right removes it.
function SplitSelectedRow({ v, onRemove }) {
  return (
    <div style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 11, marginBottom: 4, background: '#171614', border: `1px solid #3a3833`, padding: '9px 12px' }}>
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: 'block', fontFamily: T.display, fontSize: 14.5, fontWeight: 600, color: P.paper, lineHeight: 1.15, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{v.year} {v.make} {v.model}</span>
        <VehSub v={v} />
      </span>
      <button onClick={onRemove} aria-label="Remove from split" style={{ width: 28, height: 28, flexShrink: 0, marginRight: -2, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'transparent', border: 'none', cursor: 'pointer' }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={P.gold} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6L6 18" /><path d="M6 6l12 12" /></svg>
      </button>
    </div>
  );
}

function AllocSectionLabel({ children, right }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, margin: '2px 0 9px' }}>
      <RcMono size={8.5} color={P.mute} tracking="0.16em">{children}</RcMono>
      {right}
    </div>
  );
}

// Lightweight one-tap shortcut row — recents & search results. Deliberately
// lighter than the Suggested Match hero: no boxed border, just a hairline
// divider and a trailing arrow that reads "tap to assign".
function ShortcutVehRow({ v, onClick, selected }) {
  return (
    <button onClick={onClick} style={{
      width: '100%', textAlign: 'left', cursor: 'pointer',
      background: selected ? 'rgba(184,144,85,0.12)' : 'transparent', border: 'none', borderBottom: `1px solid ${P.slate}`,
      padding: '10px 8px', display: 'flex', alignItems: 'center', gap: 12,
    }}>
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: 'block', fontFamily: T.display, fontSize: 14, fontWeight: 600, color: P.paper, lineHeight: 1.15, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{v.year} {v.make} {v.model}</span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 3, minWidth: 0 }}>
          <RcMono size={8} color={P.gold} tracking="0.1em" style={{ flexShrink: 0 }}>VIN ···{(v.vin || '').slice(-4)}</RcMono>
          <RcMono size={8} color={v.project ? P.bone : P.mute} tracking="0.06em" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{v.project ? v.project : v.status}</RcMono>
        </span>
      </span>
      <Icon name={selected ? 'Check' : 'add'} size={16} color={P.gold} strokeWidth={2} />
    </button>
  );
}

// Small descending-confidence meter (3 bars) for alternative recommendations.
function ConfMeter({ level = 0 }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'flex-end', gap: 2, height: 11, flexShrink: 0 }} aria-hidden="true">
      {[0, 1, 2].map(i => (
        <span key={i} style={{ width: 3, height: 4 + i * 3, background: i < level ? P.gold : P.slate }} />
      ))}
    </span>
  );
}

// One row in the assignment selection list — radio + thumb + label + right slot.
function SelectRow({ selected, onClick, thumb, title, sub, right, last, onRemove }) {
  return (
    <button onClick={onClick} style={{
      width: '100%', textAlign: 'left', cursor: 'pointer',
      background: 'transparent',
      border: 'none', borderBottom: last ? 'none' : `1px solid ${P.slate}`,
      padding: '12px 13px', display: 'flex', alignItems: 'center', gap: 12,
      boxShadow: selected ? `inset 3px 0 0 ${P.gold}` : 'none',
    }}>
      <span style={{ width: 18, height: 18, flexShrink: 0, borderRadius: 999, border: `1px solid ${selected ? P.gold : P.slate}`, background: selected ? P.gold : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        {selected && <span style={{ width: 7, height: 7, borderRadius: 999, background: P.ink }} />}
      </span>
      {thumb}
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: 'block', fontFamily: T.display, fontSize: 14.5, fontWeight: 600, color: P.paper, lineHeight: 1.15, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</span>
        {sub}
      </span>
      {right}
      {onRemove && (
        <span role="button" aria-label="Remove from list"
          onClick={(e) => { e.stopPropagation(); onRemove(); }}
          style={{ width: 26, height: 26, flexShrink: 0, marginRight: -4, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={P.mute} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6L6 18" /><path d="M6 6l12 12" /></svg>
        </span>
      )}
    </button>
  );
}

// VIN · status/project sub-line used inside SelectRow.
function VehSub({ v }) {
  return (
    <span style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 3, minWidth: 0 }}>
      <RcMono size={8} color={P.gold} tracking="0.1em" style={{ flexShrink: 0 }}>VIN ···{(v.vin || '').slice(-4)}</RcMono>
      <RcMono size={8} color={v.project ? P.bone : P.mute} tracking="0.06em" style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{v.project ? v.project : v.status}</RcMono>
    </span>
  );
}
//
// Scales to a collection of hundreds: the AI suggestion stays the primary
// recommendation up top, a search field finds any vehicle, and the list
// surfaces only the suggestion + recently-assigned cars + search results —
// never an endless manual scroll. Collection Overhead is always available.
// One vehicle · several vehicles (shared, divided evenly) · overhead.
// ─────────────────────────────────────────────────────────────────────
function AllocatorSheet({ line, vehicles, value, onApply, onClose, money }) {
  const suggestedId = line.suggest;
  const init = value && value.mode
    ? { ...value, splits: value.splits ? value.splits.map(s => ({ ...s })) : null }
    : (suggestedId === 'overhead' ? { mode: 'overhead' } : { mode: 'vehicle', vehicleId: suggestedId });
  const [alloc, setAlloc] = useRcF(init);
  const [query, setQuery] = useRcF('');
  const [added, setAdded] = useRcF([]); // vehicles pulled into the list via search
  const [removed, setRemoved] = useRcF([]); // vehicle ids the user removed from the list
  const [splitAdded, setSplitAdded] = useRcF([]); // split cars pulled in via search
  const [splitEntered, setSplitEntered] = useRcF(init.mode === 'split'); // entered the multi editor yet?
  // Pending non-vehicle destination chosen from the split editor's OR REASSIGN
  // section. Held separately so the split layout stays intact until the user
  // taps Assign. 'overhead' | 'none' | null.
  const [reassignTo, setReassignTo] = useRcF(null);
  // When reassignTo === 'single', the specific vehicle picked from the search
  // results below (chosen in-place, without leaving the split screen).
  const [reassignSingleId, setReassignSingleId] = useRcF(null);
  // "A Single Car" picked from the Reassign list on the decision screen →
  // CONTINUE leads to a dedicated single-car search step.
  const [singleMode, setSingleMode] = useRcF(false);
  const [singleEntered, setSingleEntered] = useRcF(false);
  const multi = alloc.mode === 'split';
  const inMultiUI = multi && splitEntered; // multi-vehicle editor vs. the decision screen

  // Resolve everything against the full collection pool.
  const byIdLocal = {};
  vehicles.forEach(v => { byIdLocal[v.id] = v; });
  const poolCount = vehicles.length;

  const suggestedVehicle = suggestedId && suggestedId !== 'overhead' ? byIdLocal[suggestedId] : null;
  const suggestedSelected = suggestedId === 'overhead'
    ? alloc.mode === 'overhead'
    : (alloc.mode === 'vehicle' && alloc.vehicleId === suggestedId);

  // CURRENT ASSIGNMENT reflects the line's ACTUAL current target (init), not
  // the AI guess — whatever this line is allocated to is shown at the top.
  const currentMode = init.mode; // 'vehicle' | 'overhead' | 'none' | 'split'
  const currentVehicleId = init.mode === 'vehicle' ? init.vehicleId : null;
  const currentVehicle = currentVehicleId ? byIdLocal[currentVehicleId] : null;
  const selectCurrent = () => setAlloc(currentMode === 'vehicle' ? { mode: 'vehicle', vehicleId: currentVehicleId } : { mode: currentMode });
  // Match reasoning only makes sense when the current target IS the AI suggestion.
  const showReasoning = currentMode === 'vehicle' && currentVehicleId === suggestedId;

  const recents = (typeof COLLECTION_RECENT_IDS !== 'undefined' ? COLLECTION_RECENT_IDS : [])
    .map(id => byIdLocal[id]).filter(Boolean).filter(v => v.id !== suggestedId && !removed.includes(v.id)).slice(0, suggestedVehicle ? 2 : 3);
  const recentIdSet = new Set(recents.map(v => v.id));
  // Vehicles the user pulled in from search — shown in the main list below recents.
  const addedVehicles = added
    .map(id => byIdLocal[id])
    .filter(Boolean)
    .filter(v => v.id !== suggestedId && !recentIdSet.has(v.id) && !removed.includes(v.id));

  const results = query.trim() ? searchVehicles(vehicles, query) : [];
  const RESULT_CAP = 24;
  const shownResults = results.slice(0, RESULT_CAP);
  const moreResults = Math.max(0, results.length - RESULT_CAP);

  const pickVehicle = (id) => setAlloc({ mode: 'vehicle', vehicleId: id });
  const pickOverhead = () => setAlloc({ mode: 'overhead' });
  const pickNone = () => setAlloc({ mode: 'none' });
  // Search is a selection tool, not a list builder: picking a result becomes
  // the new assignment outright and deselects whatever was chosen before.
  const selectFromSearch = (id) => setAlloc({ mode: 'vehicle', vehicleId: id });
  // Split view: add a searched car to the selected set, then clear search.
  const addSplitFromSearch = (id) => {
    setAlloc(a => {
      if (a.mode !== 'split') return a;
      if (a.splits.some(s => s.id === id)) return a;
      const ids = [...a.splits.map(s => s.id), id];
      const pct = Math.round(100 / ids.length);
      return { mode: 'split', splits: ids.map(x => ({ id: x, pct })) };
    });
    setSplitAdded(s => s.includes(id) ? s : [...s, id]);
    setQuery('');
  };
  // One-tap confirm helpers — the express path the redesign is built around.
  const assignVehicle = (id) => { onApply({ mode: 'vehicle', vehicleId: id }); onClose(); };
  const assignOverhead = () => { onApply({ mode: 'overhead' }); onClose(); };
  // Split view: CLEAR is active once the user has added at least one car from
  // search. Clicking it empties the split so they can start over.
  const splitClearActive = multi && alloc.splits.length > 0;
  const clearSplitAll = () => {
    setAlloc(a => a.mode === 'split' ? { mode: 'split', splits: [] } : a);
    setSplitAdded([]);
  };
  const selectSuggested = () => suggestedId === 'overhead' ? pickOverhead() : pickVehicle(suggestedId);
  const inMulti = (id) => multi && alloc.splits.some(s => s.id === id);
  // Entering the split editor starts with an empty selection — the user
  // searches and picks the cars to divide this expense across.
  const enterMulti = () => setAlloc({ mode: 'split', splits: [] });
  const exitMulti = () => { setReassignTo(null); setReassignSingleId(null); setSplitEntered(false); selectSuggested(); };
  // Back from the split editor returns to wherever the user came from:
  //  · opened a line that ALREADY had a split → they never saw the decision
  //    screen, so go straight back out to the line-items list (onClose).
  //  · chose "split" on the change-assignment screen → return to it (exitMulti).
  const splitBack = () => { if (init.mode === 'split') { onClose && onClose(); } else { exitMulti(); } };
  const toggleMulti = (id) => { setReassignTo(null); setReassignSingleId(null); setAlloc(a => {
    const has = a.splits.some(s => s.id === id);
    const ids = has ? a.splits.filter(s => s.id !== id).map(s => s.id) : [...a.splits.map(s => s.id), id];
    const pct = ids.length ? Math.round(100 / ids.length) : 0;
    return { mode: 'split', splits: ids.map(x => ({ id: x, pct })) };
  }); };

  const splitCount = multi ? alloc.splits.length : 0;
  const selectedSplitVehicles = multi ? alloc.splits.map(s => byIdLocal[s.id]).filter(Boolean) : [];
  // Cars in the split besides the current assignment — these stay visible in
  // the allocation regardless of what's typed in the search field.
  const extraSelected = selectedSplitVehicles.filter(v => v.id !== suggestedId);
  // Search is the only way to add cars now: results exclude ones already in
  // the split (they live in their own visible section above).
  const splitResults = shownResults.filter(v => !inMulti(v.id));
  // In multi mode the browse list excludes already-selected cars.
  const browseSource = query.trim() ? shownResults : recents;
  const multiBrowse = browseSource.filter(v => !inMulti(v.id));

  // Has the user changed the assignment away from what it started as?
  // The Assign button stays disabled until they pick something different.
  const allocsEqual = (a, b) => {
    if (!a || !b || a.mode !== b.mode) return false;
    if (a.mode === 'overhead') return true;
    if (a.mode === 'none') return true;
    if (a.mode === 'vehicle') return a.vehicleId === b.vehicleId;
    if (a.mode === 'split') {
      const sa = a.splits || [], sb = b.splits || [];
      if (sa.length !== sb.length) return false;
      const key = s => s.id + ':' + s.pct;
      const setB = new Set(sb.map(key));
      return sa.every(s => setB.has(key(s)));
    }
    return false;
  };
  // Split is a destination choice: picking it selects the radio and turns the
  // primary action into CONTINUE — tapping CONTINUE enters the multi editor.
  const splitPending = multi && !splitEntered;
  const singlePending = inMultiUI && reassignTo === 'single';
  // "A Single Car" picked on the decision screen: CONTINUE → single-car search step.
  const singleDecisionPending = singleMode && !singleEntered;
  const primaryLabel = (!singleEntered && (splitPending || singlePending || singleDecisionPending)) ? 'Continue' : 'Assign';
  const primaryEnabled = singleEntered ? (alloc.mode === 'vehicle')
    : singleDecisionPending ? true
    : splitPending ? true
    : inMultiUI ? (reassignTo === 'single' ? true : reassignTo ? true : alloc.splits.length >= 2)
    : !allocsEqual(alloc, init);
  const onPrimary = () => {
    if (!primaryEnabled) return;
    if (singleEntered) { onApply(alloc); onClose(); return; }
    if (singleDecisionPending) { setSingleEntered(true); return; }
    if (splitPending) { setSplitEntered(true); return; }
    if (singlePending) { setSingleEntered(true); return; }
    let applied = alloc;
    if (inMultiUI && (reassignTo === 'overhead' || reassignTo === 'none')) applied = { mode: reassignTo };
    onApply(applied); onClose();
  };

  // Closing the search (× or emptying the field) without assigning a picked
  // result snaps the selection back to the current assignment at the top.
  const searchSelectionPending = !multi && alloc.mode === 'vehicle' && alloc.vehicleId !== suggestedId;
  const clearSearch = () => {
    setQuery('');
    if (searchSelectionPending) selectSuggested();
  };

  // Reusable search field (single fallback + multi browse).
  const searchField = (
    <div style={{ position: 'relative' }}>
      <input
        value={query}
        onChange={(e) => { const val = e.target.value; setQuery(val); if (!val.trim() && searchSelectionPending) selectSuggested(); }}
        placeholder="Search by vehicle, nickname, VIN, or project"
        style={{
          width: '100%', height: 44, boxSizing: 'border-box', background: P.ink,
          border: `1px solid ${query.trim() ? P.gold : P.slate}`, outline: 'none', color: P.paper,
          fontFamily: T.body, fontSize: 12.5, padding: '0 36px 0 14px',
        }} />
      {query.trim() && (
        <button onClick={clearSearch} aria-label="Clear search" style={{ position: 'absolute', right: 6, top: 0, bottom: 0, width: 30, background: 'transparent', border: 'none', color: P.mute, cursor: 'pointer', fontFamily: T.mono, fontSize: 15 }}>×</button>
      )}
    </div>
  );

  const node = (
    <div style={{ position: 'absolute', inset: 0, zIndex: 97 }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(10,10,11,0.82)', backdropFilter: 'blur(2px)', WebkitBackdropFilter: 'blur(2px)', animation: 'sheetFade .2s ease' }} />
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: '88%', background: P.graphite, color: P.paper, borderTop: `1px solid ${P.gold}`, display: 'flex', flexDirection: 'column', animation: 'sheetIn .25s cubic-bezier(.2,.7,.3,1)' }}>
        {/* header — the line being assigned */}
        <div style={{ padding: '14px 22px 12px', flex: '0 0 auto', borderBottom: `1px solid ${P.slate}` }}>
          <div style={{ width: 40, height: 4, background: P.slate, margin: '0 auto 14px' }} />
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
            <div style={{ minWidth: 0, flex: 1 }}>
              <Eyebrow color={P.gold}>CHANGE ASSIGNMENT</Eyebrow>
              <div style={{ fontFamily: T.body, fontSize: 13.5, color: P.paper, marginTop: 7, lineHeight: 1.35 }}>{line.desc}</div>
            </div>
            <div style={{ textAlign: 'right', flexShrink: 0 }}>
              <div style={{ fontFamily: T.display, fontSize: 20, fontWeight: 700, color: P.gold, lineHeight: 1 }}>{money ? money.main : eur(line.net)}</div>
              {money
                ? (money.sub ? <RcMono size={8} color={P.mute} style={{ marginTop: 3, display: 'block' }}>{money.sub}</RcMono> : null)
                : <RcMono size={8} color={P.mute} style={{ marginTop: 3, display: 'block' }}>{usd(toHome(line.net))}</RcMono>}
            </div>
          </div>
        </div>

        <div className="proto-scroll" style={{ flex: 1, overflow: 'auto', padding: '16px 22px 8px' }}>
          {singleEntered ? (
            /* ════ A SINGLE CAR — focused search step ════ */
            <React.Fragment>
              <div style={{ display: 'flex', alignItems: 'center', marginBottom: 16 }}>
                <button onClick={() => setSingleEntered(false)} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'transparent', border: 'none', color: P.gold, cursor: 'pointer', fontFamily: T.mono, fontSize: 9, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', padding: 0 }}>
                  <Icon name="ChevronLeft" size={14} color={P.gold} strokeWidth={2} />Back
                </button>
              </div>
              <div style={{ fontFamily: T.display, fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em', color: P.paper, marginBottom: 14, lineHeight: 1.1 }}>Select a Vehicle</div>

              <AllocSectionLabel>SEARCH COLLECTION</AllocSectionLabel>
              <div style={{ marginBottom: query.trim() ? 18 : 12 }}>{searchField}</div>

              {query.trim() ? (
                <div>
                  <AllocSectionLabel>{`SEARCH RESULTS · ${results.length}`}</AllocSectionLabel>
                  {results.length === 0 ? (
                    <div style={{ padding: '16px 13px', textAlign: 'center', border: `1px solid ${P.slate}` }}>
                      <RcMono size={9} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', letterSpacing: '0.02em' }}>No vehicle matches “{query.trim()}”</RcMono>
                    </div>
                  ) : (
                    <div style={{ border: `1px solid ${P.slate}` }}>
                      {shownResults.map((v, i) => (
                        <SelectRow key={v.id}
                          selected={alloc.mode === 'vehicle' && alloc.vehicleId === v.id}
                          onClick={() => selectFromSearch(v.id)}
                          last={i === shownResults.length - 1 && moreResults === 0}
                          title={`${v.year} ${v.make} ${v.model}`}
                          sub={<VehSub v={v} />} />
                      ))}
                      {moreResults > 0 && (
                        <div style={{ padding: '9px 13px', borderTop: `1px solid ${P.slate}` }}><RcMono size={8} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', letterSpacing: '0.02em' }}>+ {moreResults} more — refine your search</RcMono></div>
                      )}
                    </div>
                  )}
                </div>
              ) : (
                recents.length > 0 && (
                  <div>
                    <AllocSectionLabel>RECENT</AllocSectionLabel>
                    <div style={{ border: `1px solid ${P.slate}` }}>
                      {recents.map((v, i) => (
                        <SelectRow key={v.id}
                          selected={alloc.mode === 'vehicle' && alloc.vehicleId === v.id}
                          onClick={() => selectFromSearch(v.id)}
                          last={i === recents.length - 1}
                          title={`${v.year} ${v.make} ${v.model}`}
                          sub={<VehSub v={v} />} />
                      ))}
                    </div>
                  </div>
                )
              )}
            </React.Fragment>
          ) : inMultiUI ? (
            /* ════ SPLIT ACROSS MULTIPLE CARS — current assignment + search ════ */
            <React.Fragment>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginBottom: 16 }}>
                <button onClick={splitBack} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'transparent', border: 'none', color: P.gold, cursor: 'pointer', fontFamily: T.mono, fontSize: 9, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', padding: 0 }}>
                  <Icon name="ChevronLeft" size={14} color={P.gold} strokeWidth={2} />Back
                </button>
                <button onClick={splitClearActive ? clearSplitAll : undefined} disabled={!splitClearActive} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, background: 'transparent', border: 'none', color: splitClearActive ? P.gold : P.slate, cursor: splitClearActive ? 'pointer' : 'default', fontFamily: T.mono, fontSize: 9, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', padding: 0 }}>
                  Clear all
                </button>
              </div>

              {/* page title — sits at the top, above the selected vehicles */}
              <div style={{ fontFamily: T.display, fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em', color: P.paper, marginBottom: 16, lineHeight: 1.1 }}>Select Vehicles for Split</div>

              {/* ── ADDED TO SPLIT — cars the user picked from search; hidden until then ── */}
              {selectedSplitVehicles.length > 0 && (
                <React.Fragment>
                  {init.mode === 'split' && <AllocSectionLabel>CURRENT ASSIGNMENT</AllocSectionLabel>}
                  <div style={{ marginBottom: 18 }}>
                    {selectedSplitVehicles.map(v => (
                      <SplitSelectedRow key={'sel-' + v.id} v={v} onRemove={() => toggleMulti(v.id)} />
                    ))}
                  </div>
                </React.Fragment>
              )}

              {/* ── SEARCH COLLECTION — the primary way to add vehicles ── */}
              <AllocSectionLabel>SEARCH COLLECTION</AllocSectionLabel>
              <div style={{ marginBottom: query.trim() ? 16 : 0 }}>{searchField}</div>

              {query.trim() ? (
                <React.Fragment>
                  <AllocSectionLabel>{`SEARCH RESULTS · ${splitResults.length}`}</AllocSectionLabel>
                  {splitResults.length === 0 ? (
                    <div style={{ minHeight: 52, padding: '0 13px', display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', border: `1px solid ${P.slate}` }}>
                      <RcMono size={9} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', letterSpacing: '0.02em' }}>{results.length === 0 ? `No vehicle matches “${query.trim()}”` : 'Every match is already in the split'}</RcMono>
                    </div>
                  ) : (
                    <React.Fragment>
                      {splitResults.map(v => (
                        <ShortcutVehRow key={v.id} v={v} onClick={() => toggleMulti(v.id)} />
                      ))}
                      {moreResults > 0 && (
                        <div style={{ padding: '2px 2px 0' }}><RcMono size={8} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', letterSpacing: '0.02em' }}>+ {moreResults} more — refine your search</RcMono></div>
                      )}
                    </React.Fragment>
                  )}
                </React.Fragment>
              ) : null}

              {/* ── REASSIGN AWAY FROM THE SPLIT — only when this line opened
                     with a PRE-EXISTING split (the decision screen was skipped).
                     A new split has Back/Cancel, so it doesn't need this. ── */}
              {init.mode === 'split' && (
              <div style={{ marginTop: 22 }}>
                <AllocSectionLabel>OR REASSIGN</AllocSectionLabel>
                <div style={{ border: `1px solid ${P.slate}` }}>
                  <SelectRow
                    selected={reassignTo === 'single'}
                    onClick={() => setReassignTo(reassignTo === 'single' ? null : 'single')}
                    thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="car" size={16} color={P.mute} strokeWidth={1.6} /></span>}
                    title="A Single Vehicle"
                    sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Assign the whole line to one vehicle</RcMono>} />
                  <SelectRow
                    selected={reassignTo === 'overhead'}
                    onClick={() => setReassignTo(reassignTo === 'overhead' ? null : 'overhead')}
                    thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="archive" size={16} color={P.mute} strokeWidth={1.6} /></span>}
                    title="Collection Overhead"
                    sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Shared expense · not vehicle-specific</RcMono>} />
                  <SelectRow
                    selected={reassignTo === 'none'}
                    onClick={() => setReassignTo(reassignTo === 'none' ? null : 'none')}
                    last
                    thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="flag" size={16} color={P.mute} strokeWidth={1.6} /></span>}
                    title="No Assignment"
                    sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Leave unassigned · explain with a note on the report</RcMono>} />
                </div>
              </div>
              )}
            </React.Fragment>
          ) : (
            /* ════ CHANGE ASSIGNMENT — edit an existing assignment, not browse ════ */
            <React.Fragment>
              {/* ── CURRENT ASSIGNMENT — the archive's single recommendation ── */}
              <AllocSectionLabel>CURRENT ASSIGNMENT</AllocSectionLabel>
              <div style={{ border: `1px solid ${P.slate}`, marginBottom: 18 }}>
                <SelectRow
                  selected={allocsEqual(alloc, init) && !singleMode}
                  onClick={() => { setSingleMode(false); selectCurrent(); }}
                  last
                  thumb={currentVehicle
                    ? <MarqueThumb v={currentVehicle} />
                    : <span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name={currentMode === 'none' ? 'flag' : 'archive'} size={16} color={P.gold} strokeWidth={1.6} /></span>}
                  title={currentVehicle ? `${currentVehicle.year} ${currentVehicle.make} ${currentVehicle.model}` : currentMode === 'none' ? 'No Assignment' : 'Collection Overhead'}
                  sub={currentVehicle
                    ? <VehSub v={currentVehicle} />
                    : <RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>{currentMode === 'none' ? 'Leave unassigned · explain with a note on the report' : 'Shared expense · not vehicle-specific'}</RcMono>}
                />
                {/* match reasoning — only when the current target is the AI suggestion */}
                {showReasoning && (line.why || line.learned) && (
                  <div style={{ display: 'grid', gridTemplateRows: (allocsEqual(alloc, init) && !singleMode) ? '1fr' : '0fr', transition: 'grid-template-rows .3s cubic-bezier(.2,.7,.3,1)' }}>
                    <div style={{ overflow: 'hidden', minHeight: 0, opacity: (allocsEqual(alloc, init) && !singleMode) ? 1 : 0, transition: 'opacity .24s ease' }}>
                      <div style={{ background: '#2C2A25', borderTop: `1px solid ${P.slate}`, padding: '13px 14px 14px', boxShadow: 'inset 0 8px 10px -8px rgba(0,0,0,0.75)' }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginBottom: 10 }}>
                          <Icon name="spark" size={12} color={P.gold} strokeWidth={2} />
                          <RcMono size={8} color={P.gold} tracking="0.18em">MATCH REASONING</RcMono>
                        </div>
                        <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
                          {[line.why, line.learned].filter(Boolean).map((t, i) => (
                            <div key={i} style={{ display: 'flex', gap: 9, alignItems: 'flex-start' }}>
                              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={P.gold} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 1 }}><path d="M20 6L9 17l-5-5" /></svg>
                              <div style={{ fontFamily: T.body, fontSize: 12, color: P.bone, lineHeight: 1.45 }}>{t.replace(/[“”"]/g, '')}</div>
                            </div>
                          ))}
                        </div>
                      </div>
                    </div>
                  </div>
                )}
              </div>

              {/* ── SELECT A DIFFERENT CAR — only when the current assignment is
                     already a single car; otherwise reassigning to a car goes
                     through the "A Single Car" → Continue step in Reassign. ── */}
              {currentMode === 'vehicle' && (
              <React.Fragment>
              <AllocSectionLabel>SELECT A DIFFERENT VEHICLE</AllocSectionLabel>
              <div style={{ marginBottom: query.trim() ? 18 : 4 }}>{searchField}</div>

              {/* search results — selecting one becomes the new assignment outright */}
              {query.trim() ? (
                <div>
                  <AllocSectionLabel>{`SEARCH RESULTS · ${results.length}`}</AllocSectionLabel>
                  {results.length === 0 ? (
                    <div style={{ padding: '16px 13px', textAlign: 'center', border: `1px solid ${P.slate}` }}>
                      <RcMono size={9} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', letterSpacing: '0.02em' }}>No vehicle matches “{query.trim()}”</RcMono>
                    </div>
                  ) : (
                    <div style={{ border: `1px solid ${P.slate}` }}>
                      {shownResults.map((v, i) => (
                        <SelectRow key={v.id}
                          selected={alloc.mode === 'vehicle' && alloc.vehicleId === v.id && !singleMode}
                          onClick={() => { setSingleMode(false); selectFromSearch(v.id); }}
                          last={i === shownResults.length - 1 && moreResults === 0}
                          title={`${v.year} ${v.make} ${v.model}`}
                          sub={<VehSub v={v} />} />
                      ))}
                      {moreResults > 0 && (
                        <div style={{ padding: '9px 13px', borderTop: `1px solid ${P.slate}` }}><RcMono size={8} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', letterSpacing: '0.02em' }}>+ {moreResults} more — refine your search</RcMono></div>
                      )}
                    </div>
                  )}
                </div>
              ) : null}
              </React.Fragment>
              )}

              {/* ── REASSIGN — first-class destinations + split workflow ── */}
              <div style={{ height: 22 }} />
              <AllocSectionLabel>REASSIGN</AllocSectionLabel>
              <div style={{ border: `1px solid ${P.slate}`, marginTop: 4 }}>
                {currentMode !== 'vehicle' && (
                  <SelectRow
                    selected={singleMode}
                    onClick={() => setSingleMode(m => !m)}
                    thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="car" size={16} color={P.mute} strokeWidth={1.6} /></span>}
                    title="A Single Vehicle"
                    sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Assign the whole line to one vehicle</RcMono>} />
                )}
                {currentMode !== 'overhead' && (
                  <SelectRow
                    selected={alloc.mode === 'overhead' && !singleMode}
                    onClick={() => { setSingleMode(false); pickOverhead(); }}
                    thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="archive" size={16} color={P.mute} strokeWidth={1.6} /></span>}
                    title="Collection Overhead"
                    sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Shared expense · not vehicle-specific</RcMono>} />
                )}
                {currentMode !== 'none' && (
                <SelectRow
                  selected={alloc.mode === 'none' && !singleMode}
                  onClick={() => { setSingleMode(false); pickNone(); }}
                  thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="flag" size={16} color={P.mute} strokeWidth={1.6} /></span>}
                  title="No Assignment"
                  sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Leave unassigned · explain with a note on the report</RcMono>} />
                )}
                <SelectRow
                  selected={multi && !singleMode}
                  onClick={() => { setSingleMode(false); enterMulti(); }}
                  last
                  thumb={<span style={{ width: 38, height: 48, flexShrink: 0, border: `1px solid ${P.slate}`, background: P.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="Layers" size={16} color={(multi && !singleMode) ? P.gold : P.mute} strokeWidth={1.6} /></span>}
                  title="Split Across Multiple Cars"
                  sub={<RcMono size={8} color={P.mute} tracking="0.06em" style={{ marginTop: 3, display: 'block', textTransform: 'none', letterSpacing: '0.04em' }}>Divide this cost evenly between several vehicles</RcMono>} />
              </div>
            </React.Fragment>
          )}
        </div>

        <div style={{ padding: '10px 22px 30px', flex: '0 0 auto', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, borderTop: `1px solid ${P.slate}` }}>
          <button onClick={onClose} style={{ height: 48, background: 'transparent', border: `1px solid ${P.slate}`, color: P.paper, fontFamily: T.mono, fontSize: 10, fontWeight: 600, letterSpacing: '0.16em', textTransform: 'uppercase', cursor: 'pointer' }}>Cancel</button>
          <button onClick={onPrimary} disabled={!primaryEnabled} style={{ height: 48, background: primaryEnabled ? P.gold : 'transparent', border: `1px solid ${primaryEnabled ? P.gold : P.slate}`, color: primaryEnabled ? P.ink : P.mute, fontFamily: T.mono, fontSize: 10, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', cursor: primaryEnabled ? 'pointer' : 'not-allowed', opacity: primaryEnabled ? 1 : 0.55, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, transition: 'background .15s, color .15s, opacity .15s' }}>
            {primaryLabel}
          </button>
        </div>

      </div>
    </div>
  );
  const stage = (typeof document !== 'undefined') ? (document.getElementById('proto-stage') || document.getElementById('contrib-stage')) : null;
  return stage ? ReactDOM.createPortal(node, stage) : node;
}

// ── filed confirmation (compact, not a screen) ──────────────────────────
function FiledOverlay({ vehicles, targets, note, onClose, onAnother }) {
  const byId = {}; vehicles.forEach(v => { byId[v.id] = v; });
  const { byTarget } = rollUp(targets);
  const ids = Object.keys(byTarget).sort((a, b) => (a === 'overhead' || a === 'review' ? 1 : 0) - (b === 'overhead' || b === 'review' ? 1 : 0));
  const node = (
    <div style={{ position: 'absolute', inset: 0, zIndex: 98, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24 }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(10,10,11,0.85)', backdropFilter: 'blur(2px)', WebkitBackdropFilter: 'blur(2px)' }} />
      <div style={{ position: 'relative', width: '100%', background: P.graphite, border: `1px solid ${P.gold}`, padding: '24px 26px', animation: 'sheetIn .25s cubic-bezier(.2,.7,.3,1)' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <span style={{ width: 38, height: 38, borderRadius: 999, border: `1px solid ${P.gold}`, background: 'rgba(184,144,85,0.1)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={P.gold} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5" /></svg>
          </span>
          <div>
            <div style={{ fontFamily: T.display, fontSize: 22, fontWeight: 700, color: P.paper, letterSpacing: '-0.015em', lineHeight: 1 }}>Record Created</div>
            <Eyebrow color={P.gold} style={{ marginTop: 5, display: 'block' }}>FILED TO THE ARCHIVE</Eyebrow>
          </div>
        </div>
        <div style={{ marginTop: 16, display: 'grid', gap: 8 }}>
          {ids.map(id => {
            const t = byTarget[id]; const isOver = id === 'overhead'; const isReview = id === 'review'; const v = byId[id];
            return (
              <div key={id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10, paddingBottom: 8, borderBottom: `1px solid ${P.slate}` }}>
                <div style={{ minWidth: 0 }}>
                  <RcMono size={8} color={P.mute} style={{ display: 'block' }}>ALLOCATED TO</RcMono>
                  <div style={{ fontFamily: T.body, fontSize: 12.5, color: P.paper, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginTop: 3 }}>{isReview ? 'No Assignment' : isOver ? 'Collection Overhead' : `${v.year} ${v.make} ${v.model}`}</div>
                </div>
                <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', flexShrink: 0 }}>
                  <RcMono size={8} color={P.mute} style={{ display: 'block' }}>AMOUNT</RcMono>
                  <span style={{ fontFamily: T.mono, fontSize: 12, color: P.gold, fontWeight: 600, marginTop: 3 }}>+{eur(t.grossE)}</span>
                  <RcMono size={8} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', marginTop: 1 }}>{usd(toHome(t.grossE))}</RcMono>
                </span>
              </div>
            );
          })}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 2 }}>
            <Icon name="archive" size={13} color={P.gold} strokeWidth={1.6} />
            <RcMono size={8} color={P.mute} tracking="0.1em">Original{note.trim() ? ' + note' : ''} preserved in the Vault</RcMono>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginTop: 18 }}>
          <button onClick={onAnother} style={{ height: 48, background: P.gold, border: `1px solid ${P.gold}`, color: P.ink, fontFamily: T.mono, fontSize: 10, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', cursor: 'pointer' }}>Add New</button>
          <button onClick={onClose} style={{ height: 48, background: 'transparent', border: `1px solid ${P.slate}`, color: P.paper, fontFamily: T.mono, fontSize: 10, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', cursor: 'pointer' }}>Done</button>
        </div>
      </div>
    </div>
  );
  const stage = (typeof document !== 'undefined') ? (document.getElementById('proto-stage') || document.getElementById('contrib-stage')) : null;
  return stage ? ReactDOM.createPortal(node, stage) : node;
}

// ── submitted-for-review confirmation (contributor variant) ─────────────
// Same expense flow as the manager, but a contributor never files to the
// archive — they hand the reviewed expense off to the collection manager.
function SubmittedForReviewOverlay({ vehicles, targets, note, manager = 'your manager', onClose, onAnother }) {
  const byId = {}; vehicles.forEach(v => { byId[v.id] = v; });
  const { byTarget } = rollUp(targets);
  const ids = Object.keys(byTarget).sort((a, b) => (a === 'overhead' || a === 'review' ? 1 : 0) - (b === 'overhead' || b === 'review' ? 1 : 0));
  const node = (
    <div style={{ position: 'absolute', inset: 0, zIndex: 98, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24 }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(10,10,11,0.85)', backdropFilter: 'blur(2px)', WebkitBackdropFilter: 'blur(2px)' }} />
      <div style={{ position: 'relative', width: '100%', background: P.graphite, border: `1px solid ${P.gold}`, padding: '24px 26px', animation: 'sheetIn .25s cubic-bezier(.2,.7,.3,1)' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <span style={{ width: 38, height: 38, borderRadius: 999, border: `1px solid ${P.gold}`, background: 'rgba(184,144,85,0.1)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <Icon name="Send" size={18} color={P.gold} strokeWidth={1.9} style={{ transform: 'translate(-1px, 1px)' }} />
          </span>
          <div>
            <div style={{ fontFamily: T.display, fontSize: 22, fontWeight: 700, color: P.paper, letterSpacing: '-0.015em', lineHeight: 1 }}>Thank You</div>
            <Eyebrow color={P.gold} style={{ marginTop: 5, display: 'block' }}>SUBMITTED FOR REVIEW</Eyebrow>
          </div>
        </div>
        <div style={{ width: '100%', fontFamily: T.body, fontSize: 12.5, color: P.bone, marginTop: 14, lineHeight: 1.55 }}>
          Your submission has been sent to <span style={{ color: P.paper, fontWeight: 600 }}>{manager}</span>.
        </div>
        <div style={{ marginTop: 16, display: 'grid', gap: 8 }}>
          {ids.map(id => {
            const t = byTarget[id]; const isOver = id === 'overhead'; const isReview = id === 'review'; const v = byId[id];
            return (
              <div key={id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10, paddingBottom: 8, borderBottom: `1px solid ${P.slate}` }}>
                <div style={{ minWidth: 0 }}>
                  <RcMono size={8} color={P.mute} style={{ display: 'block' }}>ALLOCATED TO</RcMono>
                  <div style={{ fontFamily: T.body, fontSize: 12.5, color: P.paper, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginTop: 3 }}>{isReview ? 'No Assignment' : isOver ? 'Collection Overhead' : `${v.year} ${v.make} ${v.model}`}</div>
                </div>
                <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', flexShrink: 0 }}>
                  <RcMono size={8} color={P.mute} style={{ display: 'block' }}>AMOUNT</RcMono>
                  <span style={{ fontFamily: T.mono, fontSize: 12, color: P.gold, fontWeight: 600, marginTop: 3 }}>{eur(t.grossE)}</span>
                  <RcMono size={8} color={P.mute} tracking="0.04em" style={{ textTransform: 'none', marginTop: 1 }}>{usd(toHome(t.grossE))}</RcMono>
                </span>
              </div>
            );
          })}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 2 }}>
            <Icon name="Paperclip" size={13} color={P.gold} strokeWidth={1.6} />
            <RcMono size={8} color={P.mute} tracking="0.1em">Original preserved with your submission{note.trim() ? ' + note' : ''}</RcMono>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginTop: 18 }}>
          <button onClick={onAnother} style={{ height: 48, background: P.gold, border: `1px solid ${P.gold}`, color: P.ink, fontFamily: T.mono, fontSize: 10, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', cursor: 'pointer' }}>Submit Another</button>
          <button onClick={onClose} style={{ height: 48, background: 'transparent', border: `1px solid ${P.slate}`, color: P.paper, fontFamily: T.mono, fontSize: 10, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', cursor: 'pointer' }}>Done</button>
        </div>
      </div>
    </div>
  );
  const stage = (typeof document !== 'undefined') ? (document.getElementById('proto-stage') || document.getElementById('contrib-stage')) : null;
  return stage ? ReactDOM.createPortal(node, stage) : node;
}

// ─────────────────────────────────────────────────────────────────────
// THE ONE SCREEN
// ─────────────────────────────────────────────────────────────────────
function ReceiptFlow({ vehicles = [], onBack, onClose, initialPhase = 'capture', initialPicked = false, fromReview = false, reviewLabel = 'Review Submission', submit = false, manager = (typeof CONTRIBUTOR !== 'undefined' ? CONTRIBUTOR.manager : 'your manager') }) {
  const active = vehicles.filter(v => v.status !== 'Sold' && v.status !== 'Archived');
  const validIds = new Set(active.map(v => v.id));
  // The searchable collection pool: real (fully-modelled) cars + the roster
  // standing in for the rest of a large collection. All lookups resolve here.
  const pool = vehiclePool(active);
  const byId = {}; pool.forEach(v => { byId[v.id] = v; });

  const initTargets = () => {
    const t = {};
    RECEIPT.lines.forEach(l => {
      if (l.suggest === 'overhead') t[l.id] = { mode: 'overhead', ai: true };
      else if (validIds.has(l.suggest)) t[l.id] = { mode: 'vehicle', vehicleId: l.suggest, ai: true };
      else t[l.id] = { mode: 'overhead', ai: true };
    });
    return t;
  };

  const [phase, setPhase] = useRcF(initialPhase); // capture | extracting | review
  const [picked, setPicked] = useRcF(initialPicked);
  const [targets, setTargets] = useRcF(initTargets);
  const [header, setHeader] = useRcF({ vendor: RECEIPT.vendor.name, date: RECEIPT.vendor.date });
  const [note, setNote] = useRcF('');
  const [allocLine, setAllocLine] = useRcF(null);
  const [filed, setFiled] = useRcF(false);
  const taRef = useRcRef(null);

  const applyAlloc = (lineId, alloc) => setTargets(prev => ({ ...prev, [lineId]: { ...alloc, ai: false } }));
  const tot = receiptTotals();
  const { currency } = RECEIPT;

  const read = () => {
    setPhase('extracting');
    setTimeout(() => setPhase('review'), 1400);
  };
  const back = () => {
    // Opened from the Review Documents queue: there's no capture step to step
    // back to — go straight back to the queue landing page.
    if (fromReview) return onBack && onBack();
    if (phase === 'review') return setPhase('capture');
    return onBack && onBack();
  };

  return (
    <React.Fragment>
      <RcTopBar title={fromReview ? reviewLabel : 'Upload Expense'} eyebrow={phase === 'review' ? 'Financials · Review' : 'Financials'} onBack={back} />

      {/* ── CAPTURE ───────────────────────────────────────────── */}
      {phase === 'capture' && (
        <div className="proto-scroll" style={{ flex: 1, overflow: 'auto', background: P.ink }} data-screen-label="rc-capture">
          <div style={{ padding: '18px 22px 12px' }}>
            <div style={{ fontFamily: T.display, fontWeight: 700, fontSize: 30, lineHeight: 0.95, letterSpacing: '-0.02em', color: P.paper, whiteSpace: 'nowrap' }}>CAPTURE THE SOURCE</div>
            <div style={{ fontFamily: T.body, fontSize: 12.5, color: P.mute, marginTop: 10, lineHeight: 1.5, maxWidth: 320 }}>
              Upload a receipt or invoice. The archive identifies and organizes the important details automatically.
            </div>
          </div>

          <div style={{ padding: '6px 22px 18px' }}>
            {!picked ? (
              <div style={{ border: `1px solid ${P.gold}`, background: P.graphite }}>
                {/* actionable controls */}
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
                  {[{ icon: 'camera', label: 'Camera', file: 'RT-2026-0488.png' }, { icon: 'gallery', label: 'Photos', file: 'RT-2026-0488.png' }, { icon: 'FileText', label: 'PDF', file: 'RT-2026-0488.pdf' }].map((m, i) => (
                    <button key={m.label} onClick={() => setPicked(m.file)} style={{
                      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, padding: '16px 4px', cursor: 'pointer',
                      background: P.graphite, border: 'none', borderLeft: i > 0 ? `1px solid ${P.slate}` : 'none', color: P.paper,
                    }}>
                      <Icon name={m.icon} size={22} color={P.gold} strokeWidth={1.5} />
                      <RcMono size={9} color={P.paper} tracking="0.14em">{m.label}</RcMono>
                    </button>
                  ))}
                </div>
              </div>
            ) : (
              <div style={{ border: `1px solid ${P.gold}`, background: P.graphite, padding: 14, display: 'flex', alignItems: 'center', gap: 14, animation: 'sheetFade .45s ease both' }}>
                <div style={{ width: 46, height: 58, flexShrink: 0, overflow: 'hidden', border: `1px solid ${P.slate}` }}>
                  <div style={{ transform: 'scale(0.34)', transformOrigin: 'top left', width: 294 }}><ReceiptDocument compact /></div>
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontFamily: T.body, fontSize: 13, color: P.paper, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{picked}</div>
                  <RcMono size={8.5} color={P.mute} style={{ marginTop: 4, display: 'block' }}>{RECEIPT.intake.size} · READY TO READ</RcMono>
                </div>
                <button onClick={() => setPicked(false)} aria-label="Remove" style={{ width: 30, height: 30, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'transparent', border: 'none', cursor: 'pointer' }}>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={P.gold} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6L6 18" /><path d="M6 6l12 12" /></svg>
                </button>
              </div>
            )}
          </div>

          {/* automatic extraction — what the archive reads, communicated up front */}
          <div style={{ padding: '0 0 10px' }}>
            <RowRule>AUTOMATIC EXTRACTION</RowRule>
          </div>
          <div style={{ padding: '0 22px 18px' }}>
            <div style={{ background: P.graphite, borderLeft: `2px solid ${P.gold}`, padding: 18 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <Icon name="spark" size={18} color={P.gold} strokeWidth={1.6} />
                <div style={{ fontFamily: T.mono, fontSize: 10, fontWeight: 600, letterSpacing: '0.2em', textTransform: 'uppercase', color: P.paper }}>The archive reads it for you</div>
              </div>
              <div style={{ marginTop: 16, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 1, background: P.slate, border: `1px solid ${P.slate}` }}>
                {EXTRACT_FIELDS.map(f => (
                  <div key={f.k} style={{ background: P.ink, padding: '12px 12px', display: 'flex', alignItems: 'center', gap: 10 }}>
                    <Icon name={f.icon} size={15} color={P.gold} strokeWidth={1.5} />
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontFamily: T.mono, fontSize: 8.5, letterSpacing: '0.16em', textTransform: 'uppercase', color: P.mute }}>{f.k}</div>
                      <div style={{ fontFamily: T.body, fontSize: 11.5, color: P.paper, marginTop: 2 }}>{f.v}</div>
                    </div>
                  </div>
                ))}
              </div>
              <div style={{ marginTop: 12, display: 'flex', alignItems: 'center', gap: 8 }}>
                <span style={{ width: 6, height: 6, borderRadius: 4, background: P.gold, animation: 'pulseDot 1.8s ease-in-out infinite' }} />
                <div style={{ fontFamily: T.mono, fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', color: P.mute }}>Fields populate the moment a file is added</div>
              </div>
            </div>
          </div>

          <div style={{ padding: '8px 22px 16px' }}>
            <button onClick={read} disabled={!picked} style={{
              width: '100%', height: 52, background: picked ? P.gold : P.graphite, border: `1px solid ${picked ? P.gold : P.slate}`,
              color: picked ? P.ink : P.mute, cursor: picked ? 'pointer' : 'not-allowed',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
              fontFamily: T.mono, fontSize: 11, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase',
            }}>
              <Icon name="spark" size={16} color={picked ? P.ink : P.mute} strokeWidth={2} />
              Read this receipt
            </button>
            {!picked && <RcMono size={8.5} color={P.mute} style={{ display: 'block', textAlign: 'center', marginTop: 10 }}>Add a document to continue</RcMono>}
          </div>
          <div style={{ height: 14 }} />
        </div>
      )}

      {/* ── EXTRACTING (inline, same screen) ──────────────────── */}
      {phase === 'extracting' && (
        <div className="proto-scroll" style={{ flex: 1, overflow: 'auto', background: P.ink, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-start', paddingTop: 40 }} data-screen-label="rc-extracting">
          <RcMono size={9} color={P.gold} style={{ display: 'block', marginBottom: 14 }}>● READING DOCUMENT</RcMono>
          <div style={{ width: 220, padding: '0 0' }}>
            <div className="rc-scanwrap"><ReceiptDocument compact /><div className="rc-scanline" /></div>
          </div>
          <RcMono size={8.5} color={P.mute} style={{ display: 'block', marginTop: 16 }}>Vendor · date · currency · line items · tax · totals</RcMono>
        </div>
      )}

      {/* ── REVIEW (extraction + inline allocation + optional note) ── */}
      {phase === 'review' && (
        <div className="proto-scroll" style={{ flex: 1, overflow: 'auto', background: P.ink }} data-screen-label="rc-review">
          <div style={{ padding: '16px 22px 10px' }}>
            <RcMono size={9} color={P.gold} style={{ display: 'block' }}>EXTRACTED · {RECEIPT.lines.length} LINE ITEMS</RcMono>
            <div style={{ fontFamily: T.display, fontWeight: 700, fontSize: 30, lineHeight: 0.92, letterSpacing: '-0.02em', color: P.paper, marginTop: 7 }}>{submit ? <React.Fragment>REVIEW &amp; SUBMIT</React.Fragment> : <React.Fragment>REVIEW &amp; FILE</React.Fragment>}</div>
          </div>

          {/* original preserved */}
          <div style={{ padding: '4px 22px 14px' }}>
            <div style={{ display: 'flex', gap: 12, alignItems: 'stretch', background: P.graphite, padding: 12, borderLeft: `2px solid ${P.gold}` }}>
              <div style={{ width: 48, height: 60, flexShrink: 0, overflow: 'hidden', border: `1px solid ${P.slate}` }}>
                <div style={{ transform: 'scale(0.36)', transformOrigin: 'top left', width: 294 }}><ReceiptDocument compact /></div>
              </div>
              <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
                <div style={{ fontFamily: T.body, fontSize: 12.5, color: P.paper, fontWeight: 500 }}>{RECEIPT.intake.file}</div>
                <RcMono size={8} color={P.gold} style={{ marginTop: 5, display: 'inline-flex', alignItems: 'center', gap: 5 }}>
                  <Icon name={submit ? 'Paperclip' : 'archive'} size={11} color={P.gold} strokeWidth={1.8} /> {submit ? 'ATTACHED TO SUBMISSION' : 'PRESERVED IN THE VAULT ONCE FILED'}
                </RcMono>
              </div>
            </div>
          </div>

          {/* vendor / date / currency */}
          <div style={{ padding: '0 22px 8px' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 1, background: P.slate, border: `1px solid ${P.slate}` }}>
              <div style={{ gridColumn: '1 / -1' }}>
                <EditableField label="Vendor" value={header.vendor} onChange={(v) => setHeader(h => ({ ...h, vendor: v }))} />
              </div>
              <EditableField label="Date" value={header.date} onChange={(v) => setHeader(h => ({ ...h, date: v }))} mono />
              <div style={{ background: P.ink, padding: '11px 12px' }}>
                <RcMono size={8} color={P.mute} tracking="0.16em">Currency</RcMono>
                <div style={{ fontFamily: T.body, fontSize: 12.5, color: P.paper, marginTop: 4 }}>{currency.code} · {currency.homeSymbol}{currency.rate} {currency.home}</div>
              </div>
            </div>
          </div>

          {/* line items — tap to assign */}
          <div style={{ padding: '14px 0 8px' }}><RowRule>LINE ITEMS · TAP TO CHANGE ASSIGNMENT</RowRule></div>
          <div style={{ padding: '10px 22px 8px', display: 'flex', flexDirection: 'column', gap: 8 }}>
            {RECEIPT.lines.map(l => {
              const a = targets[l.id];
              return (
                <button key={l.id} onClick={() => setAllocLine(l)} style={{
                  width: '100%', textAlign: 'left', cursor: 'pointer', background: P.graphite, border: `1px solid ${P.slate}`,
                  padding: '11px 13px', display: 'flex', flexDirection: 'column', gap: 8,
                }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
                    <div style={{ minWidth: 0, flex: 1 }}>
                      <div style={{ fontFamily: T.body, fontSize: 12.5, color: P.paper, lineHeight: 1.3 }}>{l.desc}</div>
                    </div>
                    <div style={{ textAlign: 'right', flexShrink: 0 }}>
                      <div style={{ fontFamily: T.mono, fontSize: 12, color: P.paper, fontWeight: 500 }}>{eur(l.net)}</div>
                      <RcMono size={8} color={P.mute} style={{ marginTop: 2, display: 'block' }}>{usd(toHome(l.net))}</RcMono>
                    </div>
                  </div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10, paddingTop: 8, borderTop: `1px solid ${P.slate}` }}>
                    <TargetChip alloc={a} vehiclesById={byId} />
                    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, flexShrink: 0 }}>
                      <RcMono size={8} color={P.gold}>{a ? 'Change' : 'Assign'}</RcMono>
                      <Icon name="arrow" size={13} color={P.gold} strokeWidth={1.6} />
                    </span>
                  </div>
                </button>
              );
            })}
          </div>

          {/* totals */}
          <div style={{ padding: '8px 22px 8px' }}>
            <div style={{ background: P.graphite, padding: 14, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div style={{ marginTop: -2 }}>
                <RcMono size={8.5} color={P.gold} tracking="0.16em">Total</RcMono>
                <RcMono size={8} color={P.mute} style={{ marginTop: 1, display: 'block' }}>incl. VAT</RcMono>
              </div>
              <div style={{ textAlign: 'right' }}>
                <span style={{ fontFamily: T.display, fontSize: 24, fontWeight: 700, color: P.paper, letterSpacing: '-0.02em' }}>{eur(tot.total)}</span>
                <RcMono size={8} color={P.mute} style={{ marginTop: 3, display: 'block' }}>{usd(tot.home)} USD</RcMono>
              </div>
            </div>
          </div>

          {/* optional archive note */}
          <div style={{ padding: '12px 22px 8px' }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 9 }}>
              <RcMono size={9} color={P.mute} tracking="0.18em">Notes</RcMono>
              <RcMono size={8} color={P.slate} tracking="0.14em">Optional</RcMono>
            </div>
            <div style={{ border: `1px solid ${P.slate}`, background: P.graphite }}>
              <textarea ref={taRef} value={note} onChange={(e) => setNote(e.target.value)} rows={2}
                placeholder="Add details not included in this invoice or receipt."
                style={{ width: '100%', resize: 'vertical', minHeight: 58, boxSizing: 'border-box', background: P.ink, border: 'none', outline: 'none', color: P.paper, fontFamily: T.body, fontSize: 13, lineHeight: 1.5, padding: '12px 12px' }} />
            </div>
          </div>

          {/* file */}
          <div style={{ padding: '14px 22px 14px' }}>
            <button onClick={() => setFiled(true)} style={{
              width: '100%', height: 52, background: P.gold, border: `1px solid ${P.gold}`, color: P.ink, cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
              fontFamily: T.mono, fontSize: 11, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase',
            }}>
              <Icon name={submit ? 'Send' : 'archive'} size={16} color={P.ink} strokeWidth={2} />
              {submit ? 'Submit for Review' : 'File to archive'}
            </button>
            <div style={{ display: 'inline-flex', width: '100%', justifyContent: 'center', alignItems: 'center', gap: 8, marginTop: 12 }}>
              <span style={{ width: 5, height: 5, background: P.gold }} />
              {submit
                ? <RcMono size={8} color={P.mute} tracking="0.16em">Goes to {manager}'s review queue</RcMono>
                : <RcMono size={8} color={P.mute} tracking="0.16em">Actions create records · Records create the <span style={{ color: P.gold }}>archive</span></RcMono>}
            </div>
          </div>
          <div style={{ height: 14 }} />
        </div>
      )}

      {allocLine && (
        <AllocatorSheet line={allocLine} vehicles={pool} value={targets[allocLine.id]} onApply={(a) => applyAlloc(allocLine.id, a)} onClose={() => setAllocLine(null)} />
      )}
      {filed && (submit
        ? <SubmittedForReviewOverlay vehicles={pool} targets={targets} note={note} manager={manager}
            onClose={() => { setFiled(false); onClose && onClose(); }}
            onAnother={() => { setFiled(false); setPicked(false); setNote(''); setTargets(initTargets); setPhase('capture'); }} />
        : <FiledOverlay vehicles={pool} targets={targets} note={note}
            onClose={() => { setFiled(false); onClose && onClose(); }}
            onAnother={() => { setFiled(false); setPicked(false); setNote(''); setTargets(initTargets); setPhase('capture'); }} />
      )}

      <style>{`
        .rc-drop { display:flex; flex-direction:column; align-items:center; justify-content:center; width:100%; padding:30px 20px 26px; text-align:center; cursor:pointer; color:inherit; background:repeating-linear-gradient(135deg, ${P.graphite} 0 16px, rgba(255,255,255,0.015) 16px 17px); border:1px dashed ${P.slate}; }
        .rc-drop__ring { width:60px; height:60px; border-radius:999px; border:1px solid ${P.gold}; display:flex; align-items:center; justify-content:center; background:rgba(184,144,85,0.08); }
        .rc-scanwrap { position:relative; overflow:hidden; border:1px solid ${P.slate}; }
        .rc-scanline { position:absolute; left:0; right:0; height:2px; background:linear-gradient(90deg, transparent, ${P.gold}, transparent); box-shadow:0 0 18px 5px rgba(184,144,85,0.32); animation:rcScan 1.3s cubic-bezier(.5,0,.5,1) infinite; }
        @keyframes rcScan { 0%{ top:1%; } 50%{ top:97%; } 100%{ top:1%; } }
      `}</style>
    </React.Fragment>
  );
}

Object.assign(window, { ReceiptFlow, AllocatorSheet, FiledOverlay, SubmittedForReviewOverlay });
