/* global React, Icon, MegaFooter */
const { useState: useStatePortal, useEffect: useEffectPortal } = React;

// ====================================================================
// /rentals/kit-tech-portal — staff portal for Kit Prep Techs.
//
// Magic-link auth (email-only, no passwords). The /api/portal/* endpoints
// verify the email against either the hardcoded VF staff list or the
// confirmed section of the Application Form - Kit Prep Technician DB, and
// require a matching Crew DB row for tech identity (writes use the Crew
// relation on the Shifts DB; staff use the Notion person property).
//
// Phase 0 + Phase 1 ships the chrome, login flow, SOP and Rates tabs.
// Shifts / Tasks / Equipment tabs are placeholders until later phases.
// ====================================================================

const PORTAL_TABS = [
  { key: 'shifts',    label: 'Shifts',    phase: 3 },
  { key: 'tasks',     label: 'Tasks',     phase: 2 },
  { key: 'equipment', label: 'Equipment', phase: 5 },
  { key: 'sop',       label: 'SOP',       phase: 1 },
  { key: 'rates',     label: 'Rates',     phase: 1 },
];

const SOP_URL = 'https://valleyfilms.notion.site/vr-sop';
const BIN_UNIT = '1122';
const BIN_CODE = '2222';

const RATE_ROWS = [
  { type: 'After Hours', time: 'N/A',          length: '10–20 mins',    mult: '1.35×', pay: '£19.98'  },
  { type: 'Half day',    time: '11:00–16:00',  length: '4 hrs + Lunch', mult: '4.5×',  pay: '£66.60'  },
  { type: 'Full Day',    time: '09:00–17:00',  length: '7 hrs + Lunch', mult: '7×',    pay: '£103.60' },
  { type: 'Long Day',    time: '08:30–18:00',  length: '8.5 hrs + Lunch', mult: '8.5×', pay: '£125.80' },
];

function KitTechPortalPage({ onGoto }) {
  // session === undefined → loading; null → not signed in; obj → signed in
  const [session, setSession] = useStatePortal(undefined);
  const [activeTab, setActiveTab] = useStatePortal('shifts');

  useEffectPortal(() => {
    fetch('/api/portal/session', { credentials: 'same-origin' })
      .then((r) => r.ok ? r.json() : null)
      .then((j) => setSession(j && j.ok ? j : null))
      .catch(() => setSession(null));
  }, []);

  const signOut = async () => {
    try { await fetch('/api/portal/logout', { method: 'POST', credentials: 'same-origin' }); } catch (e) { /* ignore */ }
    setSession(null);
  };

  // Loading — show a spinner inside the rentals chrome (nav + footer wrap the page)
  if (session === undefined) {
    return (
      <main className="page active rentals-light kit-portal kit-portal-boot" data-screen-label="03b Rentals · Portal">
        <div className="kp-boot-page" aria-hidden="true">
          <div className="kp-boot-spin" />
        </div>
        <MegaFooter onGoto={onGoto} isRentals />
      </main>);
  }

  // Logged out — login card in page flow, with the rentals nav + footer
  if (!session) {
    return (
      <main className="page active rentals-light kit-portal" data-screen-label="03b Rentals · Portal · Sign in">
        <PortalLogin />
        <MegaFooter onGoto={onGoto} isRentals />
      </main>);
  }

  // Logged in — secondary tab strip below the rentals nav, then content, then footer
  return (
    <main className="page active rentals-light kit-portal kit-portal-dashboard" data-screen-label="03b Rentals · Portal">
      <PortalBar session={session} active={activeTab} setActive={setActiveTab} onSignOut={signOut} />
      <div className="kp-content">
        <div className="kp-content-inner">
          {activeTab === 'shifts'    && <PortalShifts session={session} />}
          {activeTab === 'tasks'     && <PortalTasks session={session} />}
          {activeTab === 'equipment' && <PortalEquipment session={session} />}
          {activeTab === 'sop'       && <PortalSOP />}
          {activeTab === 'rates'     && <PortalRates />}
        </div>
      </div>
      <MegaFooter onGoto={onGoto} isRentals />
    </main>);
}

