/* eslint-disable */
/* Auxiliary pages: Saved, Deals, SignIn, Account, TrackOrder, Help, Contact,
   Returns, FitmentGuarantee, VinLookup, RegFinder, TorqueValues, InstallGuides,
   CrossReference, Manuals, TradeAccount, Legal, Stores, ComingSoon.
   Each component is mounted as a route from app.jsx. */

const { useState: useState_x, useMemo: useMemo_x, useEffect: useEffect_x } = React;

// ============================================================
// Reusable layout shell — TopBar + content + Footer
// ============================================================
function InfoPage({ navigate, shop, auth, openCart, openGarage, title, eyebrow, children }) {
  return (
    <div className="page">
      <window.TopBar route={{ name: "" }} navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage} />
      <div className="info-hero">
        <div className="shell">
          {eyebrow && <div className="eyebrow">{eyebrow}</div>}
          <h1 className="info-h1">{title}</h1>
        </div>
      </div>
      <div className="shell info-body">{children}</div>
      <window.Footer navigate={navigate} />
    </div>
  );
}

// ============================================================
// SavedPage — wishlist as a parts grid
// ============================================================
function SavedPage({ navigate, shop, auth, openCart, openGarage, openQuickView }) {
  const items = shop.wishlistItems || [];
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Your shortlist"
      title={items.length ? `${items.length} saved ${items.length === 1 ? "part" : "parts"}` : "No saved parts yet"}
    >
      {items.length === 0 ? (
        <div className="info-empty">
          <window.Icons.Heart />
          <h3>You haven't saved anything yet.</h3>
          <p>Tap the heart on any part to keep it here for later. Saved items sync to your browser — no account required.</p>
          <button className="btn btn-orange" onClick={() => navigate({ name: "catalog" })}>
            <window.Icons.Search /> Browse the catalogue
          </button>
        </div>
      ) : (
        <>
          <div className="info-actions">
            <button
              className="btn btn-ghost"
              onClick={() => items.forEach(p => shop.addToCart(p.id, 1))}
            >
              <window.Icons.Cart /> Add all to cart
            </button>
            <button
              className="btn btn-ghost"
              onClick={() => { if (confirm("Clear all saved parts?")) items.forEach(p => shop.toggleWishlist(p.id)); }}
            >
              Clear all
            </button>
          </div>
          <div className="parts-grid" style={{ marginTop: 24 }}>
            {items.map(p => (
              <window.PartCard key={p.id} part={p} navigate={navigate} shop={shop} onQuickView={openQuickView} />
            ))}
          </div>
        </>
      )}
    </InfoPage>
  );
}

// ============================================================
// DealsPage — picks 6 parts, marks them as discounted
// ============================================================
function DealsPage({ navigate, shop, auth, openCart, openGarage, openQuickView }) {
  const parts = window.PARTS_DATA;
  // Deterministic discount: every 3rd part is 20% off, every 5th is 30% off.
  const deals = parts.map((p, i) => ({
    part: p,
    discount: i % 5 === 0 ? 0.30 : i % 3 === 0 ? 0.20 : 0.10,
  })).slice(0, 9);

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="This month's offers"
      title="Trade deals — up to 30% off"
    >
      <p className="info-lead">Workshop-grade parts at trade prices, refreshed every Monday. All deals include the standard 2-year warranty and free returns. Trade-account customers see a further 5% at checkout.</p>
      <div className="deals-grid">
        {deals.map(d => {
          const oldPrice = d.part.price;
          const newPrice = (oldPrice * (1 - d.discount)).toFixed(0);
          return (
            <div key={d.part.id} className="deal-card" onClick={() => navigate({ name: "detail", id: d.part.id })}>
              <div className="deal-badge">-{Math.round(d.discount * 100)}%</div>
              <div className="deal-cat">{d.part.category}</div>
              <div className="deal-name">{d.part.name}</div>
              <div className="deal-sub">{d.part.subtitle}</div>
              <div className="deal-price">
                <span className="now">£{newPrice}</span>
                <span className="was">£{oldPrice}</span>
              </div>
              <div className="deal-cta">View part →</div>
            </div>
          );
        })}
      </div>
    </InfoPage>
  );
}

