TypeScript 97.5%
SQL 1.4%
Python 0.8%
1import * as React from "react";2import Link from "next/link";3import { cn } from "@/lib/utils";45export const LEGAL_VERSION = "2026-09-07";6export const LEGAL_EFFECTIVE = "2026-09-07";78export type LegalSection = { id: string; title: string; body: React.ReactNode };910const OTHER_DOCS: Array<[string, string]> = [11 ["Terms of Service", "/legal/terms"],12 ["Privacy Policy", "/legal/privacy"],13 ["Acceptable Use Policy", "/legal/acceptable-use"],14 ["Data Processing Addendum", "/legal/dpa"],15 ["Cookie Policy", "/legal/cookies"],16];1718/** Prose styling without @tailwindcss/typography. Applied to each section body. */19export const legalProse = cn(20 "text-[15px] leading-[1.7] text-fg-muted",21 "[&_p]:mt-3.5 [&_p:first-child]:mt-0",22 "[&_h3]:mt-6 [&_h3]:text-[15px] [&_h3]:font-semibold [&_h3]:text-fg [&_h3]:tracking-tight",23 "[&_ul]:mt-3.5 [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:mt-3.5 [&_ol]:list-decimal [&_ol]:pl-5 [&_li]:mt-1.5 [&_li]:pl-0.5",24 "[&_a]:text-accent [&_a]:underline-offset-4 hover:[&_a]:underline",25 "[&_strong]:font-semibold [&_strong]:text-fg",26 "[&_code]:rounded-[4px] [&_code]:border [&_code]:border-border [&_code]:bg-bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-fg",27 "[&_table]:mt-4 [&_table]:w-full [&_table]:text-[13.5px] [&_th]:border-b [&_th]:border-border [&_th]:py-2 [&_th]:pr-4 [&_th]:text-left [&_th]:text-[11.5px] [&_th]:font-medium [&_th]:uppercase [&_th]:tracking-wide [&_th]:text-fg-subtle [&_td]:border-b [&_td]:border-border [&_td]:py-2 [&_td]:pr-4 [&_td]:align-top",28);2930export function LegalLayout({ title, summary, current, sections }: { title: string; summary: string; current: string; sections: LegalSection[] }) {31 return (32 <div className="container-page py-12 sm:py-16">33 <header className="max-w-3xl">34 <p className="text-[11.5px] font-medium uppercase tracking-wide text-fg-subtle">Legal</p>35 <h1 className="mt-2 text-3xl font-semibold tracking-tight sm:text-[36px]">{title}</h1>36 <p className="mt-3 font-mono text-[12.5px] text-fg-subtle">37 Version {LEGAL_VERSION} · Effective {LEGAL_EFFECTIVE}38 </p>39 <p className="mt-5 text-[15.5px] leading-relaxed text-fg-muted">{summary}</p>40 </header>4142 <div className="mt-10 grid gap-10 lg:grid-cols-[220px_minmax(0,1fr)] lg:gap-16">43 <aside className="lg:sticky lg:top-20 lg:self-start">44 <nav aria-label="Table of contents" className="rounded-lg border border-border bg-bg-subtle/60 p-4 lg:border-0 lg:bg-transparent lg:p-0">45 <h2 className="text-[11.5px] font-semibold uppercase tracking-wide text-fg-subtle">On this page</h2>46 <ol className="mt-3 space-y-1.5 text-[13px]">47 {sections.map((s, i) => (48 <li key={s.id} className="flex gap-2">49 <span className="w-5 shrink-0 font-mono tabular text-fg-subtle">{i + 1}.</span>50 <a href={`#${s.id}`} className="text-fg-muted transition-colors hover:text-fg">51 {s.title}52 </a>53 </li>54 ))}55 </ol>56 <h2 className="mt-6 text-[11.5px] font-semibold uppercase tracking-wide text-fg-subtle">Other documents</h2>57 <ul className="mt-3 space-y-1.5 text-[13px]">58 {OTHER_DOCS.filter(([, href]) => href !== current).map(([label, href]) => (59 <li key={href}>60 <Link href={href} className="text-fg-muted transition-colors hover:text-fg">61 {label}62 </Link>63 </li>64 ))}65 </ul>66 </nav>67 </aside>6869 <article className="min-w-0 max-w-3xl">70 {sections.map((s, i) => (71 <section key={s.id} id={s.id} className="scroll-mt-24 border-t border-border py-8 first:border-t-0 first:pt-0">72 <h2 className="text-[20px] font-semibold tracking-tight text-fg">73 <span className="mr-2 font-mono text-[14px] font-medium text-fg-subtle tabular">{i + 1}.</span>74 {s.title}75 </h2>76 <div className={cn("mt-4", legalProse)}>{s.body}</div>77 </section>78 ))}79 <footer className="mt-4 rounded-lg border border-border bg-bg-subtle/60 p-5 text-[13.5px] leading-relaxed text-fg-muted">80 Questions about this document? Write to <a className="text-accent underline-offset-4 hover:underline" href="mailto:legal@fetcha.co">legal@fetcha.co</a>. Previous versions are available on request. We will post material changes on this page and, for changes that reduce your rights, notify account owners by email at least 30 days before they take effect.81 </footer>82 </article>83 </div>84 </div>85 );86}87