// VEXEL — Legal & info pages (privacy, terms, faq, code-of-conduct, anti-cheat, 404)

function LegalShell({ eyebrow, title, lede, version, children }) {
  return (
    <div style={{ background: "var(--ink)", minHeight: "60vh" }}>
      <div className="bg-grid" style={{ borderBottom: "1px solid var(--line)", padding: "64px var(--gutter) 56px" }}>
        <div className="shell">
          <div className="t-eyebrow" style={{ color: "var(--cyan)" }}>{eyebrow}</div>
          <h1 className="t-display" style={{ fontSize: 76, marginTop: 12 }}>{title}</h1>
          {lede && <p style={{ color: "var(--text-dim)", fontSize: 17, maxWidth: 720, marginTop: 18 }}>{lede}</p>}
          {version && <p className="t-mono" style={{ color: "var(--text-mute)", fontSize: 12, marginTop: 24, letterSpacing: "0.15em" }}>{version}</p>}
        </div>
      </div>
      <div className="shell" style={{ padding: "64px 0 120px", display: "grid", gridTemplateColumns: "260px 1fr", gap: 64 }}>
        {children}
      </div>
    </div>
  );
}

function LegalTOC({ items, active, onClick }) {
  return (
    <aside style={{ position: "sticky", top: 120, alignSelf: "start" }}>
      <div className="t-eyebrow" style={{ marginBottom: 16 }}>On this page</div>
      <ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: 6, borderLeft: "1px solid var(--line)" }}>
        {items.map(({ id, label }) => (
          <li key={id}>
            <a onClick={() => onClick(id)} style={{
              display: "block", padding: "6px 0 6px 16px",
              fontSize: 13, cursor: "pointer",
              color: active === id ? "var(--cyan)" : "var(--text-dim)",
              borderLeft: active === id ? "1px solid var(--cyan)" : "1px solid transparent",
              marginLeft: -1, transition: "all 0.15s"
            }}>{label}</a>
          </li>
        ))}
      </ul>
    </aside>
  );
}

function Prose({ children }) {
  return (
    <article style={{ maxWidth: 720, color: "var(--text-dim)", fontSize: 15, lineHeight: 1.8 }}>
      {children}
    </article>
  );
}

function H2({ id, children }) {
  return <h2 id={id} className="t-display" style={{ fontSize: 36, color: "var(--white)", margin: "56px 0 16px", scrollMarginTop: 120 }}>{children}</h2>;
}

function H3({ children }) {
  return <h3 style={{ fontSize: 17, color: "var(--white)", margin: "28px 0 10px", fontWeight: 700, letterSpacing: 0 }}>{children}</h3>;
}

function Callout({ title, children }) {
  return (
    <div style={{ background: "var(--surface)", border: "1px solid var(--line)", padding: "20px 24px", margin: "24px 0", borderLeft: "3px solid var(--cyan)" }}>
      {title && <div className="t-eyebrow" style={{ color: "var(--cyan)", marginBottom: 8 }}>{title}</div>}
      <div style={{ color: "var(--text)" }}>{children}</div>
    </div>
  );
}