// ============================================================
// SignInPage — auth form (prototype, no backend)
// ============================================================
function SignInPage({ navigate, shop, auth, openCart, openGarage }) {
  const [mode, setMode] = useState_x("signin");     // "signin" | "signup"
  const [email, setEmail] = useState_x("");
  const [password, setPassword] = useState_x("");
  const [name, setName] = useState_x("");
  const [submitting, setSubmitting] = useState_x(false);
  const [error, setError] = useState_x(null);

  // Already signed in? Bounce home.
  useEffect_x(() => {
    if (auth && auth.user) navigate({ name: "account" });
  }, [auth && auth.user && auth.user.id]);

  const onSubmit = async (e) => {
    e.preventDefault();
    setError(null);
    setSubmitting(true);
    try {
      if (mode === "signup") {
        await auth.signUp(email, password, name);
      } else {
        await auth.signIn(email, password);
      }
      navigate({ name: "account" });
    } catch (err) {
      // Friendly mapping for known error codes from /api/auth/*.
      const codeMap = {
        email_in_use:        "An account already exists for that email. Try signing in instead.",
        invalid_credentials: "Email or password didn't match. Try again or sign up.",
        password_too_short:  "Password must be at least 8 characters.",
        invalid_email:       "That doesn't look like a valid email address.",
      };
      setError(codeMap[err.code] || err.message || "Something went wrong. Try again.");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop account"
      title={mode === "signin" ? "Sign in" : "Create an account"}
    >
      <div className="auth-card">
        <div className="auth-tabs">
          <button
            type="button"
            className={"auth-tab" + (mode === "signin" ? " on" : "")}
            onClick={() => { setMode("signin"); setError(null); }}
          >Sign in</button>
          <button
            type="button"
            className={"auth-tab" + (mode === "signup" ? " on" : "")}
            onClick={() => { setMode("signup"); setError(null); }}
          >Sign up</button>
        </div>

        <form onSubmit={onSubmit} autoComplete="on">
          {mode === "signup" && (
            <>
              <label className="field-label">Name <span className="field-opt">(optional)</span></label>
              <input
                type="text"
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder="Your name"
                className="auth-input"
                autoComplete="name"
              />
            </>
          )}
          <label className="field-label">Email</label>
          <input
            type="email"
            required
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="you@workshop.co.uk"
            className="auth-input"
            autoComplete="email"
          />
          <label className="field-label">
            Password {mode === "signup" && <span className="field-opt">(8+ chars)</span>}
          </label>
          <input
            type="password"
            required
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            placeholder="••••••••"
            className="auth-input"
            autoComplete={mode === "signup" ? "new-password" : "current-password"}
          />

          {error && <div className="auth-error">{error}</div>}

          <button type="submit" className="btn btn-orange" disabled={submitting} style={{ width: "100%", marginTop: 8 }}>
            {submitting ? "Working…" : (mode === "signin" ? "Sign in" : "Create account")}
          </button>
        </form>

        <div className="auth-divider"><span>or</span></div>
        <button className="btn btn-dark" style={{ width: "100%" }} onClick={() => navigate({ name: "trade-account" })}>
          <window.Icons.Tool /> Apply for a trade account
        </button>
        <p className="auth-note">
          {mode === "signin"
            ? <>Don't have an account? <a className="auth-link" onClick={() => { setMode("signup"); setError(null); }}>Sign up →</a></>
            : <>Already have one? <a className="auth-link" onClick={() => { setMode("signin"); setError(null); }}>Sign in →</a></>}
        </p>
      </div>
    </InfoPage>
  );
}

// ============================================================
// AccountPage — dashboard
// ============================================================
function AccountPage({ navigate, shop, auth, openCart, openGarage }) {
  const [orders, setOrders] = useState_x([]);
  const [loadingOrders, setLoadingOrders] = useState_x(false);
  const [ordersError, setOrdersError] = useState_x(null);

  // Not signed in (and we're past initial auth check) → bounce to sign-in.
  useEffect_x(() => {
    if (auth && !auth.loading && !auth.user) navigate({ name: "signin" });
  }, [auth && auth.loading, auth && auth.user && auth.user.id]);

  // Load orders once we have a user.
  useEffect_x(() => {
    if (!auth || !auth.user) return;
    let cancelled = false;
    setLoadingOrders(true);
    auth.fetchOrders()
      .then((list) => { if (!cancelled) { setOrders(list); setLoadingOrders(false); } })
      .catch((e) => { if (!cancelled) { setOrdersError(e.message); setLoadingOrders(false); } });
    return () => { cancelled = true; };
  }, [auth && auth.user && auth.user.id]);

  if (!auth || !auth.user) {
    return (
      <InfoPage
        navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
        eyebrow="My account" title="Sign in required"
      >
        <p className="info-lead">Redirecting to sign-in…</p>
      </InfoPage>
    );
  }

  const fmtMoney = (pence, ccy = "GBP") => {
    const v = (pence || 0) / 100;
    return ccy === "GBP" ? `£${v.toFixed(2)}` : `${v.toFixed(2)} ${ccy}`;
  };
  const fmtDate = (iso) => {
    if (!iso) return "—";
    try { return new Date(iso).toLocaleDateString("en-GB", { year: "numeric", month: "short", day: "numeric" }); }
    catch { return iso; }
  };

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow={`Signed in as ${auth.user.email}`}
      title={`Hi, ${auth.user.name || auth.user.email.split("@")[0]}`}
    >
      <div className="account-grid">
        <div className="account-card">
          <h3>Recent orders</h3>
          <p className="ac-stat">{orders.length}</p>
          <p className="ac-muted">
            {loadingOrders ? "Loading…" :
              orders.length === 0 ? "No orders yet. Once you check out they appear here." :
              `${orders.length} order${orders.length > 1 ? "s" : ""} on file.`}
          </p>
        </div>
        <div className="account-card">
          <h3>Saved vehicles</h3>
          <p className="ac-stat">{shop.garage.length}</p>
          <p className="ac-muted">{shop.garage.length === 0 ? "Add your first vehicle from the home page." : `${shop.garage.length} vehicle${shop.garage.length > 1 ? "s" : ""} in your garage.`}</p>
          <button className="btn btn-ghost" onClick={openGarage}>Open garage →</button>
        </div>
        <div className="account-card">
          <h3>Saved parts</h3>
          <p className="ac-stat">{shop.wishlist.length}</p>
          <p className="ac-muted">{shop.wishlist.length === 0 ? "Heart any part to keep it here." : `${shop.wishlist.length} part${shop.wishlist.length > 1 ? "s" : ""} on your shortlist.`}</p>
          <button className="btn btn-ghost" onClick={() => navigate({ name: "saved" })}>View shortlist →</button>
        </div>
        {auth.user.role === "admin" ? (
          <div className="account-card">
            <h3>Admin tools</h3>
            <p className="ac-muted">You have admin access. Manage orders, users, and products.</p>
            <button className="btn btn-orange" onClick={() => navigate({ name: "admin" })}>Open admin →</button>
          </div>
        ) : (
          <div className="account-card">
            <h3>Trade status</h3>
            <p className="ac-muted">Apply for a workshop account to unlock trade pricing, 30-day terms and bulk discounts.</p>
            <button className="btn btn-orange" onClick={() => navigate({ name: "trade-account" })}>Apply →</button>
          </div>
        )}
      </div>

      <section className="orders-section">
        <h2>Order history</h2>
        {loadingOrders && <p className="ac-muted">Loading orders…</p>}
        {ordersError && <p className="auth-error">{ordersError}</p>}
        {!loadingOrders && !ordersError && orders.length === 0 && (
          <div className="info-empty" style={{ margin: 0 }}>
            <window.Icons.Cart />
            <h3>No orders yet</h3>
            <p>Browse the catalogue and check out — your order history will live here.</p>
            <button className="btn btn-orange" onClick={() => navigate({ name: "catalog" })}>Browse parts →</button>
          </div>
        )}
        {orders.length > 0 && (
          <table className="orders-table">
            <thead>
              <tr>
                <th>Order</th>
                <th>Date</th>
                <th>Status</th>
                <th style={{ textAlign: "right" }}>Total</th>
              </tr>
            </thead>
            <tbody>
              {orders.map((o) => (
                <tr key={o.id}>
                  <td className="mono">#{String(o.id).padStart(5, "0")}</td>
                  <td>{fmtDate(o.created_at)}</td>
                  <td>
                    <span className={"order-status status-" + o.status}>{o.status}</span>
                  </td>
                  <td className="mono" style={{ textAlign: "right" }}>{fmtMoney(o.total_pence, o.currency)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </section>

      <div style={{ marginTop: 32, paddingTop: 20, borderTop: "1px solid var(--line)" }}>
        <button className="btn btn-ghost" onClick={async () => { await auth.signOut(); navigate({ name: "home" }); }}>
          Sign out
        </button>
      </div>
    </InfoPage>
  );
}

// ============================================================
// TrackOrderPage — order lookup form
// ============================================================
function TrackOrderPage({ navigate, shop, auth, openCart, openGarage }) {
  const [orderNo, setOrderNo] = useState_x("");
  const [email, setEmail] = useState_x("");
  const [status, setStatus] = useState_x(null);

  const lookup = (e) => {
    e.preventDefault();
    if (!/^[A-Z0-9-]{6,}$/i.test(orderNo)) {
      setStatus({ kind: "invalid" });
      return;
    }
    // Deterministic fake status from the order number hash.
    const states = [
      { kind: "ok", stage: "Picked", line: "Picker grabbed the parts at 14:22.", eta: "Dispatching by 5pm today." },
      { kind: "ok", stage: "Dispatched", line: "Left our Coventry hub on van 04.", eta: "Arrives tomorrow before 6pm." },
      { kind: "ok", stage: "Out for delivery", line: "On the courier's last run.", eta: "Arrives today before 6pm." },
      { kind: "ok", stage: "Delivered", line: "Signed for by C. PATEL.", eta: "Delivered 2 days ago." },
    ];
    let h = 0;
    for (let i = 0; i < orderNo.length; i++) h = (h * 31 + orderNo.charCodeAt(i)) >>> 0;
    setStatus(states[h % states.length]);
  };

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Order tracking"
      title="Where's my order?"
    >
      <p className="info-lead">Enter your order number (e.g. <code>FCP-83291</code>) and the email you used at checkout. We'll show the latest dispatch status.</p>
      <form className="track-form" onSubmit={lookup}>
        <div className="field-row">
          <div className="field">
            <label className="field-label">Order number</label>
            <input
              type="text"
              value={orderNo}
              onChange={(e) => setOrderNo(e.target.value.toUpperCase())}
              placeholder="FCP-83291"
              className="auth-input"
            />
          </div>
          <div className="field">
            <label className="field-label">Email at checkout</label>
            <input
              type="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              placeholder="you@workshop.co.uk"
              className="auth-input"
            />
          </div>
        </div>
        <button type="submit" className="btn btn-orange">
          <window.Icons.Search /> Track order
        </button>
      </form>
      {status && status.kind === "invalid" && (
        <div className="track-result err">
          <strong>That doesn't look like a valid order number.</strong>
          Order numbers start with <code>FCP-</code> followed by 5 digits. Check your dispatch email and try again.
        </div>
      )}
      {status && status.kind === "ok" && (
        <div className="track-result ok">
          <div className="tr-stage">{status.stage}</div>
          <div className="tr-line">{status.line}</div>
          <div className="tr-eta"><strong>ETA:</strong> {status.eta}</div>
          <div className="tr-steps">
            {["Received", "Picked", "Dispatched", "Out for delivery", "Delivered"].map(s => {
              const order = ["Received", "Picked", "Dispatched", "Out for delivery", "Delivered"];
              const reached = order.indexOf(s) <= order.indexOf(status.stage);
              return <div key={s} className={"tr-step" + (reached ? " on" : "")}>{s}</div>;
            })}
          </div>
        </div>
      )}
    </InfoPage>
  );
}

// ============================================================
// HelpPage — FAQ accordion
// ============================================================
const FAQ_ITEMS = [
  { q: "How do I find the right part for my car?", a: "Drop your UK registration plate into the finder on the home page. We look it up against DVLA records to get the make and year, then ask you to confirm the model. We then filter the catalogue to parts that fit. Alternatively, use the Make & Model tab if you don't have the reg handy." },
  { q: "What's your delivery timeframe?", a: "Standard delivery is next-working-day for orders placed before 5pm. Workshop trade accounts get same-day collection from one of our 14 UK depots. Saturday delivery is available for an extra £4.95." },
  { q: "Do you sell genuine OEM parts or aftermarket?", a: "Both. Every listing is tagged: OE-grade parts come from the same factories as the original manufacturer's parts, just without their badge; OEM parts carry the manufacturer's branding. Aftermarket parts are independent brands we've personally vetted. The product page tells you which is which." },
  { q: "What if the part doesn't fit?", a: "Free returns within 90 days, no questions asked, even if the part has been unwrapped. We pay return shipping. Our fitment guarantee means we cover the labour cost if a workshop fitted the wrong part because of our error — see the Fitment Guarantee page for details." },
  { q: "How do I get trade pricing?", a: "Apply for a trade account from the For Trade section. We verify your VAT or workshop registration within 24 hours, then your prices are automatically lowered across the site. Trade accounts also get 30-day invoice terms and bulk discounts." },
  { q: "Can I see what fits before I buy?", a: "Every product page shows verified fitment for popular vehicle platforms. If your vehicle's saved in our garage, we'll show a green Fits Your Car banner. If you're unsure, our experts answer fitment questions on the phone (0808 555 0142, 7 days)." },
  { q: "What's the difference between brake parts on the site?", a: "All our brake discs and pads meet ECE R90 (the EU type-approval standard for brake friction). Beyond that, brands vary in disc material (carbon vs. composite), pad compound (organic, semi-met, ceramic) and finish (geomet vs. zinc). The detail page lists everything." },
  { q: "How do I return something?", a: "Open your order from the Track Order page and click Start a return. We email a free postage label within 10 minutes. Pack the part in any sturdy box (the original packaging isn't required) and drop it at any Royal Mail point. Refund hits your card within 5 working days of us receiving it." },
];

function HelpPage({ navigate, shop, auth, openCart, openGarage }) {
  const [openIdx, setOpenIdx] = useState_x(0);
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Help centre"
      title="Frequently asked questions"
    >
      <p className="info-lead">Quick answers to the most common workshop and DIY questions. If you can't find it here, <a className="auth-link" onClick={() => navigate({ name: "contact" })}>contact our team</a> — real mechanics answer the phones, 7 days a week.</p>
      <div className="faq-list">
        {FAQ_ITEMS.map((item, i) => (
          <div key={i} className={"faq-item" + (openIdx === i ? " open" : "")}>
            <button className="faq-q" onClick={() => setOpenIdx(openIdx === i ? -1 : i)}>
              <span>{item.q}</span>
              <span className="faq-toggle">{openIdx === i ? "−" : "+"}</span>
            </button>
            {openIdx === i && <div className="faq-a">{item.a}</div>}
          </div>
        ))}
      </div>
      <div className="info-cta">
        <h3>Still stuck?</h3>
        <p>Speak to one of our fitters — they've seen it before.</p>
        <button className="btn btn-orange" onClick={() => navigate({ name: "contact" })}>Contact support →</button>
      </div>
    </InfoPage>
  );
}

// ============================================================
// ContactPage
// ============================================================
function ContactPage({ navigate, shop, auth, openCart, openGarage }) {
  const [submitted, setSubmitted] = useState_x(false);
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Get in touch"
      title="Contact us"
    >
      <div className="contact-grid">
        <div className="contact-card">
          <window.Icons.Phone />
          <h3>Phone</h3>
          <p className="contact-value">0808 555 0142</p>
          <p className="ac-muted">Mon–Sun · 7am – 9pm UK</p>
        </div>
        <div className="contact-card">
          <window.Icons.Headset />
          <h3>Live chat</h3>
          <p className="contact-value">Click the chat bubble</p>
          <p className="ac-muted">Average response · 90 seconds</p>
        </div>
        <div className="contact-card">
          <window.Icons.Tool />
          <h3>Email</h3>
          <p className="contact-value">workshop@easyrepair.uk</p>
          <p className="ac-muted">Replies within 1 working day</p>
        </div>
      </div>
      <h3 style={{ marginTop: 40 }}>Send us a message</h3>
      {submitted ? (
        <div className="info-empty">
          <window.Icons.Check />
          <h3>Thanks — we'll be in touch.</h3>
          <p>One of our fitters will reply within one working day.</p>
        </div>
      ) : (
        <form className="contact-form" onSubmit={(e) => { e.preventDefault(); setSubmitted(true); }}>
          <div className="field-row">
            <div className="field"><label className="field-label">Your name</label><input className="auth-input" required /></div>
            <div className="field"><label className="field-label">Email</label><input type="email" className="auth-input" required /></div>
          </div>
          <div className="field"><label className="field-label">Order number (optional)</label><input className="auth-input" placeholder="FCP-83291" /></div>
          <div className="field"><label className="field-label">How can we help?</label><textarea rows={5} className="auth-input" required /></div>
          <button type="submit" className="btn btn-orange">Send message</button>
        </form>
      )}
    </InfoPage>
  );
}

// ============================================================
// ReturnsPage
// ============================================================
function ReturnsPage({ navigate, shop, auth, openCart, openGarage }) {
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Returns & warranty"
      title="Free returns, no quibbles"
    >
      <p className="info-lead">If something doesn't fit, isn't right, or you simply changed your mind — we cover the return. Here's how it works.</p>
      <div className="returns-grid">
        <div className="returns-card">
          <div className="rg-num">90</div>
          <h3>Day window</h3>
          <p>Start a return up to 90 days from delivery. No restocking fee. Even if you've opened the box.</p>
        </div>
        <div className="returns-card">
          <div className="rg-num">£0</div>
          <h3>Cost to you</h3>
          <p>We email a Royal Mail postage label within 10 minutes of your return request. Drop it at any post office.</p>
        </div>
        <div className="returns-card">
          <div className="rg-num">5</div>
          <h3>Working days</h3>
          <p>From the moment we receive the part, refunds hit your card or account within five working days.</p>
        </div>
      </div>
      <h3 style={{ marginTop: 32 }}>What can I return?</h3>
      <ul className="info-list">
        <li><window.Icons.Check /> Any unfitted part within 90 days, in any condition (no original packaging required)</li>
        <li><window.Icons.Check /> Fitted parts that turned out to be the wrong fit, covered by our fitment guarantee</li>
        <li><window.Icons.Check /> Defective parts within the 2-year manufacturer warranty</li>
        <li><window.Icons.Check /> Workshop trade accounts: bulk returns of up to 50 units per shipment</li>
      </ul>
      <h3 style={{ marginTop: 32 }}>What can't be returned?</h3>
      <ul className="info-list">
        <li><window.Icons.Tool style={{ color: "var(--orange)" }} /> Special-order parts marked "Made to order" on the listing</li>
        <li><window.Icons.Tool style={{ color: "var(--orange)" }} /> Fluids opened and used (unopened bottles are fine)</li>
        <li><window.Icons.Tool style={{ color: "var(--orange)" }} /> Electrical parts with broken seal-stickers</li>
      </ul>
      <div className="info-cta">
        <h3>Start a return</h3>
        <p>Track your order to open a return request — we'll generate the label and instructions.</p>
        <button className="btn btn-orange" onClick={() => navigate({ name: "track-order" })}>Track an order →</button>
      </div>
    </InfoPage>
  );
}

// ============================================================
// FitmentGuaranteePage
// ============================================================
function FitmentGuaranteePage({ navigate, shop, auth, openCart, openGarage }) {
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="The Fitment Guarantee"
      title="Right part. Right car. Or we pay."
    >
      <p className="info-lead">When you tell us your vehicle (via reg plate, VIN, or make/model), we show only parts that fit. If a part listed as fitting doesn't fit, we cover the cost of fixing it — including a fitter's time.</p>
      <div className="fg-list">
        <div className="fg-item">
          <div className="fg-step">01</div>
          <div>
            <h3>Add your car</h3>
            <p>Drop your reg into the finder, save it to your garage. All catalogue filters and product pages will be pre-flagged with whether the part fits your specific vehicle.</p>
          </div>
        </div>
        <div className="fg-item">
          <div className="fg-step">02</div>
          <div>
            <h3>We verify fitment</h3>
            <p>Every product is cross-referenced against manufacturer service data. A green "Fits your car" banner means we've confirmed compatibility against the V5C make, year, and engine code.</p>
          </div>
        </div>
        <div className="fg-item">
          <div className="fg-step">03</div>
          <div>
            <h3>If we got it wrong</h3>
            <p>Free returns of the wrong part, plus we reimburse up to £80 of fitter labour if a workshop fitted it before realising. Send us the invoice — we settle within 5 working days.</p>
          </div>
        </div>
      </div>
      <h3 style={{ marginTop: 32 }}>What's covered</h3>
      <ul className="info-list">
        <li><window.Icons.Check /> Any part marked "Fits your car" that doesn't physically fit</li>
        <li><window.Icons.Check /> Up to £80 of labour cost reimbursement per incident, on production of a workshop invoice</li>
        <li><window.Icons.Check /> Free return shipping of the wrong part</li>
        <li><window.Icons.Check /> Free dispatch of the correct part within 24 hours of incident verification</li>
      </ul>
      <h3 style={{ marginTop: 32 }}>What's not covered</h3>
      <ul className="info-list">
        <li><window.Icons.Tool style={{ color: "var(--orange)" }} /> Parts bought without a saved vehicle (we couldn't pre-check fitment)</li>
        <li><window.Icons.Tool style={{ color: "var(--orange)" }} /> Non-standard modifications declared after purchase</li>
        <li><window.Icons.Tool style={{ color: "var(--orange)" }} /> Consequential damage (we cover the wrong part, not the engine that ate it)</li>
      </ul>
    </InfoPage>
  );
}

// ============================================================
// VinLookupPage — VIN input + decoded info
// ============================================================
function VinLookupPage({ navigate, shop, auth, openCart, openGarage }) {
  const [vin, setVin] = useState_x("");
  const [result, setResult] = useState_x(null);

  const decodeVin = (e) => {
    e.preventDefault();
    const v = vin.toUpperCase().replace(/[^A-Z0-9]/g, "");
    if (v.length !== 17) {
      setResult({ kind: "invalid" });
      return;
    }
    const wmiMap = {
      "WBA": "BMW (Germany)", "WBS": "BMW M (Germany)", "WVW": "Volkswagen (Germany)",
      "WAU": "Audi (Germany)", "WDB": "Mercedes-Benz (Germany)", "WP0": "Porsche (Germany)",
      "TMB": "Skoda (Czechia)", "VF7": "Citroen (France)", "VF1": "Renault (France)",
      "VF3": "Peugeot (France)", "ZFA": "Fiat (Italy)", "WF0": "Ford (Germany)",
      "MNB": "Nissan (UK)", "JTD": "Toyota (Japan)", "SAJ": "Jaguar (UK)",
    };
    const wmi = v.slice(0, 3);
    const yearChar = v.charAt(9);
    const yearMap = "ABCDEFGHJKLMNPRSTVWXY123456789";
    const yearIdx = yearMap.indexOf(yearChar);
    const year = yearIdx >= 0 ? (1980 + yearIdx) : null;
    setResult({
      kind: "ok",
      vin: v,
      manufacturer: wmiMap[wmi] || "Unknown manufacturer (WMI not in our table)",
      yearChar,
      year: year && year > 2030 ? year - 30 : year,
      plant: v.charAt(10),
      serial: v.slice(11),
    });
  };

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop tool"
      title="VIN decoder"
    >
      <p className="info-lead">Paste a 17-character VIN to decode the manufacturer, model year, plant code and serial. Find the VIN on the V5C, the windscreen base, or stamped on the chassis.</p>
      <form className="track-form" onSubmit={decodeVin}>
        <div className="field"><label className="field-label">VIN (17 characters)</label>
          <input
            type="text"
            value={vin}
            onChange={(e) => setVin(e.target.value.toUpperCase())}
            placeholder="WBASA53456FB12345"
            className="auth-input"
            style={{ fontFamily: "var(--mono)", letterSpacing: "0.06em", textTransform: "uppercase" }}
            maxLength={20}
          />
        </div>
        <button type="submit" className="btn btn-orange"><window.Icons.Search /> Decode VIN</button>
      </form>
      {result && result.kind === "invalid" && (
        <div className="track-result err">
          <strong>That doesn't look like a 17-character VIN.</strong>
          Letters I, O, Q are never used (to avoid confusion with 1 and 0). Check for spaces or extra characters.
        </div>
      )}
      {result && result.kind === "ok" && (
        <div className="track-result ok">
          <div className="vin-row">
            <div><span>VIN</span><strong style={{ fontFamily: "var(--mono)" }}>{result.vin}</strong></div>
            <div><span>Manufacturer (WMI)</span><strong>{result.manufacturer}</strong></div>
            <div><span>Model year</span><strong>{result.year || "Unknown"} <span className="ac-muted">(code: {result.yearChar})</span></strong></div>
            <div><span>Assembly plant</span><strong>{result.plant}</strong></div>
            <div><span>Serial</span><strong style={{ fontFamily: "var(--mono)" }}>{result.serial}</strong></div>
          </div>
          <p className="ac-muted" style={{ marginTop: 14 }}>VIN decoding is informational. For the full make/model/engine spec, use the Reg plate lookup which queries DVLA directly.</p>
        </div>
      )}
    </InfoPage>
  );
}

// ============================================================
// RegFinderPage — full-page version of the reg lookup
// ============================================================
function RegFinderPage({ navigate, shop, auth, openCart, openGarage }) {
  const [reg, setReg] = useState_x("");
  const [loading, setLoading] = useState_x(false);
  const [result, setResult] = useState_x(null);

  const lookup = async (e) => {
    e.preventDefault();
    if (!window.RegLookup) return;
    setLoading(true);
    const r = await window.RegLookup.lookup(reg);
    setLoading(false);
    setResult(r);
  };

  const saveAndShop = () => {
    if (!result || !result.vehicle) return;
    shop.addVehicle(result.vehicle);
    navigate({ name: "catalog" });
  };

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop tool"
      title="Reg plate finder"
    >
      <p className="info-lead">Decode any UK plate against DVLA records. Get the make, year, colour, fuel type, CO₂ rating, tax status and MOT due date — no account required.</p>
      <form className="track-form" onSubmit={lookup}>
        <div className="field"><label className="field-label">UK registration plate</label>
          <div className="reg-plate">
            <span className="reg-flag">GB</span>
            <input
              type="text"
              value={reg}
              onChange={(e) => setReg(e.target.value)}
              placeholder="AB12 CDE"
              maxLength={10}
            />
          </div>
        </div>
        <button type="submit" className="btn btn-orange" disabled={loading || !reg}>
          {loading ? <><span className="reg-spinner" /> Checking DVLA…</> : <><window.Icons.Search /> Decode plate</>}
        </button>
      </form>
      {result && (
        <div style={{ marginTop: 24 }}>
          {result.status === "hit" && result.vehicle && (
            <div className="track-result ok">
              <div className="tr-stage">{result.vehicle.year} {result.vehicle.make} {result.vehicle.model || ""}</div>
              <div className="tr-line">{result.vehicle.color} · {result.vehicle.fuel} · {result.vehicle.engine || ""}</div>
              <div className="vin-row" style={{ marginTop: 12 }}>
                <div><span>Tax status</span><strong>{result.vehicle.taxStatus}</strong></div>
                <div><span>MOT due</span><strong>{result.vehicle.motDue}</strong></div>
                <div><span>CO₂</span><strong>{result.vehicle.co2}</strong></div>
                <div><span>Region</span><strong>{result.vehicle.region}</strong></div>
              </div>
              <button className="btn btn-orange" style={{ marginTop: 14 }} onClick={saveAndShop}>
                <window.Icons.Check /> Save to garage & shop parts
              </button>
            </div>
          )}
          {result.status === "not_registered" && (
            <div className="track-result err">
              <strong>That plate isn't on DVLA's books.</strong>
              Check the spelling — letters O and 0 are easy to mix up.
            </div>
          )}
          {result.status === "unverified" && (
            <div className="track-result err">
              <strong>Couldn't reach DVLA right now.</strong>
              Try again in a moment, or use the Make &amp; Model picker on the home page.
            </div>
          )}
          {result.status === "invalid" && (
            <div className="track-result err">
              <strong>That doesn't look like a UK plate.</strong>
              Try <code>AB12 CDE</code> (two letters, two digits, three letters).
            </div>
          )}
        </div>
      )}
    </InfoPage>
  );
}