// ───────────────────────────────────────────────────────────────────
// Login
// ───────────────────────────────────────────────────────────────────
function PortalLogin() {
  const [email, setEmail] = useStatePortal('');
  const [sending, setSending] = useStatePortal(false);
  const [sent, setSent] = useStatePortal(false);
  const [error, setError] = useStatePortal('');

  const submit = async (e) => {
    e.preventDefault();
    setError('');
    const trimmed = email.trim();
    if (!/^\S+@\S+\.\S+$/.test(trimmed)) { setError('Please enter a valid email.'); return; }
    setSending(true);
    try {
      await fetch('/api/portal/auth-request', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: trimmed }),
        credentials: 'same-origin',
      });
      // Always show the same confirmation regardless of whether the email
      // matched — never leak enumeration. Even network errors get the same
      // UI; the user retries with a fresh link.
      setSent(true);
    } catch (_) {
      setSent(true);
    } finally {
      setSending(false);
    }
  };

  if (sent) {
    return (
      <section className="kp-login-shell">
        <div className="kp-login-card">
          <img className="kp-login-logo" src="assets/rentals-logo-blue.png" alt="Valley Rentals" />
          <h1>Check your inbox</h1>
          <p className="kp-login-sub">If <strong>{email}</strong> is on the access list we've sent a sign-in link. It expires in 30 minutes.</p>
          <p className="kp-login-fine">Didn't arrive? Check spam, or <button type="button" className="kp-textlink" onClick={() => { setSent(false); setEmail(''); }}>try a different email</button>.</p>
        </div>
      </section>);
  }

  return (
    <section className="kp-login-shell">
      <form className="kp-login-card" onSubmit={submit} noValidate>
        <img className="kp-login-logo" src="assets/rentals-logo-blue.png" alt="Valley Rentals" />
        <h1>Kit-tech portal</h1>
        <p className="kp-login-sub">Enter your work email and we'll send a sign-in link.</p>
        <label className="kp-login-field">
          <span>Email</span>
          <input
            type="email"
            autoComplete="email"
            inputMode="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="you@example.com"
            disabled={sending}
            required />
        </label>
        {error && <div className="kp-login-error" role="alert">{error}</div>}
        <button type="submit" className="kp-btn-primary" disabled={sending}>
          {sending ? 'Sending…' : 'Send sign-in link'}
        </button>
        <p className="kp-login-fine">Only confirmed kit-techs and Valley Films staff can sign in.</p>
      </form>
    </section>);
}

// ───────────────────────────────────────────────────────────────────
// Portal secondary nav — styled to match the rentals top-nav menu pill.
// Sticks below the fixed rentals nav (which stays visible so users can
// still navigate back to the public site).
// ───────────────────────────────────────────────────────────────────
function PortalBar({ session, active, setActive, onSignOut }) {
  return (
    <div className="kp-portalbar">
      <div className="kp-portalbar-inner">
        <div className="kp-portalbar-label" aria-hidden="true">
          Kit-tech portal
        </div>
        <nav className="kp-portaltabs" role="tablist" aria-label="Portal sections">
          {PORTAL_TABS.map((t) => (
            <button
              key={t.key}
              type="button"
              role="tab"
              aria-selected={active === t.key}
              className={`kp-portaltab${active === t.key ? ' is-active' : ''}`}
              onClick={() => setActive(t.key)}>
              {t.label}
            </button>
          ))}
        </nav>
        <div className="kp-userchip">
          <span className="kp-userchip-name" title={session.email}>{session.fullName || session.email}</span>
          <span className="kp-userchip-divider" aria-hidden="true">·</span>
          <button type="button" className="kp-userchip-signout" onClick={onSignOut}>Sign out</button>
        </div>
      </div>
    </div>);
}

// ───────────────────────────────────────────────────────────────────
// Bin location card — surfaced on the default (Shifts) tab so it's the
// first thing a tech sees when arriving for a shift.
// ───────────────────────────────────────────────────────────────────
function BinLocationCard() {
  return (
    <aside className="kp-bin-card" aria-label="Storage bin access">
      <div className="kp-bin-eyebrow">Storage bin</div>
      <div className="kp-bin-grid">
        <div>
          <div className="kp-bin-key">Unit</div>
          <div className="kp-bin-val">{BIN_UNIT}</div>
        </div>
        <div>
          <div className="kp-bin-key">Code</div>
          <div className="kp-bin-val">{BIN_CODE}</div>
        </div>
      </div>
    </aside>);
}