function useToc(items) {
  const [active, setActive] = useState(items[0]?.id);
  useEffect(() => {
    const onScroll = () => {
      const y = window.scrollY + 200;
      let cur = items[0]?.id;
      for (const it of items) {
        const el = document.getElementById(it.id);
        if (el && el.offsetTop <= y) cur = it.id;
      }
      setActive(cur);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  const onClick = (id) => {
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return { active, onClick };
}

/* ============================================================
 *  PRIVACY
 * ============================================================ */
function PrivacyPage() {
  const items = [
    { id: "summary",  label: "A short summary" },
    { id: "who",      label: "Who we are" },
    { id: "what",     label: "What we collect" },
    { id: "why",      label: "Why we collect it" },
    { id: "share",    label: "How we share data" },
    { id: "cookies",  label: "Cookies & tracking" },
    { id: "retention",label: "How long we keep it" },
    { id: "rights",   label: "Your rights" },
    { id: "security", label: "Security" },
    { id: "minors",   label: "Players under 18" },
    { id: "changes",  label: "Changes to this policy" },
    { id: "contact",  label: "Contact us" },
  ];
  const { active, onClick } = useToc(items);

  return (
    <LegalShell eyebrow="Legal" title="Privacy Policy" version="Effective 1 May 2026 · Version 1.0"
      lede="A plain-language summary of what we collect, why, and the choices you have. Built around the UAE Personal Data Protection Law and the realities of competitive gaming.">
      <LegalTOC items={items} active={active} onClick={onClick} />
      <Prose>
        <H2 id="summary">A short summary.</H2>
        <p>We collect only what we need to run tournaments, broadcasts and accounts — your handle, email, country, favourite games, match history, and (when you choose to share it) your team affiliations. We do not sell your data to advertisers.</p>
        <Callout title="The essentials">
          This policy applies to <a style={{ color: "var(--cyan)" }}>vexel</a>, our broadcasts, our Discord, our tournament platform and our newsletter. It is governed by the laws of the United Arab Emirates and the UAE PDPL (Federal Decree-Law No. 45 of 2021).
        </Callout>

        <H2 id="who">Who we are.</H2>
        <p>This platform is operated by <strong style={{ color: "var(--white)" }}>Wakefield Project Management</strong> (Trade Licence No. 1167116, Owner: Ibrahim Hussain Ahli), Dubai, UAE. "We", "us", and "VEXEL" refer to Wakefield throughout. The Data Protection Officer can be reached at <a style={{ color: "var(--cyan)" }}>privacy@clutchscan.online</a>.</p>

        <H2 id="what">What we collect.</H2>
        <H3>You give it to us</H3>
        <ul style={{ paddingLeft: 20 }}>
          <li>Handle, email, password (hashed), country, favourite game</li>
          <li>Profile photo, social handles (Discord, Twitch, Riot ID — optional)</li>
          <li>Tournament registrations, team affiliations</li>
        </ul>
        <H3>You generate by playing</H3>
        <ul style={{ paddingLeft: 20 }}>
          <li>Match history, scores, in-platform chat (kept 90 days)</li>
          <li>Stream-chat messages on our broadcasts</li>
          <li>IP address, device, browser, anti-cheat telemetry during matches</li>
        </ul>
        <H3>From partners</H3>
        <ul style={{ paddingLeft: 20 }}>
          <li>Verified ranks from Riot, Valve, Bandai-Namco where you have linked accounts</li>
          <li>Payment status from Stripe / Tabby for store orders</li>
        </ul>

        <H2 id="why">Why we collect it.</H2>
        <p>Five reasons, in order of importance: <strong style={{ color: "var(--white)" }}>1.</strong> Running tournaments and matchmaking. <strong style={{ color: "var(--white)" }}>2.</strong> Anti-cheat enforcement. <strong style={{ color: "var(--white)" }}>3.</strong> Broadcasting and producing the live shows. <strong style={{ color: "var(--white)" }}>4.</strong> Sending you tournament updates (only with consent). <strong style={{ color: "var(--white)" }}>5.</strong> Aggregated, anonymised research to improve the platform.</p>

        <H2 id="share">How we share data.</H2>
        <p>We share the minimum needed with:</p>
        <ul style={{ paddingLeft: 20 }}>
          <li>Tournament operators (only your handle, country and rank)</li>
          <li>Game publishers (Riot, Valve, etc.) for rank verification</li>
          <li>Stream platforms (Twitch, YouTube) when you appear in broadcasts</li>
          <li>Anti-cheat providers (BattlEye, EAC) during competitive matches</li>
          <li>Government authorities only when legally required</li>
        </ul>
        <p>We never sell or rent your data for marketing — ever.</p>

        <H2 id="cookies">Cookies & tracking.</H2>
        <p>Four categories: <em>essential</em> (sign-in, cart, language), <em>functional</em> (recently viewed teams, saved favourites), <em>analytics</em> (anonymised page-view data), <em>marketing</em> (only with your explicit consent). Manage at any time via the cookie banner.</p>

        <H2 id="retention">How long we keep it.</H2>
        <ul style={{ paddingLeft: 20 }}>
          <li>Account data: until deletion, plus 30 days</li>
          <li>Match & ranking history: 5 years (competitive integrity)</li>
          <li>Anti-cheat logs: 2 years</li>
          <li>Order & financial records: 7 years (UAE FTA requirement)</li>
          <li>Marketing preferences: until unsubscribe + 6 months</li>
        </ul>

        <H2 id="rights">Your rights.</H2>
        <p>Under the UAE PDPL you can: request a copy of your data, ask us to correct anything inaccurate, ask us to delete your data, object to certain processing, withdraw consent at any time, and lodge a complaint with the UAE Data Office.</p>
        <p>To exercise any of these, email <a style={{ color: "var(--cyan)" }}>privacy@clutchscan.online</a>. We respond within 30 days.</p>

        <H2 id="security">Security.</H2>
        <p>256-bit TLS in transit, AES-256 at rest, role-based access, regular pen-testing. No system is invulnerable — we'll notify affected players within 72 hours of any confirmed breach.</p>

        <H2 id="minors">Players under 18.</H2>
        <p>We require players to be at least 13. Players under 18 need a parent/guardian to co-sign tournament participation that has a prize component. We do not collect data from anyone under 13.</p>

        <H2 id="changes">Changes to this policy.</H2>
        <p>When this policy changes materially, we email registered accounts and post a banner on the homepage at least 14 days before the change takes effect.</p>

        <H2 id="contact">Contact us.</H2>
        <p>
          <a style={{ color: "var(--cyan)" }}>privacy@clutchscan.online</a> — Data Protection<br/>
          <a style={{ color: "var(--cyan)" }}>info@clutchscan.online</a> — General enquiries<br/>
          <a style={{ color: "var(--cyan)" }}>shirley@clutchscan.online</a> — Administration
        </p>
        <p style={{ marginTop: 14 }}>Wakefield Project Management — Trade Licence No. 1167116 — Owner: Ibrahim Hussain Ahli — Dubai, UAE</p>
      </Prose>
    </LegalShell>
  );
}

/* ============================================================
 *  TERMS
 * ============================================================ */
function TermsPage() {
  const items = [
    { id: "about",     label: "About these terms" },
    { id: "eligibility", label: "Eligibility" },
    { id: "account",   label: "Your account" },
    { id: "tournaments", label: "Tournaments & prizes" },
    { id: "conduct",   label: "Player conduct" },
    { id: "store",     label: "Store purchases" },
    { id: "ip",        label: "Intellectual property" },
    { id: "broadcasts",label: "Broadcasts & likeness" },
    { id: "termination", label: "Termination" },
    { id: "liability", label: "Limitation of liability" },
    { id: "disputes",  label: "Disputes & governing law" },
    { id: "contact",   label: "Contact" },
  ];
  const { active, onClick } = useToc(items);

  return (
    <LegalShell eyebrow="Legal" title="Terms & Conditions" version="Effective 1 May 2026 · Version 1.0"
      lede="The terms that govern your use of VEXEL — sign-up, participation in tournaments, prize distribution, and the rules of the platform.">
      <LegalTOC items={items} active={active} onClick={onClick} />
      <Prose>
        <H2 id="about">About these terms.</H2>
        <p>VEXEL is operated by <strong style={{ color: "var(--white)" }}>Wakefield Project Management</strong> (Trade Licence No. 1167116, Dubai, UAE). By creating an account, registering for a tournament, or buying from our store you agree to these terms.</p>

        <H2 id="eligibility">Eligibility.</H2>
        <p>You must be at least 13 to play. Cash-prize tournaments require players to be 18+ or have a parent/guardian co-sign. We may require ID verification for prize payouts above AED 5,000.</p>

        <H2 id="account">Your account.</H2>
        <p>One account per person. No account sharing. You're responsible for keeping your password secure. We may suspend accounts used for cheating, harassment, or fraud — see <a style={{ color: "var(--cyan)" }}>Code of Conduct</a>.</p>

        <H2 id="tournaments">Tournaments & prizes.</H2>
        <ul style={{ paddingLeft: 20 }}>
          <li>Registration opens and closes per tournament — check the detail page</li>
          <li>Prize pools are paid in AED via bank transfer (international winners: USD via SWIFT/Wise)</li>
          <li>Payout takes 14–21 business days after tournament conclusion and identity verification</li>
          <li>Disputes during a match: contact the on-shift admin within 30 minutes; brackets cannot be re-run after results are official</li>
          <li>VEXEL retains 10% organisational fee on the published prize pool unless otherwise stated</li>
        </ul>

        <H2 id="conduct">Player conduct.</H2>
        <p>The <a style={{ color: "var(--cyan)" }}>Code of Conduct</a> and <a style={{ color: "var(--cyan)" }}>Anti-Cheat Policy</a> are part of these terms. Violations result in match forfeitures, prize disqualification, or permanent bans.</p>

        <H2 id="store">Store purchases.</H2>
        <p>We accept Visa, Mastercard, Apple Pay, Tabby and Tamara. Orders ship via insured courier within the UAE; international ship is quoted per order. 14-day returns on unopened items.</p>

        <H2 id="ip">Intellectual property.</H2>
        <p>The VEXEL name, logo, broadcast content and tournament formats are owned by Wakefield Project Management. Game titles (Valorant, CS2, Dota 2, etc.) are property of their respective publishers. Personal, non-commercial sharing of broadcast clips with attribution is fine; commercial use requires written consent.</p>

        <H2 id="broadcasts">Broadcasts & likeness.</H2>
        <p>By participating in a tournament you grant VEXEL a worldwide, royalty-free license to broadcast, record, photograph and re-air your matches and post-match interviews, and to use your name and handle in tournament marketing.</p>

        <H2 id="termination">Termination.</H2>
        <p>You may delete your account at any time from your dashboard. We may suspend or close accounts that violate these terms, with notice when reasonable and immediately when not (e.g. confirmed cheating, illegal activity).</p>

        <H2 id="liability">Limitation of liability.</H2>
        <p>Nothing here excludes our liability for death, personal injury caused by negligence, or fraud. Subject to that, our total liability in connection with any tournament shall not exceed the prize pool of the relevant event. We're not liable for indirect or consequential loss.</p>

        <H2 id="disputes">Disputes & governing law.</H2>
        <p>These terms are governed by the laws of the UAE as applied in the Emirate of Dubai. We will always try to resolve issues through our concierge first. If that fails, the courts of Dubai have exclusive jurisdiction.</p>

        <H2 id="contact">Contact.</H2>
        <p>
          <a style={{ color: "var(--cyan)" }}>info@clutchscan.online</a> · <a style={{ color: "var(--cyan)" }}>shirley@clutchscan.online</a><br/>
          Wakefield Project Management — Trade Licence No. 1167116 — Owner: Ibrahim Hussain Ahli — Dubai, UAE
        </p>
      </Prose>
    </LegalShell>
  );
}

/* ============================================================
 *  CODE OF CONDUCT
 * ============================================================ */
function CodeOfConductPage() {
  const items = [
    { id: "spirit",     label: "The spirit" },
    { id: "respect",    label: "Respect for everyone" },
    { id: "fair",       label: "Fair play" },
    { id: "comms",      label: "Communications" },
    { id: "harassment", label: "Harassment & hate" },
    { id: "reporting",  label: "Reporting violations" },
    { id: "enforcement",label: "Enforcement & appeals" },
  ];
  const { active, onClick } = useToc(items);

  return (
    <LegalShell eyebrow="Player rules" title="Code of Conduct" version="Effective 1 May 2026 · Version 1.0"
      lede="Competition is hard. Being a decent person while doing it isn't. These are the rules that keep the Gulf scene a place worth being part of.">
      <LegalTOC items={items} active={active} onClick={onClick} />
      <Prose>
        <H2 id="spirit">The spirit.</H2>
        <p>VEXEL is built around competitive integrity, mutual respect, and the long-term health of the Gulf scene. Tournaments are won by the better team — not the louder one.</p>

        <H2 id="respect">Respect for everyone.</H2>
        <p>You will not discriminate against, harass, dox, or threaten any player, staff member, viewer or partner — full stop. This applies in-game, on Discord, in broadcasts, in DMs, on social media, and at offline events.</p>

        <H2 id="fair">Fair play.</H2>
        <ul style={{ paddingLeft: 20 }}>
          <li>No cheats, exploits, scripts or third-party hardware (mouse macros, recoil controllers, vision aids)</li>
          <li>No smurfing or "boosting" — play on your verified account, at your verified rank</li>
          <li>No match-fixing or sandbagging. Suspected fixing = permanent ban + reporting to the publisher</li>
          <li>No collusion with bracket opponents (sharing strategies, soft-throwing, etc.)</li>
          <li>Tilt-quitting a finalist match = forfeit + 90-day ban</li>
        </ul>

        <H2 id="comms">Communications.</H2>
        <p>Voice and text chat during matches is recorded and reviewed when reported. Trash-talking is OK; targeted abuse is not. The line: would you say it to their face, at a LAN, with their parent next to them? If no, don't say it.</p>

        <H2 id="harassment">Harassment & hate.</H2>
        <p>Zero tolerance for racism, sexism, homophobia, transphobia, religious harassment, ableist slurs, or threats of violence. First confirmed offence = 30-day ban. Second = permanent.</p>

        <H2 id="reporting">Reporting violations.</H2>
        <p>Report any breach in-platform (right-click → Report) or by email to <a style={{ color: "var(--cyan)" }}>conduct@clutchscan.online</a>. Include match ID, timestamps, screenshots/clips. Reports are confidential.</p>

        <H2 id="enforcement">Enforcement & appeals.</H2>
        <p>Our integrity team reviews reports within 5 business days. Sanctions are recorded against your account and visible to you. Appeals: email <a style={{ color: "var(--cyan)" }}>appeals@clutchscan.online</a> within 14 days of a sanction. Decisions on appeal are final.</p>
      </Prose>
    </LegalShell>
  );
}

/* ============================================================
 *  ANTI-CHEAT
 * ============================================================ */
function AntiCheatPage() {
  const items = [
    { id: "policy",  label: "Our policy" },
    { id: "what",    label: "What counts as cheating" },
    { id: "detect",  label: "How we detect it" },
    { id: "penalty", label: "Penalties" },
    { id: "appeals", label: "Appeals" },
  ];
  const { active, onClick } = useToc(items);

  return (
    <LegalShell eyebrow="Competitive integrity" title="Anti-Cheat Policy" version="Effective 1 May 2026 · Version 1.0"
      lede="Cheating breaks tournaments. Our policy is short, strict, and consistent — for every player, every match, every prize pool.">
      <LegalTOC items={items} active={active} onClick={onClick} />
      <Prose>
        <H2 id="policy">Our policy.</H2>
        <p>One offence is one too many. VEXEL takes a zero-tolerance approach to cheating in all sanctioned matches and tournaments.</p>

        <H2 id="what">What counts as cheating.</H2>
        <ul style={{ paddingLeft: 20 }}>
          <li>Third-party software (aimbots, wallhacks, triggerbots, ESP)</li>
          <li>Hardware cheats (modded mice, recoil-control devices, vision aids)</li>
          <li>Account boosting / sharing</li>
          <li>Match-fixing or intentional throwing</li>
          <li>Stream-sniping in a live broadcast</li>
          <li>DDoS-ing or harassing opponents to disconnect</li>
          <li>Exploiting bugs that grant unfair advantage</li>
        </ul>

        <H2 id="detect">How we detect it.</H2>
        <p>We use a combination of publisher-grade anti-cheat (BattlEye, EAC, VAC), our own statistical anomaly detection, replay analysis by our integrity team, and community reports. Many of our finals require players to install our anti-cheat client and play from a verified setup.</p>

        <H2 id="penalty">Penalties.</H2>
        <ul style={{ paddingLeft: 20 }}>
          <li><strong style={{ color: "var(--white)" }}>First confirmed offence:</strong> match forfeiture, prize disqualification, 90-day platform ban</li>
          <li><strong style={{ color: "var(--white)" }}>Second offence or major (paid cheats, hardware, match-fixing):</strong> permanent ban, public listing, report to publisher</li>
          <li><strong style={{ color: "var(--white)" }}>Coordinated cheating (teams):</strong> entire team disqualified and banned; organisation rejected from future events</li>
        </ul>

        <H2 id="appeals">Appeals.</H2>
        <p>Email <a style={{ color: "var(--cyan)" }}>appeals@clutchscan.online</a> within 14 days with your account ID, match ID, and any evidence (replay, system logs). Our integrity team reviews independently. Decisions on appeal are final.</p>
      </Prose>
    </LegalShell>
  );
}

/* ============================================================
 *  FAQ
 * ============================================================ */
function FAQItem({ q, a }) {
  const [open, setOpen] = useState(false);
  return (
    <div style={{ borderBottom: "1px solid var(--line)" }}>
      <button onClick={() => setOpen(!open)} style={{
        width: "100%", padding: "22px 0",
        display: "flex", justifyContent: "space-between", alignItems: "center",
        textAlign: "left", color: "var(--white)", fontSize: 16, fontWeight: 600
      }}>
        <span>{q}</span>
        <span style={{ fontSize: 22, color: "var(--text-mute)", lineHeight: 1 }}>{open ? "−" : "+"}</span>
      </button>
      {open && <div style={{ paddingBottom: 22, color: "var(--text-dim)", fontSize: 15, lineHeight: 1.7, maxWidth: 640 }}>{a}</div>}
    </div>
  );
}

function FAQPage({ go }) {
  const cats = [
    { id: "account", label: "Account & sign-up", items: [
      { q: "Is VEXEL free to join?", a: "Yes. Creating an account, browsing tournaments, watching live broadcasts and following teams is completely free." },
      { q: "What's the minimum age to play?", a: "13 to create an account. 18+ for any tournament with a cash prize (or 13–17 with parent/guardian co-signature)." },
      { q: "Can I have multiple accounts?", a: "No — one account per person. We use IP + payment + behavioural signals to detect duplicates." },
      { q: "How do I link my Riot / Steam / Discord?", a: "Go to your Dashboard → Linked accounts → Connect. Required for rank-restricted tournaments." }
    ]},
    { id: "tournaments", label: "Tournaments", items: [
      { q: "How do I register for a tournament?", a: "Open the tournament page, hit Register. Some tournaments require a verified rank or a team invite." },
      { q: "When do prize pools pay out?", a: "Within 14–21 business days after the tournament concludes and identity verification is complete. Bank transfer in AED (or USD via SWIFT/Wise for international winners)." },
      { q: "What if my team has a substitute?", a: "Subs must be registered on your roster before the tournament starts. Stand-ins after registration close are reviewed case-by-case." },
      { q: "Can I run my own tournament on VEXEL?", a: "Yes — apply via Partners → Tournament organisers. We provide bracket software, stream production and prize escrow." }
    ]},
    { id: "broadcasts", label: "Broadcasts", items: [
      { q: "Where do you stream matches?", a: "Twitch (primary), YouTube (mirror), and Vexel.com/live for the production cut. Arabic-language casting on our second channel." },
      { q: "Can I clip and re-post broadcasts?", a: "Personal clips with attribution: yes. Commercial use or full VOD re-uploads: contact press@clutchscan.online." }
    ]},
    { id: "store", label: "Store", items: [
      { q: "Do you ship internationally?", a: "Yes, by quote. UAE shipping is flat-rate AED 25; GCC is AED 100; international varies." },
      { q: "What's your return policy?", a: "14 days for unopened items in original packaging. Custom jerseys are final sale." }
    ]},
    { id: "anti-cheat", label: "Anti-cheat", items: [
      { q: "Will I have to install software?", a: "For finals of major tournaments, yes — our anti-cheat client (works alongside BattlEye/EAC). For most ladder play, no." },
      { q: "I was banned and I think it's a mistake.", a: "Email appeals@clutchscan.online within 14 days with your account ID, match ID, and evidence (replay, system logs)." }
    ]},
    { id: "trade", label: "Partnership & press", items: [
      { q: "How do I sponsor a tournament?", a: "Visit our Partners page and submit the partnership form. Our partnerships lead replies within 5 business days." },
      { q: "I'm a journalist — where's the press kit?", a: "Email press@clutchscan.online. We send logo packs, broadcast access and embargoed news for accredited outlets." }
    ]}
  ];
  const [activeCat, setActiveCat] = useState(cats[0].id);

  return (
    <div style={{ background: "var(--ink)", minHeight: "60vh" }}>
      <div className="bg-grid" style={{ borderBottom: "1px solid var(--line)", padding: "64px var(--gutter) 56px" }}>
        <div className="shell">
          <div className="t-eyebrow" style={{ color: "var(--cyan)" }}>Help</div>
          <h1 className="t-display" style={{ fontSize: 76, marginTop: 12 }}>FAQ</h1>
          <p style={{ color: "var(--text-dim)", fontSize: 17, maxWidth: 640, marginTop: 18 }}>Common questions about VEXEL — accounts, tournaments, broadcasts, the store and our anti-cheat policy.</p>
        </div>
      </div>
      <div className="shell" style={{ padding: "64px 0 120px", display: "grid", gridTemplateColumns: "240px 1fr", gap: 64 }}>
        <aside style={{ position: "sticky", top: 120, alignSelf: "start" }}>
          <div className="t-eyebrow" style={{ marginBottom: 16 }}>Categories</div>
          {cats.map(c => (
            <a key={c.id} onClick={() => { setActiveCat(c.id); document.getElementById("cat-"+c.id)?.scrollIntoView({ behavior: "smooth" }); }}
               style={{ display: "block", padding: "10px 0", borderBottom: "1px solid var(--line)", color: activeCat === c.id ? "var(--cyan)" : "var(--text-dim)", fontSize: 14, cursor: "pointer" }}>
              {c.label}
            </a>
          ))}
        </aside>
        <div style={{ maxWidth: 720 }}>
          {cats.map(c => (
            <div key={c.id} id={"cat-"+c.id} style={{ marginBottom: 56 }}>
              <h2 className="t-display" style={{ fontSize: 28, color: "var(--white)", marginBottom: 12 }}>{c.label}</h2>
              {c.items.map((it, i) => <FAQItem key={i} q={it.q} a={it.a} />)}
            </div>
          ))}
          <div className="card-flat" style={{ padding: 28, marginTop: 32 }}>
            <div className="t-eyebrow" style={{ color: "var(--cyan)" }}>Still stuck?</div>
            <h3 className="t-display" style={{ fontSize: 24, color: "var(--white)", marginTop: 8, marginBottom: 12 }}>Talk to us.</h3>
            <p style={{ color: "var(--text-dim)", fontSize: 14, marginBottom: 16 }}>Our concierge replies within 24 hours, 7 days a week.</p>
            <button onClick={() => go("contact")} className="btn btn-primary btn-sm">Contact support →</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
 *  404 — Not found
 * ============================================================ */
function NotFoundPage({ go }) {
  return (
    <div style={{ background: "var(--ink)", minHeight: "70vh", display: "flex", alignItems: "center", justifyContent: "center", padding: "80px var(--gutter)" }}>
      <div style={{ textAlign: "center", maxWidth: 640 }}>
        <div className="t-display" style={{ fontSize: 220, color: "var(--cyan)", lineHeight: 1, textShadow: "0 0 40px rgba(0,229,255,0.4)" }}>404</div>
        <h1 className="t-display" style={{ fontSize: 48, color: "var(--white)", marginTop: 16 }}>Lobby disconnected.</h1>
        <p style={{ color: "var(--text-dim)", fontSize: 17, maxWidth: 480, margin: "20px auto 32px" }}>This route doesn't exist on the bracket. Reconnect through the homepage, or jump straight to live matches.</p>
        <div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap" }}>
          <button onClick={() => go("home")} className="btn btn-primary">Return to lobby</button>
          <button onClick={() => go("live")} className="btn btn-ghost">Watch live →</button>
          <button onClick={() => go("tournaments")} className="btn btn-dark">Browse tournaments</button>
        </div>
        <div style={{ marginTop: 64, display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, textAlign: "left" }}>
          {[
            ["Tournaments", "Live & upcoming", "tournaments"],
            ["Rankings", "Top players in the GCC", "players"],
            ["Teams", "Pro organisations", "teams"],
            ["The Drop", "Weekly news + ranks", "news"],
          ].map(([t, sub, route]) => (
            <a key={route} onClick={() => go(route)} className="card-flat" style={{ padding: 18, cursor: "pointer", transition: "all 0.15s" }}>
              <div className="t-eyebrow" style={{ color: "var(--cyan)" }}>{t}</div>
              <div style={{ color: "var(--text)", fontSize: 14, marginTop: 6 }}>{sub}</div>
            </a>
          ))}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { PrivacyPage, TermsPage, CodeOfConductPage, AntiCheatPage, FAQPage, NotFoundPage });