// ============================================================
// TorqueValuesPage — searchable fastener torque table
// ============================================================
const TORQUE_VALUES = [
  { component: "Wheel nuts (steel rim)", spec: "M12 × 1.5", torque: "100–110 Nm", angle: null, notes: "Star pattern. Re-torque after 100 km." },
  { component: "Wheel nuts (alloy rim)", spec: "M14 × 1.5", torque: "120–140 Nm", angle: null, notes: "Star pattern. Don't use impact gun on final pass." },
  { component: "Brake caliper carrier (front)", spec: "M14 × 1.5", torque: "110 Nm", angle: "+90°", notes: "Replace bolts each removal — single-use." },
  { component: "Brake caliper carrier (rear)", spec: "M12 × 1.25", torque: "80 Nm", angle: "+45°", notes: "Single-use bolts." },
  { component: "Brake caliper guide pin", spec: "M9", torque: "30 Nm", angle: null, notes: "Apply ceramic grease to slider boots." },
  { component: "Brake disc retaining screw", spec: "M6", torque: "12 Nm", angle: null, notes: "Optional after first fit." },
  { component: "Spark plug (16mm hex, alu head)", spec: "M14 × 1.25", torque: "23 Nm", angle: null, notes: "Use plug-specific socket only. Cold engine." },
  { component: "Spark plug (14mm hex, steel head)", spec: "M14 × 1.25", torque: "30 Nm", angle: null, notes: "Cold engine. Use anti-seize sparingly." },
  { component: "Oil drain plug (steel sump)", spec: "M14 × 1.5", torque: "30 Nm", angle: null, notes: "New crush washer each service." },
  { component: "Oil drain plug (alu sump)", spec: "M12 × 1.75", torque: "20 Nm", angle: null, notes: "New crush washer each service." },
  { component: "Oil filter housing cap (paper element)", spec: "M27", torque: "25 Nm", angle: null, notes: "Hand-tight is usually under-torqued." },
  { component: "Strut top mount (passenger car)", spec: "M14 × 1.5", torque: "60 Nm", angle: "+90°", notes: "Loaded — use stand to compress before final torque." },
  { component: "Suspension lower arm bush", spec: "M14 × 1.5", torque: "100 Nm", angle: "+45°", notes: "Torque with wheels on the ground." },
  { component: "Tie rod end (passenger)", spec: "M14 × 1.5", torque: "45 Nm", angle: null, notes: "New cotter pin or castellated nut." },
  { component: "Engine mount (transverse)", spec: "M12 × 1.75", torque: "60 Nm", angle: "+90°", notes: "Tighten with engine supported, not loaded." },
  { component: "Crankshaft pulley bolt", spec: "M16 × 1.5", torque: "150 Nm", angle: "+90° + 90°", notes: "Single-use bolt. Cold engine." },
  { component: "Cylinder head bolt (alu head)", spec: "M11", torque: "30 Nm", angle: "+90° + 90° + 90°", notes: "Single-use. Star sequence inside out." },
];