// ───────────────────────────────────────────────────────────────────
// Tab: Shifts (placeholder — Phase 3)
// ───────────────────────────────────────────────────────────────────
function PortalShifts({ session }) {
  return (
    <div className="kp-stack">
      <div className="kp-section-head">
        <h2>Shifts</h2>
        <p>The calendar of available and booked shifts. Claim one to lock it in.</p>
      </div>
      <BinLocationCard />
      <PhasePlaceholder
        phase={3}
        title="Calendar lands in Phase 3"
        body={session.role === 'staff'
          ? 'You\'ll be able to publish open shifts (date, type, tech needed) from this tab. Kit techs claim them; you can see who\'s booked at a glance.'
          : 'You\'ll see open shifts here and be able to claim them with a tap. Booked shifts show up in your calendar.'} />
    </div>);
}

// ───────────────────────────────────────────────────────────────────
// Tab: Tasks
//
// Lists open warehouse tasks (Location=Warehouse, Status in to-do/in-progress)
// from the Notion Tasks DB via /api/portal/tasks. Anyone can mark complete or
// quick-log a Booqable/SOP/List issue; staff also get a +Add task form with
// an assignee picker. Refreshes on window focus.
// ───────────────────────────────────────────────────────────────────

// Mirror of lib/portal-staff.js for the assignee picker. Notion user IDs are
// not secrets — keeping them client-side here saves an extra round-trip.
// Update this list whenever lib/portal-staff.js changes.
const STAFF_DIRECTORY = [
  { notionUserId: '5182dfd4-1244-4e27-98b3-c9a817d62fb3', fullName: 'Max'   },
  { notionUserId: '22ed872b-594c-813b-9914-0002317e192f', fullName: 'Pete'  },
  { notionUserId: '2dcd872b-594c-8117-97fb-00022936dab7', fullName: 'Vince' },
];

const TASK_MODAL_PRESETS = {
  'booqable-issue': {
    title: 'Report a Booqable issue',
    sub: 'Something missing or wrong in Booqable — pricing, photos, item not where it should be, broken page. Drops in as a task for the team.',
    nameLabel: 'What\'s wrong?',
    namePlaceholder: 'e.g. ARRI Alexa 35 day-rate looks off',
  },
  'sop-issue': {
    title: 'Report an SOP gap',
    sub: 'Something missing or unclear in the SOP doc. The team will fill it in.',
    nameLabel: 'What needs adding or clarifying?',
    namePlaceholder: 'e.g. No instructions for cleaning Variable NDs',
  },
  'list-item': {
    title: 'List a new item',
    sub: 'A Hygglo or Booqable item to be added to the shelf. Drop the name and link.',
    nameLabel: 'Item to list',
    namePlaceholder: 'e.g. Aputure 600d Pro from Hygglo',
  },
  'add-task': {
    title: 'Add a task',
    sub: 'Create a new warehouse task. Optionally assign it to someone.',
    nameLabel: 'Task',
    namePlaceholder: 'What needs doing?',
  },
};

const PRIORITY_OPTIONS = ['Low', 'Medium', 'High', 'Immediate'];