function TorqueValuesPage({ navigate, shop, auth, openCart, openGarage }) {
  const [q, setQ] = useState_x("");
  const filtered = useMemo_x(() => {
    if (!q.trim()) return TORQUE_VALUES;
    const needle = q.toLowerCase();
    return TORQUE_VALUES.filter(t => (t.component + " " + t.spec + " " + (t.notes || "")).toLowerCase().includes(needle));
  }, [q]);
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop tool"
      title="Torque values"
    >
      <p className="info-lead">Common fastener torque specs in Nm, with final-pass angle where applicable. Always cross-reference with the manufacturer's service manual for safety-critical work — these are workshop reference, not gospel.</p>
      <div className="field" style={{ marginBottom: 18 }}>
        <input
          type="text"
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="Search component, e.g. wheel nut, spark plug, crankshaft…"
          className="auth-input"
        />
      </div>
      <div className="torque-table-wrap">
        <table className="torque-table">
          <thead><tr><th>Component</th><th>Thread</th><th>Torque</th><th>Angle</th><th>Notes</th></tr></thead>
          <tbody>
            {filtered.map((t, i) => (
              <tr key={i}>
                <td><strong>{t.component}</strong></td>
                <td className="mono">{t.spec}</td>
                <td className="mono"><strong>{t.torque}</strong></td>
                <td className="mono">{t.angle || "—"}</td>
                <td className="ac-muted">{t.notes}</td>
              </tr>
            ))}
            {filtered.length === 0 && <tr><td colSpan="5" className="ac-muted" style={{ textAlign: "center", padding: 24 }}>No matches. Try a different component name.</td></tr>}
          </tbody>
        </table>
      </div>
    </InfoPage>
  );
}

// ============================================================
// InstallGuidesPage — grid of guides linked to part detail pages
// ============================================================
function InstallGuidesPage({ navigate, shop, auth, openCart, openGarage }) {
  const parts = window.PARTS_DATA;
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop tool"
      title="Install guides"
    >
      <p className="info-lead">Step-by-step fitting instructions written by working mechanics, with tools required, torque values, and a typical install time. Click a guide to open the full procedure on the part's detail page.</p>
      <div className="guides-grid">
        {parts.map(p => (
          <div key={p.id} className="guide-card" onClick={() => navigate({ name: "detail", id: p.id })}>
            <div className="guide-cat">{p.category}</div>
            <h3>{p.name}</h3>
            <div className="guide-meta">
              <span><window.Icons.Tool style={{ width: 12, height: 12 }} /> {p.difficulty}</span>
              <span><window.Icons.Reload style={{ width: 12, height: 12 }} /> {p.minutes} min</span>
              <span>{p.steps.length} steps</span>
            </div>
            <div className="guide-cta">Open guide →</div>
          </div>
        ))}
      </div>
    </InfoPage>
  );
}

// ============================================================
// CrossReferencePage — OE number → part lookup
// ============================================================
const OE_NUMBERS = {
  "06H115561B": "oil-filter",  "1K0407151AC": "suspension-spring",
  "5Q0915105K": "battery",     "078903016AB": "alternator",
  "8K0035411Q": "spark-plug",  "1K0698451M": "brake-pad",
  "5Q0615601G": "brake-disc",  "5N0820367":  "cabin-filter",
  "5N0129620A": "air-filter",  "06H905611":  "spark-plug",
};
function CrossReferencePage({ navigate, shop, auth, openCart, openGarage }) {
  const [q, setQ] = useState_x("");
  const [match, setMatch] = useState_x(null);
  const search = (e) => {
    e.preventDefault();
    const cleaned = q.toUpperCase().replace(/[\s-]/g, "");
    const partId = OE_NUMBERS[cleaned];
    if (partId) {
      const part = window.PARTS_DATA.find(p => p.id === partId);
      setMatch({ kind: "ok", oe: cleaned, part });
    } else {
      setMatch({ kind: "none", oe: cleaned });
    }
  };
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop tool"
      title="Cross-reference OE numbers"
    >
      <p className="info-lead">Enter the manufacturer's original-equipment part number and we'll find the matching catalogue entry. Useful when the dealer parts book gives you a number but you want an OE-grade aftermarket equivalent.</p>
      <form className="track-form" onSubmit={search}>
        <div className="field"><label className="field-label">OE part number</label>
          <input
            type="text"
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder="06H115561B"
            className="auth-input"
            style={{ fontFamily: "var(--mono)", letterSpacing: "0.04em" }}
          />
        </div>
        <button type="submit" className="btn btn-orange"><window.Icons.Search /> Find equivalent</button>
      </form>
      <p className="ac-muted" style={{ marginTop: 8, fontSize: 12 }}>
        Try: <code>06H115561B</code> (VAG oil filter), <code>5Q0915105K</code> (VAG battery), <code>1K0698451M</code> (VAG brake pad)
      </p>
      {match && match.kind === "ok" && (
        <div className="track-result ok" style={{ marginTop: 18 }}>
          <div className="tr-stage">Match found</div>
          <div className="tr-line">OE <strong className="mono">{match.oe}</strong> = our SKU <strong className="mono">{match.part.sku}</strong></div>
          <div className="vin-row" style={{ marginTop: 10 }}>
            <div><span>Part</span><strong>{match.part.name}</strong></div>
            <div><span>Category</span><strong>{match.part.category}</strong></div>
            <div><span>Price</span><strong>£{match.part.price}</strong></div>
          </div>
          <button className="btn btn-orange" style={{ marginTop: 14 }} onClick={() => navigate({ name: "detail", id: match.part.id })}>
            View part →
          </button>
        </div>
      )}
      {match && match.kind === "none" && (
        <div className="track-result err" style={{ marginTop: 18 }}>
          <strong>No match for {match.oe} in our cross-reference table yet.</strong>
          Try searching the catalogue by name, or call our trade desk on 0808 555 0142.
        </div>
      )}
    </InfoPage>
  );
}

// ============================================================
// ManualsPage — placeholder downloadable manuals
// ============================================================
const MANUAL_MAKES = [
  { make: "BMW",  models: ["1 Series", "3 Series", "5 Series", "X1", "X3", "X5"] },
  { make: "Audi", models: ["A1", "A3", "A4", "A6", "Q3", "Q5"] },
  { make: "Ford", models: ["Fiesta", "Focus", "Kuga", "Mondeo", "Puma"] },
  { make: "Volkswagen", models: ["Polo", "Golf", "Passat", "Tiguan", "T-Roc"] },
  { make: "Skoda", models: ["Fabia", "Octavia", "Superb", "Kodiaq", "Karoq"] },
  { make: "Toyota", models: ["Yaris", "Corolla", "C-HR", "RAV4"] },
];