function PortalTasks({ session }) {
  const [tasks, setTasks] = useStatePortal(null); // null = loading
  const [error, setError] = useStatePortal('');
  const [modal, setModal] = useStatePortal(null); // { type } | null
  const [completing, setCompleting] = useStatePortal({});

  const refresh = React.useCallback(async () => {
    try {
      const r = await fetch('/api/portal/tasks', { credentials: 'same-origin' });
      if (r.status === 401) { setError('Your session has expired — refresh to sign in again.'); setTasks([]); return; }
      const body = await r.json().catch(() => ({}));
      if (!r.ok || !body.ok) { setError(body.error || 'Could not load tasks.'); setTasks([]); return; }
      setError('');
      setTasks(body.tasks || []);
    } catch (e) {
      setError('Network error — could not reach the portal.');
      setTasks([]);
    }
  }, []);

  useEffectPortal(() => { refresh(); }, [refresh]);

  // Re-fetch when the tab regains focus so multiple sessions stay in sync.
  useEffectPortal(() => {
    const onFocus = () => refresh();
    window.addEventListener('focus', onFocus);
    return () => window.removeEventListener('focus', onFocus);
  }, [refresh]);

  const markComplete = async (taskId) => {
    setCompleting((c) => ({ ...c, [taskId]: true }));
    try {
      const r = await fetch(`/api/portal/tasks/${encodeURIComponent(taskId)}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ status: 'Completed' }),
        credentials: 'same-origin',
      });
      if (r.ok) {
        // Optimistic — remove from the list rather than refetching the whole thing.
        setTasks((ts) => Array.isArray(ts) ? ts.filter((t) => t.id !== taskId) : ts);
      } else {
        const body = await r.json().catch(() => ({}));
        setError(body.error || 'Could not mark complete. Try again.');
      }
    } catch (e) {
      setError('Network error — could not update the task.');
    } finally {
      setCompleting((c) => { const n = { ...c }; delete n[taskId]; return n; });
    }
  };

  return (
    <div className="kp-stack">
      <div className="kp-section-head">
        <h2>Tasks</h2>
        <p>Open warehouse tasks. Tap <strong>Mark complete</strong> when done. Use the buttons below to flag an issue or list a new item.</p>
      </div>

      <div className="kp-quicklog">
        <button type="button" className="kp-quicklog-btn" onClick={() => setModal({ type: 'booqable-issue' })}>
          <span className="kp-quicklog-icon" aria-hidden="true">⚠</span>
          <span className="kp-quicklog-text">
            <strong>Booqable issue</strong>
            <em>Pricing, listing, missing item</em>
          </span>
        </button>
        <button type="button" className="kp-quicklog-btn" onClick={() => setModal({ type: 'sop-issue' })}>
          <span className="kp-quicklog-icon" aria-hidden="true">!</span>
          <span className="kp-quicklog-text">
            <strong>SOP gap</strong>
            <em>Something missing or unclear</em>
          </span>
        </button>
        <button type="button" className="kp-quicklog-btn" onClick={() => setModal({ type: 'list-item' })}>
          <span className="kp-quicklog-icon" aria-hidden="true">+</span>
          <span className="kp-quicklog-text">
            <strong>List an item</strong>
            <em>Hygglo or Booqable addition</em>
          </span>
        </button>
        {session.role === 'staff' && (
          <button type="button" className="kp-quicklog-btn kp-quicklog-staff" onClick={() => setModal({ type: 'add-task' })}>
            <span className="kp-quicklog-icon" aria-hidden="true">★</span>
            <span className="kp-quicklog-text">
              <strong>Add task</strong>
              <em>Create &amp; assign</em>
            </span>
          </button>
        )}
      </div>

      {error && <div className="kp-error-banner" role="alert">{error}</div>}

      <div className="kp-task-list">
        {tasks === null && <div className="kp-empty">Loading…</div>}
        {tasks !== null && tasks.length === 0 && !error && (
          <div className="kp-empty">No open warehouse tasks. Nothing to do — go enjoy the sun.</div>
        )}
        {Array.isArray(tasks) && tasks.map((t) => (
          <TaskRow key={t.id} task={t} onComplete={() => markComplete(t.id)} completing={!!completing[t.id]} />
        ))}
      </div>

      {modal && (
        <TaskFormModal
          type={modal.type}
          session={session}
          onClose={() => setModal(null)}
          onSaved={() => { setModal(null); refresh(); }} />
      )}
    </div>);
}

function TaskRow({ task, onComplete, completing }) {
  const priority = task.priority || 'Medium';
  return (
    <article className="kp-task-row">
      <div className="kp-task-head">
        <span className={`kp-prio kp-prio-${priority.toLowerCase()}`}>{priority}</span>
        <span className={`kp-status kp-status-${task.status.toLowerCase().replace(/\s+/g, '-')}`}>{task.status}</span>
        {(task.tags || []).slice(0, 3).map((t) => <span key={t} className="kp-tag">{t}</span>)}
      </div>
      <h3 className="kp-task-name">{task.name}</h3>
      {task.brief && <p className="kp-task-brief">{task.brief}</p>}
      <div className="kp-task-foot">
        <div className="kp-task-info">
          {task.actionDate && <span className="kp-task-date">Action: {formatTaskDate(task.actionDate)}</span>}
          {task.link && (
            <a href={task.link} target="_blank" rel="noopener noreferrer" className="kp-task-link">
              Link <Icon name="arrow-up-right" size={11} />
            </a>
          )}
          {(task.assignees || []).map((a) => (
            <span key={a.id} className="kp-task-assignee" title={a.name || ''}>
              {a.avatar ? <img src={a.avatar} alt={a.name || ''} /> : <span className="kp-task-assignee-initials">{initials(a.name)}</span>}
            </span>
          ))}
        </div>
        <button
          type="button"
          className="kp-btn-primary kp-btn-small"
          onClick={onComplete}
          disabled={completing}>
          {completing ? 'Completing…' : 'Mark complete'}
        </button>
      </div>
    </article>);
}

function TaskFormModal({ type, session, onClose, onSaved }) {
  const preset = TASK_MODAL_PRESETS[type] || TASK_MODAL_PRESETS['add-task'];
  const isAddTask = type === 'add-task';
  const showStaffFields = isAddTask && session.role === 'staff';

  const [name, setName] = useStatePortal('');
  const [brief, setBrief] = useStatePortal('');
  const [link, setLink] = useStatePortal('');
  const [priority, setPriority] = useStatePortal('Medium');
  const [assignee, setAssignee] = useStatePortal('');
  const [saving, setSaving] = useStatePortal(false);
  const [error, setError] = useStatePortal('');

  useEffectPortal(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = prev; };
  }, [onClose]);

  const submit = async (e) => {
    e.preventDefault();
    setError('');
    if (!name.trim()) { setError('Please add a short title.'); return; }
    setSaving(true);
    try {
      const payload = { type, name: name.trim(), brief: brief.trim(), link: link.trim() };
      if (showStaffFields) {
        payload.priority = priority;
        payload.assigneeNotionId = assignee || null;
      }
      const r = await fetch('/api/portal/tasks', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
        credentials: 'same-origin',
      });
      const body = await r.json().catch(() => ({}));
      if (!r.ok || !body.ok) { setError(body.error || 'Could not save. Try again.'); return; }
      onSaved();
    } catch (_) {
      setError('Network error — could not save the task.');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="kp-modal-backdrop" role="dialog" aria-modal="true" aria-labelledby="kp-modal-title" onClick={onClose}>
      <form className="kp-modal" onClick={(e) => e.stopPropagation()} onSubmit={submit}>
        <button type="button" className="kp-modal-close" onClick={onClose} aria-label="Close">
          <Icon name="close" size={14} />
        </button>
        <h2 id="kp-modal-title">{preset.title}</h2>
        <p className="kp-modal-sub">{preset.sub}</p>

        <label className="kp-form-field">
          <span>{preset.nameLabel}</span>
          <input
            autoFocus
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder={preset.namePlaceholder}
            maxLength={200}
            required />
        </label>

        <label className="kp-form-field">
          <span>More detail (optional)</span>
          <textarea
            value={brief}
            onChange={(e) => setBrief(e.target.value)}
            rows={3}
            placeholder="Anything useful — context, kit affected, where to look."
            maxLength={2000} />
        </label>

        <label className="kp-form-field">
          <span>Link (optional)</span>
          <input
            type="url"
            value={link}
            onChange={(e) => setLink(e.target.value)}
            placeholder="https://…" />
        </label>

        {showStaffFields && (
          <div className="kp-form-row">
            <label className="kp-form-field">
              <span>Priority</span>
              <select value={priority} onChange={(e) => setPriority(e.target.value)}>
                {PRIORITY_OPTIONS.map((p) => <option key={p} value={p}>{p}</option>)}
              </select>
            </label>
            <label className="kp-form-field">
              <span>Assign to</span>
              <select value={assignee} onChange={(e) => setAssignee(e.target.value)}>
                <option value="">Unassigned</option>
                {STAFF_DIRECTORY.map((s) => (
                  <option key={s.notionUserId} value={s.notionUserId}>{s.fullName}</option>
                ))}
              </select>
            </label>
          </div>
        )}

        {error && <div className="kp-form-error" role="alert">{error}</div>}

        <div className="kp-modal-actions">
          <button type="button" className="kp-btn-ghost" onClick={onClose} disabled={saving}>Cancel</button>
          <button type="submit" className="kp-btn-primary" disabled={saving}>
            {saving ? 'Saving…' : (isAddTask ? 'Add task' : 'Log it')}
          </button>
        </div>
      </form>
    </div>);
}

function formatTaskDate(iso) {
  // Notion date strings look like "2026-06-10" or "2026-06-10T09:00:00.000+01:00".
  const d = new Date(iso);
  if (isNaN(d.getTime())) return iso;
  return d.toLocaleDateString('en-GB', { day: 'numeric', month: 'short' });
}

function initials(name) {
  if (!name) return '?';
  return name.split(/\s+/).filter(Boolean).map((p) => p[0]).join('').slice(0, 2).toUpperCase();
}

// ───────────────────────────────────────────────────────────────────
// Tab: Equipment (placeholder — Phase 5)
// ───────────────────────────────────────────────────────────────────
function PortalEquipment() {
  return (
    <div className="kp-stack">
      <div className="kp-section-head">
        <h2>Equipment</h2>
        <p>Search the live catalogue. Useful when prepping or troubleshooting an item on the shelf.</p>
      </div>
      <PhasePlaceholder
        phase={5}
        title="Equipment lookup lands in Phase 5"
        body="Search the live Booqable shelf without leaving the portal. Tap an item to see image, day rate, and a one-click 'report an issue with this item' link." />
    </div>);
}

// ───────────────────────────────────────────────────────────────────
// Tab: SOP — embedded Notion-published page with an "open in Notion"
// fallback for clients/browsers that block the embed.
// ───────────────────────────────────────────────────────────────────
function PortalSOP() {
  return (
    <div className="kp-stack">
      <div className="kp-section-head kp-section-head-row">
        <div>
          <h2>Standard operating procedure</h2>
          <p>The Valley Rentals SOP. Linked live from Notion — open in a new tab if the embed has any trouble.</p>
        </div>
        <a className="kp-btn-ghost kp-btn-ghost-link" href={SOP_URL} target="_blank" rel="noopener noreferrer">
          Open in Notion <Icon name="arrow-up-right" size={13} />
        </a>
      </div>
      <div className="kp-sop-frame">
        <iframe
          src={SOP_URL}
          title="Valley Rentals SOP"
          loading="lazy"
          referrerPolicy="no-referrer"
          allow="clipboard-write" />
      </div>
    </div>);
}

// ───────────────────────────────────────────────────────────────────
// Tab: Rates
// ───────────────────────────────────────────────────────────────────
function PortalRates() {
  return (
    <div className="kp-stack">
      <div className="kp-section-head">
        <h2>Rates &amp; billing</h2>
        <p>Pegged to the London Living Wage (currently £14.80/hr). Updated quarterly to match any new published rate.</p>
      </div>

      <div className="kp-rates-card">
        <table className="kp-rates-table">
          <thead>
            <tr>
              <th>Type</th>
              <th>Default time</th>
              <th>Length</th>
              <th>Multiplier</th>
              <th className="kp-rates-pay">Total pay</th>
            </tr>
          </thead>
          <tbody>
            {RATE_ROWS.map((r) => (
              <tr key={r.type}>
                <td><strong>{r.type}</strong></td>
                <td>{r.time}</td>
                <td>{r.length}</td>
                <td><span className="kp-mult">{r.mult}</span></td>
                <td className="kp-rates-pay"><strong>{r.pay}</strong></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="kp-bill-grid">
        <div className="kp-bill-card">
          <h3>Billing</h3>
          <p>Billed monthly on the 1st of the month for work completed the month prior. Invoices land from <a href="mailto:accounts@valley.film">accounts@valley.film</a>.</p>
          <address>
            Valley Creative LTD<br />
            Access House, 207–211 The Vale<br />
            London W3 7QS
          </address>
        </div>
        <div className="kp-bill-card">
          <h3>Raises</h3>
          <p>Rates update quarterly (if applicable) to the new published London Living Wage. We'll let you know when a change kicks in — no need to ask.</p>
        </div>
      </div>
    </div>);
}

// ───────────────────────────────────────────────────────────────────
// Shared placeholder for future-phase tabs.
// ───────────────────────────────────────────────────────────────────
function PhasePlaceholder({ phase, title, body }) {
  return (
    <div className="kp-placeholder">
      <div className="kp-placeholder-tag">Phase {phase}</div>
      <h3>{title}</h3>
      <p>{body}</p>
    </div>);
}

Object.assign(window, { KitTechPortalPage });