function ManualsPage({ navigate, shop, auth, openCart, openGarage }) {
  const [active, setActive] = useState_x("BMW");
  const cur = MANUAL_MAKES.find(m => m.make === active) || MANUAL_MAKES[0];
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop manuals"
      title="Service & repair manuals"
    >
      <p className="info-lead">Manufacturer service intervals, torque specifications, wiring diagrams and disassembly procedures. Free PDF downloads for workshop trade-account holders; pay-per-vehicle for retail customers.</p>
      <div className="manual-makes">
        {MANUAL_MAKES.map(m => (
          <button key={m.make} className={"manual-tab" + (active === m.make ? " on" : "")} onClick={() => setActive(m.make)}>
            {m.make}
          </button>
        ))}
      </div>
      <div className="manual-list">
        {cur.models.map(model => (
          <div key={model} className="manual-row">
            <div className="manual-info">
              <h3>{cur.make} {model}</h3>
              <div className="ac-muted">Service manual · Wiring diagrams · Body repair</div>
            </div>
            <div className="manual-actions">
              <span className="badge badge-steel">PDF · ~42 MB</span>
              <button className="btn btn-ghost" onClick={() => alert("Sign in with a trade account to download.")}>
                Download
              </button>
            </div>
          </div>
        ))}
      </div>
    </InfoPage>
  );
}

// ============================================================
// TradeAccountPage
// ============================================================
function TradeAccountPage({ navigate, shop, auth, openCart, openGarage }) {
  const [submitted, setSubmitted] = useState_x(false);
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="For workshops & traders"
      title="Open a trade account"
    >
      <p className="info-lead">Trade accounts unlock workshop pricing (typically 12–25% below retail), 30-day invoice terms, free same-day depot collection, and a dedicated trade-desk number that doesn't go through IVR. Applications are reviewed within one working day.</p>
      <div className="benefits-grid">
        <div className="benefit-card">
          <window.Icons.Tool />
          <h3>Trade pricing</h3>
          <p>12–25% off retail across the catalogue, applied automatically at checkout.</p>
        </div>
        <div className="benefit-card">
          <window.Icons.Truck />
          <h3>Same-day collection</h3>
          <p>Free same-day collection from any of our 14 UK depots. Order by 1pm.</p>
        </div>
        <div className="benefit-card">
          <window.Icons.Reload />
          <h3>30-day terms</h3>
          <p>Pay by invoice with 30-day terms. Bulk returns up to 50 units per shipment.</p>
        </div>
        <div className="benefit-card">
          <window.Icons.Headset />
          <h3>Direct trade desk</h3>
          <p>Dedicated phone line, real mechanics, no IVR. Average answer time 22 seconds.</p>
        </div>
      </div>
      <h3 style={{ marginTop: 40 }}>Apply now</h3>
      {submitted ? (
        <div className="info-empty">
          <window.Icons.Check />
          <h3>Application received.</h3>
          <p>We'll verify your VAT or workshop registration and reply within one working day. Trade pricing activates automatically once approved.</p>
        </div>
      ) : (
        <form className="contact-form" onSubmit={(e) => { e.preventDefault(); setSubmitted(true); }}>
          <div className="field-row">
            <div className="field"><label className="field-label">Business name</label><input className="auth-input" required /></div>
            <div className="field"><label className="field-label">Companies House number</label><input className="auth-input" placeholder="e.g. 09384721" /></div>
          </div>
          <div className="field-row">
            <div className="field"><label className="field-label">VAT number (optional)</label><input className="auth-input" placeholder="GB123456789" /></div>
            <div className="field"><label className="field-label">Workshop type</label>
              <select className="auth-input">
                <option>Independent garage</option>
                <option>Franchise / dealer</option>
                <option>Mobile mechanic</option>
                <option>Fleet operator</option>
                <option>Body shop</option>
                <option>Other</option>
              </select>
            </div>
          </div>
          <div className="field-row">
            <div className="field"><label className="field-label">Contact name</label><input className="auth-input" required /></div>
            <div className="field"><label className="field-label">Email</label><input type="email" className="auth-input" required /></div>
          </div>
          <div className="field"><label className="field-label">Anything we should know?</label><textarea rows={3} className="auth-input" /></div>
          <button type="submit" className="btn btn-orange">Submit application</button>
        </form>
      )}
    </InfoPage>
  );
}

// ============================================================
// LegalPage — privacy / terms / cookies / slavery
// ============================================================
const LEGAL_CONTENT = {
  privacy: {
    eyebrow: "Legal",
    title: "Privacy policy",
    sections: [
      { h: "What we collect", p: "Account details (name, email), order data (parts purchased, delivery address), browsing data (pages visited, parts viewed) and your saved vehicle details. We don't sell, lease or rent your data to third parties." },
      { h: "Why we collect it", p: "To process orders, run our fitment guarantee, suggest relevant parts, and send dispatch updates. Marketing emails are opt-in only — you can unsubscribe with one click." },
      { h: "How long we keep it", p: "Order data for 7 years (HMRC requirement). Account data while the account is active, then deleted within 30 days of closure. Browsing data anonymised after 90 days." },
      { h: "Your rights", p: "Access, correct, export or delete your data at any time. Email privacy@easyrepair.uk and we'll respond within 7 days." },
      { h: "Cookies & tracking", p: "Essential cookies for cart and login. Analytics cookies (Plausible — privacy-respecting, no cross-site tracking). Marketing cookies only if you opt in." },
    ],
  },
  terms: {
    eyebrow: "Legal",
    title: "Terms & conditions",
    sections: [
      { h: "About us", p: "EasyRepair Ltd is registered in England as company number 09384721. Registered office: 4 Brindley Way, Coventry CV1 4QW. VAT number GB 247 8910 02." },
      { h: "Pricing & VAT", p: "All retail prices include UK VAT at 20%. Trade-account prices shown ex-VAT, with VAT added at checkout. Prices can change without notice; the price at order confirmation is binding." },
      { h: "Orders & delivery", p: "Standard delivery is next working day for orders before 5pm. Saturday delivery £4.95. Delivery is to the cardholder's address unless verified by phone. Risk passes to you on delivery." },
      { h: "Cancellations", p: "Cancel any order up to 1 hour after placing it for a full refund. After dispatch, follow the standard return process." },
      { h: "Liability", p: "Our maximum liability for any single order is limited to the order value plus £80 fitter-labour reimbursement under the Fitment Guarantee. Indirect or consequential losses are excluded as far as the law allows." },
    ],
  },
  cookies: {
    eyebrow: "Legal",
    title: "Cookie policy",
    sections: [
      { h: "Essential cookies", p: "Required for the site to work: cart contents, login session, your saved vehicle. Can't be disabled." },
      { h: "Functional cookies", p: "Remember your preferences — e.g. the recently-viewed strip and the workshop/garage/blueprint theme tweaks. Can be cleared via your browser." },
      { h: "Analytics", p: "We use Plausible Analytics, which doesn't set persistent cookies and doesn't track across sites. Aggregated stats only — no personal data leaves our domain." },
      { h: "Marketing", p: "Only set with your explicit opt-in via the cookie banner. Used for retargeting and conversion measurement. Off by default." },
    ],
  },
  slavery: {
    eyebrow: "Legal",
    title: "Modern slavery statement",
    sections: [
      { h: "Our commitment", p: "EasyRepair Ltd has a zero-tolerance approach to modern slavery in our operations and supply chain. We comply with the Modern Slavery Act 2015." },
      { h: "Supply chain", p: "We source parts from established manufacturers — BMW, Bosch, Brembo, Mann-Hummel, Bilstein, NGK, Varta, and direct from OE-grade producers in the EU and UK. We don't trade with regions of known forced-labour concern." },
      { h: "Due diligence", p: "Each new supplier signs our anti-slavery and human-rights commitment. Annual on-site audits of our top-10 suppliers by an independent third party." },
      { h: "Reporting concerns", p: "Email integrity@easyrepair.uk anonymously. We investigate every concern within 14 days." },
    ],
  },
};
function LegalPage({ navigate, shop, auth, openCart, openGarage, kind }) {
  const c = LEGAL_CONTENT[kind] || LEGAL_CONTENT.privacy;
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow={c.eyebrow} title={c.title}
    >
      <div className="legal-tabs">
        {Object.entries(LEGAL_CONTENT).map(([k, v]) => (
          <button key={k} className={"legal-tab" + (kind === k ? " on" : "")} onClick={() => navigate({ name: "legal", kind: k })}>
            {v.title.replace(/(policy|& conditions|statement)/, "").trim()}
          </button>
        ))}
      </div>
      <div className="legal-body">
        {c.sections.map((s, i) => (
          <div key={i} className="legal-section">
            <h3>{s.h}</h3>
            <p>{s.p}</p>
          </div>
        ))}
        <p className="ac-muted" style={{ marginTop: 32, fontSize: 12 }}>Last updated: May 2026.</p>
      </div>
    </InfoPage>
  );
}

// ============================================================
// StoresPage — depot locator placeholder
// ============================================================
const DEPOTS = [
  { city: "London Wimbledon",  postcode: "SW19 1QH", hours: "Mon–Sat 7am–6pm, Sun 9am–4pm" },
  { city: "Birmingham Aston",  postcode: "B6 7AP",   hours: "Mon–Sat 7am–6pm" },
  { city: "Manchester Trafford", postcode: "M17 8AA", hours: "Mon–Sat 7am–6pm, Sun 10am–4pm" },
  { city: "Leeds Cross Green", postcode: "LS9 0SE",  hours: "Mon–Sat 7am–6pm" },
  { city: "Glasgow Hillington", postcode: "G52 4XB", hours: "Mon–Sat 7am–6pm" },
  { city: "Bristol Avonmouth", postcode: "BS11 8HJ", hours: "Mon–Sat 7am–6pm" },
  { city: "Liverpool Speke",   postcode: "L24 8RB",  hours: "Mon–Sat 7am–6pm" },
  { city: "Newcastle Team Valley", postcode: "NE11 0RZ", hours: "Mon–Sat 7am–6pm" },
  { city: "Sheffield Tinsley", postcode: "S9 1WB",   hours: "Mon–Sat 7am–6pm" },
  { city: "Coventry Bayton Rd", postcode: "CV7 9EJ", hours: "Mon–Sat 7am–6pm" },
  { city: "Cardiff Newport Rd", postcode: "CF3 4HP", hours: "Mon–Sat 7am–6pm" },
  { city: "Edinburgh Sighthill", postcode: "EH11 4DS", hours: "Mon–Sat 7am–6pm" },
  { city: "Nottingham Lenton",  postcode: "NG7 2GR", hours: "Mon–Sat 7am–6pm" },
  { city: "Belfast Mallusk",    postcode: "BT36 4PX", hours: "Mon–Sat 7am–6pm" },
];
function StoresPage({ navigate, shop, auth, openCart, openGarage }) {
  const [q, setQ] = useState_x("");
  const filtered = DEPOTS.filter(d => (d.city + " " + d.postcode).toLowerCase().includes(q.toLowerCase()));
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Click & collect"
      title="Find a depot"
    >
      <p className="info-lead">Order before 1pm and pick up the same day from any of our 14 UK depots. Free for orders over £15. Bring your order number and a photo ID.</p>
      <div className="field" style={{ marginBottom: 18 }}>
        <input
          type="text"
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="Search by city or postcode…"
          className="auth-input"
        />
      </div>
      <div className="depots-list">
        {filtered.map(d => (
          <div key={d.postcode} className="depot-row">
            <div>
              <h3>{d.city}</h3>
              <div className="mono ac-muted">{d.postcode}</div>
            </div>
            <div className="ac-muted">{d.hours}</div>
            <button className="btn btn-ghost" onClick={() => alert(`Set ${d.city} as your collection depot.`)}>Set as default</button>
          </div>
        ))}
        {filtered.length === 0 && <div className="ac-muted" style={{ textAlign: "center", padding: 32 }}>No depots match. Try a different postcode.</div>}
      </div>
    </InfoPage>
  );
}

// ============================================================
// ComingSoonPage — generic fallback (Volume pricing, Fleet supply, etc.)
// ============================================================
function ComingSoonPage({ navigate, shop, auth, openCart, openGarage, title }) {
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Workshop pipeline"
      title={title || "Coming soon"}
    >
      <div className="info-empty">
        <window.Icons.Tool />
        <h3>We're building this out.</h3>
        <p>This page isn't live yet. In the meantime, our trade desk can help on 0808 555 0142, or apply for a trade account to get notified when it launches.</p>
        <div style={{ display: "flex", gap: 8, justifyContent: "center" }}>
          <button className="btn btn-orange" onClick={() => navigate({ name: "trade-account" })}>Apply for trade account</button>
          <button className="btn btn-ghost" onClick={() => navigate({ name: "home" })}>Back to home</button>
        </div>
      </div>
    </InfoPage>
  );
}

// ============================================================
// AdminPage — admin-only dashboard (Orders / Users / Products tabs)
// ============================================================
function AdminPage({ navigate, shop, auth, openCart, openGarage, tab = "orders" }) {
  const [activeTab, setActiveTab] = useState_x(tab);
  const [orders, setOrders] = useState_x([]);
  const [users, setUsers] = useState_x([]);
  const [loading, setLoading] = useState_x(true);
  const [error, setError] = useState_x(null);

  // Order detail view + filtering
  const [selectedOrder, setSelectedOrder] = useState_x(null);   // full order object when open
  const [loadingOrder, setLoadingOrder] = useState_x(false);
  const [savingOrder,  setSavingOrder]  = useState_x(false);
  const [trackingInput, setTrackingInput] = useState_x("");
  const [searchQuery, setSearchQuery] = useState_x("");
  const [statusFilter, setStatusFilter] = useState_x("all");

  // Gate access. Unauthed → /signin; non-admin → home.
  useEffect_x(() => {
    if (!auth || auth.loading) return;
    if (!auth.user) navigate({ name: "signin" });
    else if (auth.user.role !== "admin") navigate({ name: "home" });
  }, [auth && auth.loading, auth && auth.user && auth.user.role]);

  // Load both tabs' data once we know we're admin (small dataset; no pagination).
  useEffect_x(() => {
    if (!auth || !auth.user || auth.user.role !== "admin") return;
    let cancelled = false;
    setLoading(true);
    setError(null);
    Promise.all([
      fetch("/api/admin/orders", { credentials: "same-origin" }).then(r => r.json()),
      fetch("/api/admin/users",  { credentials: "same-origin" }).then(r => r.json()),
    ])
      .then(([o, u]) => {
        if (cancelled) return;
        setOrders(o.orders || []);
        setUsers(u.users || []);
        setLoading(false);
      })
      .catch((e) => { if (!cancelled) { setError(String(e)); setLoading(false); } });
    return () => { cancelled = true; };
  }, [auth && auth.user && auth.user.id]);

  const promote = async (userId, role) => {
    try {
      const r = await fetch("/api/admin/promote", {
        method: "POST",
        credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ userId, role }),
      });
      if (!r.ok) {
        const data = await r.json().catch(() => ({}));
        alert(data.message || data.error || `Failed (${r.status})`);
        return;
      }
      setUsers((us) => us.map((u) => (u.id === userId ? { ...u, role } : u)));
    } catch (e) {
      alert(`Network error: ${e.message}`);
    }
  };

  // ---- Order detail + actions ----
  const openOrder = async (orderId) => {
    setLoadingOrder(true);
    try {
      const r = await fetch(`/api/admin/orders?id=${orderId}`, { credentials: "same-origin" });
      const data = await r.json();
      if (!r.ok) throw new Error(data.message || data.error || `Failed (${r.status})`);
      setSelectedOrder(data.order);
      setTrackingInput((data.order.metadata && data.order.metadata.tracking_number) || "");
    } catch (e) {
      alert(`Failed to load order: ${e.message}`);
    } finally {
      setLoadingOrder(false);
    }
  };
  const closeOrder = () => { setSelectedOrder(null); setTrackingInput(""); };

  const changeStatus = async (newStatus) => {
    if (!selectedOrder) return;
    const confirmMsg = newStatus === "cancelled"
      ? "Cancel this order? The customer won't be refunded automatically — use 'Issue refund' for that."
      : `Mark this order as ${newStatus}?`;
    if (!window.confirm(confirmMsg)) return;
    setSavingOrder(true);
    try {
      const body = { id: selectedOrder.id, status: newStatus };
      if (newStatus === "shipped" && trackingInput) body.trackingNumber = trackingInput;
      const r = await fetch("/api/admin/orders", {
        method: "POST",
        credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
      const data = await r.json();
      if (!r.ok) throw new Error(data.message || data.error || `Failed (${r.status})`);
      await openOrder(selectedOrder.id);
      setOrders((os) => os.map((o) => o.id === selectedOrder.id ? { ...o, status: newStatus } : o));
    } catch (e) {
      alert(`Failed: ${e.message}`);
    } finally {
      setSavingOrder(false);
    }
  };

  const refundOrder = async () => {
    if (!selectedOrder) return;
    const amt = (selectedOrder.total_pence / 100).toFixed(2);
    if (!window.confirm(`Issue a FULL refund of £${amt} via Stripe? This cannot be undone.`)) return;
    setSavingOrder(true);
    try {
      const r = await fetch("/api/admin/orders", {
        method: "POST",
        credentials: "same-origin",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: selectedOrder.id, action: "refund" }),
      });
      const data = await r.json();
      if (!r.ok) throw new Error(data.message || data.error || `Failed (${r.status})`);
      await openOrder(selectedOrder.id);
      setOrders((os) => os.map((o) => o.id === selectedOrder.id ? { ...o, status: "refunded" } : o));
      alert(`Refund issued. Stripe refund ID: ${data.refundId}`);
    } catch (e) {
      alert(`Refund failed: ${e.message}`);
    } finally {
      setSavingOrder(false);
    }
  };

  // ---- Filtered orders for the list ----
  const filteredOrders = useMemo_x(() => {
    let list = orders;
    if (statusFilter !== "all") list = list.filter((o) => o.status === statusFilter);
    if (searchQuery.trim()) {
      const q = searchQuery.trim().toLowerCase();
      list = list.filter((o) =>
        String(o.id).includes(q) ||
        (o.user_email || "").toLowerCase().includes(q) ||
        (o.email || "").toLowerCase().includes(q) ||
        (o.user_name || "").toLowerCase().includes(q)
      );
    }
    return list;
  }, [orders, statusFilter, searchQuery]);

  const fmtMoney = (pence, ccy = "GBP") => `${ccy === "GBP" ? "£" : ""}${((pence || 0) / 100).toFixed(2)}${ccy !== "GBP" ? " " + ccy : ""}`;
  const fmtDate = (iso) => {
    if (!iso) return "—";
    try { return new Date(iso).toLocaleString("en-GB"); } catch { return iso; }
  };
  const fmtAddress = (addr) => {
    if (!addr) return null;
    // Stripe shipping_details shape: { name, address: { line1, line2, city, postal_code, state, country } }
    const a = addr.address || addr;
    const name = addr.name || "";
    const phone = addr.phone || "";
    return { name, phone, line1: a.line1 || "", line2: a.line2 || "", city: a.city || "", postcode: a.postal_code || a.postcode || "", state: a.state || "", country: a.country || "" };
  };

  if (!auth || !auth.user || auth.user.role !== "admin") {
    return (
      <InfoPage
        navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
        eyebrow="Admin" title="Verifying access…"
      ><p className="info-lead">Checking your permissions.</p></InfoPage>
    );
  }

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow={`Signed in as ${auth.user.email}`}
      title="Admin dashboard"
    >
      <div className="auth-tabs" style={{ marginBottom: 24 }}>
        <button className={"auth-tab" + (activeTab === "orders"   ? " on" : "")} onClick={() => setActiveTab("orders")}>Orders {orders.length > 0 && <span style={{ opacity: 0.5 }}>({orders.length})</span>}</button>
        <button className={"auth-tab" + (activeTab === "users"    ? " on" : "")} onClick={() => setActiveTab("users")}>Users {users.length > 0 && <span style={{ opacity: 0.5 }}>({users.length})</span>}</button>
        <button className={"auth-tab" + (activeTab === "products" ? " on" : "")} onClick={() => setActiveTab("products")}>Products {window.PARTS_DATA && <span style={{ opacity: 0.5 }}>({window.PARTS_DATA.length})</span>}</button>
      </div>

      {loading && <p className="info-lead">Loading…</p>}
      {error && <div className="auth-error">{error}</div>}

      {!loading && activeTab === "orders" && !selectedOrder && (
        orders.length === 0 ? <p className="ac-muted">No orders yet.</p> : (
          <>
            <div className="admin-filters">
              <input
                type="search"
                className="admin-search"
                placeholder="Search by order #, customer email, or name…"
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
              />
              <select
                className="admin-status-filter"
                value={statusFilter}
                onChange={(e) => setStatusFilter(e.target.value)}
              >
                <option value="all">All statuses</option>
                <option value="pending">Pending</option>
                <option value="paid">Paid</option>
                <option value="shipped">Shipped</option>
                <option value="delivered">Delivered</option>
                <option value="cancelled">Cancelled</option>
                <option value="refunded">Refunded</option>
              </select>
              <span className="admin-count">
                {filteredOrders.length === orders.length
                  ? `${orders.length} order${orders.length === 1 ? "" : "s"}`
                  : `${filteredOrders.length} of ${orders.length}`}
              </span>
            </div>

            {filteredOrders.length === 0 ? (
              <p className="ac-muted">No orders match the current filters.</p>
            ) : (
              <table className="orders-table orders-clickable">
                <thead>
                  <tr>
                    <th>Order</th><th>Date</th><th>Customer</th><th>Items</th>
                    <th>Status</th><th style={{ textAlign: "right" }}>Total</th>
                  </tr>
                </thead>
                <tbody>
                  {filteredOrders.map((o) => (
                    <tr key={o.id} onClick={() => openOrder(o.id)}>
                      <td className="mono">#{String(o.id).padStart(5, "0")}</td>
                      <td>{fmtDate(o.created_at)}</td>
                      <td>{o.user_email || o.email || <span className="ac-muted">guest</span>}</td>
                      <td>{o.item_count}</td>
                      <td><span className={"order-status status-" + o.status}>{o.status}</span></td>
                      <td className="mono" style={{ textAlign: "right" }}>{fmtMoney(o.total_pence, o.currency)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </>
        )
      )}

      {!loading && activeTab === "orders" && selectedOrder && (() => {
        const o = selectedOrder;
        const addr = fmtAddress(o.shipping_address);
        const meta = o.metadata || {};
        return (
          <div className="order-detail">
            <button className="btn btn-ghost" onClick={closeOrder} style={{ marginBottom: 16 }}>
              ← Back to orders
            </button>

            <div className="od-head">
              <div>
                <div className="od-eyebrow">Order</div>
                <h2 className="od-id">#{String(o.id).padStart(5, "0")}</h2>
                <div className="od-meta">
                  <span className={"order-status status-" + o.status}>{o.status}</span>
                  <span>·  Placed {fmtDate(o.created_at)}</span>
                  {o.updated_at && o.updated_at !== o.created_at && <span>·  Updated {fmtDate(o.updated_at)}</span>}
                </div>
              </div>
              <div className="od-total">
                <div className="od-total-num mono">{fmtMoney(o.total_pence, o.currency)}</div>
                <div className="od-total-tax">inc. VAT</div>
              </div>
            </div>

            {loadingOrder && <p className="ac-muted">Refreshing…</p>}

            <div className="od-grid">
              <section className="od-panel">
                <h4>Customer</h4>
                <p><strong>{o.user_name || addr?.name || "—"}</strong></p>
                <p className="mono" style={{ fontSize: 12 }}>{o.user_email || o.email || "(guest checkout)"}</p>
                {o.user_id && <p className="ac-muted" style={{ fontSize: 12 }}>User ID #{o.user_id}</p>}
              </section>

              <section className="od-panel">
                <h4>Shipping address</h4>
                {addr ? (
                  <address style={{ fontStyle: "normal", lineHeight: 1.6 }}>
                    {addr.name && <>{addr.name}<br /></>}
                    {addr.line1}<br />
                    {addr.line2 && <>{addr.line2}<br /></>}
                    {addr.city}{addr.state ? `, ${addr.state}` : ""}<br />
                    {addr.postcode}<br />
                    {addr.country}
                    {addr.phone && <><br /><span className="mono" style={{ fontSize: 12 }}>☎ {addr.phone}</span></>}
                  </address>
                ) : <p className="ac-muted">No address captured.</p>}
              </section>
            </div>

            <h4 className="od-section-h">Items ({o.items?.length || 0})</h4>
            <table className="orders-table" style={{ marginTop: 6 }}>
              <thead>
                <tr>
                  <th>SKU</th><th>Part</th><th style={{ textAlign: "right" }}>Qty</th>
                  <th style={{ textAlign: "right" }}>Unit</th><th style={{ textAlign: "right" }}>Subtotal</th>
                </tr>
              </thead>
              <tbody>
                {(o.items || []).map((it) => (
                  <tr key={it.id}>
                    <td className="mono">{it.part_sku || "—"}</td>
                    <td>{it.part_name}</td>
                    <td className="mono" style={{ textAlign: "right" }}>{it.qty}</td>
                    <td className="mono" style={{ textAlign: "right" }}>{fmtMoney(it.unit_price_pence, o.currency)}</td>
                    <td className="mono" style={{ textAlign: "right" }}>{fmtMoney(it.unit_price_pence * it.qty, o.currency)}</td>
                  </tr>
                ))}
                <tr><td colSpan="4" style={{ textAlign: "right", paddingTop: 12, color: "var(--ink-2)" }}>Subtotal</td>
                    <td className="mono" style={{ textAlign: "right", paddingTop: 12 }}>{fmtMoney(o.subtotal_pence, o.currency)}</td></tr>
                <tr><td colSpan="4" style={{ textAlign: "right", color: "var(--ink-2)" }}>Shipping</td>
                    <td className="mono" style={{ textAlign: "right" }}>{o.shipping_pence === 0 ? "FREE" : fmtMoney(o.shipping_pence, o.currency)}</td></tr>
                <tr><td colSpan="4" style={{ textAlign: "right", fontWeight: 600 }}>Total</td>
                    <td className="mono" style={{ textAlign: "right", fontWeight: 700 }}>{fmtMoney(o.total_pence, o.currency)}</td></tr>
              </tbody>
            </table>

            {/* Status actions */}
            <h4 className="od-section-h">Actions</h4>
            <div className="od-actions">
              {o.status === "paid" && (
                <>
                  <div className="od-action-row">
                    <input
                      type="text"
                      className="od-tracking-input"
                      placeholder="Tracking number (optional, e.g. RM1234..."
                      value={trackingInput}
                      onChange={(e) => setTrackingInput(e.target.value)}
                    />
                    <button className="btn btn-orange" disabled={savingOrder} onClick={() => changeStatus("shipped")}>
                      Mark as shipped
                    </button>
                  </div>
                  <div className="od-action-row">
                    <button className="btn btn-dark" disabled={savingOrder} onClick={refundOrder}>
                      Issue refund (£{(o.total_pence / 100).toFixed(2)})
                    </button>
                    <button className="btn btn-ghost" disabled={savingOrder} onClick={() => changeStatus("cancelled")}>
                      Cancel order (no refund)
                    </button>
                  </div>
                </>
              )}
              {o.status === "shipped" && (
                <>
                  {meta.tracking_number && (
                    <p className="ac-muted">Shipped with tracking: <strong className="mono">{meta.tracking_number}</strong> on {fmtDate(meta.shipped_at)}</p>
                  )}
                  <button className="btn btn-orange" disabled={savingOrder} onClick={() => changeStatus("delivered")}>
                    Mark as delivered
                  </button>
                </>
              )}
              {o.status === "delivered" && (
                <p className="ac-muted">Order completed. No further actions.</p>
              )}
              {o.status === "refunded" && meta.refund_id && (
                <p className="ac-muted">Refunded on {fmtDate(meta.refunded_at)}. Stripe refund ID: <strong className="mono">{meta.refund_id}</strong></p>
              )}
              {o.status === "cancelled" && (
                <p className="ac-muted">Cancelled on {fmtDate(meta.cancelled_at || o.updated_at)}.</p>
              )}
              {o.status === "pending" && (
                <p className="ac-muted">Pending payment. Once Stripe's webhook fires, this'll flip to paid automatically.</p>
              )}
            </div>

            <details className="od-stripe-refs">
              <summary>Stripe references</summary>
              <p className="mono" style={{ fontSize: 12 }}>
                {o.stripe_payment_intent_id && <>PaymentIntent: <a href={`https://dashboard.stripe.com/payments/${o.stripe_payment_intent_id}`} target="_blank" rel="noreferrer">{o.stripe_payment_intent_id}</a><br /></>}
                {o.stripe_session_id && o.stripe_session_id !== o.stripe_payment_intent_id && <>Session/Intent ID stored: {o.stripe_session_id}</>}
              </p>
            </details>
          </div>
        );
      })()}

      {!loading && activeTab === "users" && (
        users.length === 0 ? <p className="ac-muted">No users yet.</p> : (
          <table className="orders-table">
            <thead>
              <tr><th>ID</th><th>Email</th><th>Name</th><th>Role</th><th>Joined</th><th></th></tr>
            </thead>
            <tbody>
              {users.map((u) => (
                <tr key={u.id}>
                  <td className="mono">#{u.id}</td>
                  <td>{u.email}</td>
                  <td>{u.name || <span className="ac-muted">—</span>}</td>
                  <td>
                    <span className={"order-status status-" + (u.role === "admin" ? "delivered" : "pending")}>
                      {u.role}
                    </span>
                  </td>
                  <td>{fmtDate(u.created_at)}</td>
                  <td style={{ textAlign: "right" }}>
                    {u.id === auth.user.id ? (
                      <span className="ac-muted">(you)</span>
                    ) : u.role === "admin" ? (
                      <button className="btn btn-ghost btn-sm" onClick={() => promote(u.id, "customer")}>Demote</button>
                    ) : (
                      <button className="btn btn-orange btn-sm" onClick={() => promote(u.id, "admin")}>Promote to admin</button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )
      )}

      {!loading && activeTab === "products" && (
        <div>
          <p className="ac-muted" style={{ marginBottom: 16 }}>
            Read-only view of the catalogue. To change products, regenerate
            <code style={{ margin: "0 4px" }}>parts-data.js</code> via the import scripts.
          </p>
          <table className="orders-table">
            <thead>
              <tr><th>SKU</th><th>Name</th><th>Category</th><th>Brand</th><th>Fits</th><th style={{ textAlign: "right" }}>Price</th></tr>
            </thead>
            <tbody>
              {(window.PARTS_DATA || []).slice(0, 100).map((p) => (
                <tr key={p.id}>
                  <td className="mono">{p.sku}</td>
                  <td>{p.name}</td>
                  <td>{p.category}</td>
                  <td>{p.brand || "—"}</td>
                  <td>{(p.fits || []).length}</td>
                  <td className="mono" style={{ textAlign: "right" }}>£{(p.price || 0).toFixed(2)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {window.PARTS_DATA && window.PARTS_DATA.length > 100 && (
            <p className="ac-muted" style={{ marginTop: 12 }}>
              Showing first 100 of {window.PARTS_DATA.length}.
            </p>
          )}
        </div>
      )}
    </InfoPage>
  );
}

// ============================================================
// CheckoutPage — in-page Stripe Elements (Payment + Address)
// ============================================================
function CheckoutPage({ navigate, shop, auth, openCart, openGarage }) {
  const [config, setConfig] = useState_x(null);
  const [clientSecret, setClientSecret] = useState_x(null);
  const [intentId, setIntentId] = useState_x(null);
  const [amounts, setAmounts] = useState_x(null);  // { subtotalPence, shippingPence, amountPence }
  const [submitting, setSubmitting] = useState_x(false);
  const [error, setError] = useState_x(null);
  const [stripeReady, setStripeReady] = useState_x(false);

  const stripeRef = window.React.useRef(null);
  const elementsRef = window.React.useRef(null);
  const addressDomRef = window.React.useRef(null);
  const paymentDomRef = window.React.useRef(null);
  const mountedRef = window.React.useRef(false);

  // Empty cart → bounce.
  useEffect_x(() => {
    if (!shop.cart || shop.cart.length === 0) navigate({ name: "catalog" });
  }, []);

  // 1. Load /api/config to get publishable key, then init Stripe.
  // 2. Create PaymentIntent on /api/checkout/intent for current cart.
  // 3. Once both are ready, mount Address + Payment elements.
  useEffect_x(() => {
    if (!shop.cart || shop.cart.length === 0) return;
    if (!window.Stripe) {
      setError("Stripe.js failed to load — check your network connection.");
      return;
    }
    let cancelled = false;
    (async () => {
      try {
        // /api/config
        const cfgRes = await fetch("/api/config");
        const cfg = await cfgRes.json();
        if (cancelled) return;
        if (!cfg.publishableKey) {
          setError("Stripe is not configured on the server (STRIPE_PUBLISHABLE_KEY missing).");
          return;
        }
        setConfig(cfg);
        stripeRef.current = window.Stripe(cfg.publishableKey);

        // /api/checkout/intent
        const intentRes = await fetch("/api/checkout/intent", {
          method: "POST",
          credentials: "same-origin",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ items: shop.cart.map((c) => ({ id: c.id, qty: c.qty })) }),
        });
        const intentData = await intentRes.json();
        if (cancelled) return;
        if (!intentRes.ok) {
          setError(intentData.message || intentData.error || `Checkout failed (${intentRes.status})`);
          return;
        }
        setClientSecret(intentData.clientSecret);
        setIntentId(intentData.intentId);
        setAmounts({
          subtotalPence: intentData.subtotalPence,
          shippingPence: intentData.shippingPence,
          amountPence:   intentData.amountPence,
        });
      } catch (err) {
        if (!cancelled) setError(err.message);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // Once we have clientSecret + DOM nodes are mounted, build the Stripe Elements.
  useEffect_x(() => {
    if (!clientSecret || !stripeRef.current) return;
    if (!addressDomRef.current || !paymentDomRef.current) return;
    if (mountedRef.current) return;
    mountedRef.current = true;

    const elements = stripeRef.current.elements({
      clientSecret,
      appearance: {
        theme: "stripe",
        variables: {
          colorPrimary: "#ff5a1f",
          colorBackground: "#ffffff",
          colorText: "#141414",
          fontFamily: '"IBM Plex Sans", system-ui, -apple-system, Segoe UI, sans-serif',
          borderRadius: "2px",
          spacingUnit: "4px",
        },
      },
    });
    elementsRef.current = elements;

    const addressElement = elements.create("address", {
      mode: "shipping",
      allowedCountries: ["GB"],
      // Disable Stripe's address autocomplete so the full form (line 1, line 2,
      // city, postcode, county) renders up front instead of collapsing into a
      // single search box.
      autocomplete: { mode: "disabled" },
      // Always render Address line 2 (flat number, building, c/o, etc.).
      display: { name: "split" },     // splits "Full name" into First + Last
      // Phone is critical for parcel delivery exception calls.
      fields: { phone: "always" },
      validation: { phone: { required: "always" } },
      defaultValues: auth && auth.user
        ? {
            name: auth.user.name || "",
            address: { country: "GB" },
          }
        : { address: { country: "GB" } },
    });
    addressElement.mount(addressDomRef.current);

    const paymentElement = elements.create("payment", { layout: "tabs" });
    paymentElement.mount(paymentDomRef.current);

    paymentElement.on("ready", () => setStripeReady(true));
  }, [clientSecret]);

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!stripeRef.current || !elementsRef.current) return;
    setSubmitting(true);
    setError(null);
    const { error: confirmError } = await stripeRef.current.confirmPayment({
      elements: elementsRef.current,
      confirmParams: {
        return_url: `${window.location.origin}/?route=checkout-success`,
      },
    });
    // confirmPayment redirects on success. We only get here if there was an
    // immediate error (e.g. card declined, validation failed).
    if (confirmError) {
      setError(confirmError.message || "Payment failed. Try a different card.");
      setSubmitting(false);
    }
  };

  const fmtMoney = (pence) => `£${((pence || 0) / 100).toFixed(2)}`;

  // Items derived from the cart × PARTS_DATA for the summary side.
  const cartLines = (shop.cart || []).map((c) => {
    const p = (window.PARTS_DATA || []).find((x) => x.id === c.id);
    return p ? { ...c, part: p } : null;
  }).filter(Boolean);

  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Secure payment via Stripe"
      title="Checkout"
    >
      <div className="checkout-grid">
        {/* LEFT — Order summary */}
        <aside className="checkout-summary">
          <h3>Order summary</h3>
          <div className="checkout-items">
            {cartLines.map((c) => (
              <div className="checkout-item" key={c.id}>
                <div className="ci-thumb">
                  {c.part.image ? (
                    <img src={c.part.image} alt={c.part.name} onError={(e) => { e.target.style.display = "none"; }} />
                  ) : <window.Icons.Tool style={{ opacity: 0.4 }} />}
                </div>
                <div className="ci-info">
                  <div className="ci-name">{c.part.name}</div>
                  <div className="ci-meta">{c.part.brand || "OEM"} · Qty {c.qty}</div>
                </div>
                <div className="ci-price mono">£{(c.part.price * c.qty).toFixed(2)}</div>
              </div>
            ))}
          </div>
          {amounts && (
            <div className="checkout-totals">
              <div className="ct-line"><span>Subtotal</span><span className="mono">{fmtMoney(amounts.subtotalPence)}</span></div>
              <div className="ct-line"><span>Delivery</span><span className="mono">{amounts.shippingPence === 0 ? "FREE" : fmtMoney(amounts.shippingPence)}</span></div>
              <div className="ct-line ct-total"><span>Total</span><span className="mono">{fmtMoney(amounts.amountPence)}</span></div>
              <div className="ct-tax">inc. VAT</div>
            </div>
          )}
          <button type="button" className="btn btn-ghost btn-block" onClick={() => navigate({ name: "catalog" })} style={{ marginTop: 16 }}>
            ← Continue shopping
          </button>
        </aside>

        {/* RIGHT — Stripe Elements */}
        <form className="checkout-form" onSubmit={onSubmit}>
          <section className="checkout-section">
            <h3>Shipping address</h3>
            <div ref={addressDomRef} className="stripe-mount" />
          </section>

          <section className="checkout-section">
            <h3>Payment details</h3>
            <div ref={paymentDomRef} className="stripe-mount" />
            <p className="checkout-note">
              Card details are sent directly to Stripe — they never touch our server.
              We support Visa, Mastercard, Amex, plus Apple Pay and Google Pay where available.
            </p>
          </section>

          {error && <div className="auth-error">{error}</div>}

          <button
            type="submit"
            className="btn btn-orange btn-lg"
            style={{ width: "100%" }}
            disabled={submitting || !stripeReady || !clientSecret}
          >
            {submitting
              ? "Processing…"
              : !clientSecret
                ? "Preparing checkout…"
                : !stripeReady
                  ? "Loading payment methods…"
                  : amounts
                    ? `Pay ${fmtMoney(amounts.amountPence)}`
                    : "Pay now"}
          </button>
          <p className="checkout-note" style={{ textAlign: "center" }}>
            🔒 Encrypted by Stripe. Your card information is never stored on our servers.
          </p>
        </form>
      </div>
    </InfoPage>
  );
}

// ============================================================
// CheckoutSuccessPage — Stripe redirects here after a successful pay
// ============================================================
function CheckoutSuccessPage({ navigate, shop, auth, openCart, openGarage, sessionId }) {
  // Clear the cart on first mount so it's empty when they go back to shop.
  useEffect_x(() => { try { shop.clearCart(); } catch {} }, []);
  // Clean the URL so refreshes don't keep re-mounting this page.
  useEffect_x(() => {
    if (typeof window !== "undefined" && window.history && window.history.replaceState) {
      window.history.replaceState({}, "", window.location.pathname);
    }
  }, []);
  return (
    <InfoPage
      navigate={navigate} shop={shop} auth={auth} openCart={openCart} openGarage={openGarage}
      eyebrow="Payment received"
      title="Order confirmed"
    >
      <div className="info-empty" style={{ textAlign: "center" }}>
        <window.Icons.Check style={{ width: 40, height: 40, color: "var(--green)" }} />
        <h3>Thanks — your order is in the workshop queue.</h3>
        <p>
          We've emailed a receipt to your address on file. Your order also appears in your account
          history within a minute or two (Stripe's webhook writes it asynchronously).
        </p>
        {sessionId && (
          <p style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--ink-2)" }}>
            Session: <strong>{sessionId.slice(0, 14)}…{sessionId.slice(-6)}</strong>
          </p>
        )}
        <div style={{ display: "flex", gap: 12, justifyContent: "center", marginTop: 16 }}>
          {auth && auth.user
            ? <button className="btn btn-orange" onClick={() => navigate({ name: "account" })}>View my orders →</button>
            : <button className="btn btn-orange" onClick={() => navigate({ name: "signin" })}>Sign in to track →</button>
          }
          <button className="btn btn-ghost" onClick={() => navigate({ name: "catalog" })}>Keep shopping</button>
        </div>
      </div>
    </InfoPage>
  );
}

// ============================================================
// Export all pages on window
// ============================================================
window.SavedPage = SavedPage;
window.DealsPage = DealsPage;
window.SignInPage = SignInPage;
window.AccountPage = AccountPage;
window.TrackOrderPage = TrackOrderPage;
window.HelpPage = HelpPage;
window.ContactPage = ContactPage;
window.ReturnsPage = ReturnsPage;
window.FitmentGuaranteePage = FitmentGuaranteePage;
window.VinLookupPage = VinLookupPage;
window.RegFinderPage = RegFinderPage;
window.TorqueValuesPage = TorqueValuesPage;
window.InstallGuidesPage = InstallGuidesPage;
window.CrossReferencePage = CrossReferencePage;
window.ManualsPage = ManualsPage;
window.TradeAccountPage = TradeAccountPage;
window.LegalPage = LegalPage;
window.StoresPage = StoresPage;
window.ComingSoonPage = ComingSoonPage;
window.CheckoutPage = CheckoutPage;
window.CheckoutSuccessPage = CheckoutSuccessPage;
window.AdminPage = AdminPage;
