diff options
| author | benj <benj@rse8.com> | 2026-04-09 16:10:08 +0800 |
|---|---|---|
| committer | benj <benj@rse8.com> | 2026-04-09 16:10:08 +0800 |
| commit | c041641634650c31e03c70dcad132fd94cb08e63 (patch) | |
| tree | 8f714a6fc0a66b05b2e43afec75808fd29002a42 /landing | |
| parent | 5f56e0eaf8030f78077fc93b441296bb51fe9331 (diff) | |
| download | tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.tar tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.tar.gz tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.tar.bz2 tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.tar.lz tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.tar.xz tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.tar.zst tidyindex-c041641634650c31e03c70dcad132fd94cb08e63.zip | |
Rework landing page with editorial layout, new demo, and LLM CTA
Replaces the generic SaaS template look with a left-aligned editorial
design — Fraunces serif headlines, monospace section markers (§ 01,
§ 02 …), hairline rules, and a quieter palette where the blue earns
its place rather than splashing on every surface.
The hero now leads with a real product demo (§ 01): one IRS 990 dataset
shown in three consumption shapes — a single normalized JSON record, a
JSONL bulk slice, and a token-efficient prose summary — instead of the
old fake-macOS code window. Each shape carries source-link receipts
back to the original filing, which doubles as a credibility signal and
a working illustration of the "every record has a receipt" promise.
§ 03 introduces a coverage widget driven by data/catalog.toml: four
auto-scrolling category windows (securities, government, regulatory,
science) showing 60 hand-picked datasets with seamless CSS-only
infinite-scroll loops, fade masks, hover-pause, and a
prefers-reduced-motion fallback that converts the windows into manually
scrollable lists.
Adds a discoverable /llms.txt at the static root — a markdown-light,
human-readable site description aimed at LLM agents — wired up via
<link rel="alternate"> in <head>, a comment in robots.txt, and a small
mono "for agents · GET /llms.txt →" satellite link sitting directly
under the hero CTA so any agent shallow-scraping the page hits the
machine path immediately.
Other changes: drops the XML format demo and the "promises" ledger
section entirely, swaps hello@ for contact@ across the site, and
renames the bottom CTA to a single-action "Ready when you are. → API
Key" close.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'landing')
| -rw-r--r-- | landing/data/catalog.toml | 83 | ||||
| -rw-r--r-- | landing/layouts/_default/baseof.html | 3 | ||||
| -rw-r--r-- | landing/layouts/index.html | 283 | ||||
| -rw-r--r-- | landing/layouts/partials/footer.html | 13 | ||||
| -rw-r--r-- | landing/layouts/partials/header.html | 12 | ||||
| -rw-r--r-- | landing/static/css/style.css | 888 | ||||
| -rw-r--r-- | landing/static/llms.txt | 99 | ||||
| -rw-r--r-- | landing/static/robots.txt | 3 |
8 files changed, 827 insertions, 557 deletions
diff --git a/landing/data/catalog.toml b/landing/data/catalog.toml new file mode 100644 index 0000000..3882d68 --- /dev/null +++ b/landing/data/catalog.toml @@ -0,0 +1,83 @@ +# Datasets shown in the § 03 catalog widget on the landing page. +# Each category becomes one scrolling column. Order within a category is +# the order they scroll past, so put recognizable / flagship datasets first. + +[[categories]] +name = "securities & finance" +items = [ + "SEC EDGAR 10-K, 10-Q", + "SEC 13-F holdings", + "SEC Form 4 insiders", + "SEC 13-D/G ownership", + "SEC Form D placements", + "FFIEC HMDA mortgages", + "FDIC call reports", + "NCUA credit unions", + "FINRA BrokerCheck", + "SEC investment advisers", + "CFPB consumer complaints", + "CFPB rate spread data", + "Federal bankruptcy filings", + "FinCEN beneficial ownership", + "Delaware franchise tax", +] + +[[categories]] +name = "government & politics" +items = [ + "USAspending awards", + "FEC campaign finance", + "Federal lobbying (LDA)", + "Congressional votes", + "Congressional bills", + "Federal Register rules", + "FPDS procurement", + "Federal subawards (FSRS)", + "GSA Schedule pricing", + "Foreign agents (FARA)", + "Executive orders", + "Federal IT spending", + "DOJ settlements", + "State lobbying", + "State procurement", +] + +[[categories]] +name = "regulatory & legal" +items = [ + "IRS 990 & 990-PF", + "IRS Form 5500 plans", + "IRS Business Master File", + "SAM.gov registrations", + "OSHA inspections", + "EPA ECHO enforcement", + "PACER federal courts", + "State court records", + "UCC filings", + "Secretary of State (SOS)", + "State medical boards", + "State bar attorneys", + "State contractor licenses", + "ITC trade rulings", + "DEA registrations", +] + +[[categories]] +name = "science, health & IP" +items = [ + "USPTO patent grants", + "USPTO trademarks", + "Patent assignments", + "Copyright registrations", + "NIH RePORTER grants", + "NSF grant awards", + "FDA drug approvals", + "FDA 510(k) devices", + "FDA FAERS adverse events", + "FDA warning letters", + "ClinicalTrials.gov", + "NPI provider registry", + "IPEDS college financials", + "DOE College Scorecard", + "DOE SBIR/STTR awards", +] diff --git a/landing/layouts/_default/baseof.html b/landing/layouts/_default/baseof.html index 89a0bd7..bab1b56 100644 --- a/landing/layouts/_default/baseof.html +++ b/landing/layouts/_default/baseof.html @@ -17,10 +17,11 @@ <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> + <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300..600&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <link rel="stylesheet" href="{{ "css/style.css" | relURL }}" /> <link rel="icon" type="image/svg+xml" href="{{ "favicon.svg" | relURL }}" /> + <link rel="alternate" type="text/plain" title="LLM-readable site description" href="{{ "llms.txt" | relURL }}" /> </head> <body> {{ partial "header.html" . }} diff --git a/landing/layouts/index.html b/landing/layouts/index.html index 231ff61..a08109e 100644 --- a/landing/layouts/index.html +++ b/landing/layouts/index.html @@ -1,213 +1,152 @@ {{ define "main" }} <section class="hero"> - <div class="container hero-inner"> - <span class="eyebrow">Clean data, on tap</span> - <h1 class="hero-title"> - Structured data,<br /> - <span class="accent">served simply.</span> + <div class="container"> + <h1 class="hero-headline"> + Structured data,<br> + <em>served simply.</em> </h1> <p class="hero-sub"> Tidy Index delivers clean, well-organized datasets through a single API designed for humans, machines, and LLM agents alike. </p> <div class="hero-cta"> - <a href="#contact" class="btn btn-primary">Request access</a> - <a href="#how" class="btn btn-ghost">See how it works</a> - </div> - - <div class="hero-visual" aria-hidden="true"> - <div class="code-card"> - <div class="code-card-head"> - <span class="dot dot-a"></span> - <span class="dot dot-b"></span> - <span class="dot dot-c"></span> - <span class="code-card-title">GET /v1/datasets/cities</span> - </div> -<pre class="code-card-body"><code><span class="tk-p">{</span> - <span class="tk-k">"id"</span>: <span class="tk-s">"cities"</span>, - <span class="tk-k">"updated"</span>: <span class="tk-s">"2026-04-09T08:14:00Z"</span>, - <span class="tk-k">"records"</span>: <span class="tk-p">[</span> - <span class="tk-p">{</span> <span class="tk-k">"name"</span>: <span class="tk-s">"Lisbon"</span>, <span class="tk-k">"population"</span>: <span class="tk-n">548703</span> <span class="tk-p">}</span>, - <span class="tk-p">{</span> <span class="tk-k">"name"</span>: <span class="tk-s">"Kyoto"</span>, <span class="tk-k">"population"</span>: <span class="tk-n">1463723</span> <span class="tk-p">}</span>, - <span class="tk-p">{</span> <span class="tk-k">"name"</span>: <span class="tk-s">"Quito"</span>, <span class="tk-k">"population"</span>: <span class="tk-n">2011388</span> <span class="tk-p">}</span> - <span class="tk-p">]</span> -<span class="tk-p">}</span></code></pre> - </div> + <a href="mailto:contact@tidyindex.com" class="btn btn-primary"> + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> + <circle cx="7.5" cy="15.5" r="5.5"/> + <path d="m11.5 11.5 9.5-9.5"/> + <path d="m17 5 3 3"/> + <path d="m14 8 3 3"/> + </svg> + Get an API Key + </a> + <a href="#demo" class="btn-link">See a record <span aria-hidden="true">↓</span></a> </div> - </div> -</section> -<section id="what" class="section"> - <div class="container narrow"> - <span class="eyebrow center">What is Tidy Index</span> - <h2 class="section-title center">We’ve already done the cleanup.</h2> - <p class="section-lede center"> - Scraping. Reformatting. Reconciling. Re-scraping when the source changes - shape. We do all of that — once, properly — so you don’t - have to do any of it. + <p class="cta-agents"> + <span class="cta-agents-label">for agents</span> + <a href="{{ "llms.txt" | relURL }}"><code>GET /llms.txt</code> →</a> + <span class="cta-agents-note">a machine-readable invitation. No form, no salesperson.</span> </p> </div> </section> -<section id="formats" class="section section-soft"> +<section id="demo" class="section"> <div class="container"> - <span class="eyebrow center">Pick your shape</span> - <h2 class="section-title center">One dataset. Every shape you need.</h2> - <p class="section-lede center"> - Ask for JSON, get JSON. Ask for chunks, get chunks. Same data underneath — - no reformatting, no glue code. + <p class="section-marker">§ 01 · one dataset, three shapes</p> + <h2 class="section-headline">The same data, in whatever shape your job needs.</h2> + <p class="section-body"> + Below is the <code>irs-990</code> dataset — the annual return + every U.S. nonprofit files with the IRS, normally distributed as a + sprawling PDF or wall of e-file XML. Tidy Index serves it three ways: + a single record for your API, a streaming bulk export for your data + team, or a token-efficient summary your agents can drop straight into + context. </p> - <div class="format-grid"> - <article class="format-card"> - <div class="format-icon" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"> - <path d="M8 4 4 12l4 8"/> - <path d="m16 4 4 8-4 8"/> - </svg> + <div class="record"> + <header class="record-head"> + <span class="record-label">Dataset</span> + <code class="record-id">irs-990</code> + <span class="record-meta">1.5M filings · updated daily</span> + </header> + + <div class="record-row"> + <div class="record-tag"> + <span class="tag-name">record</span> + <span class="tag-mime">application/json</span> + <span class="tag-note">single filing, fully normalized</span> </div> - <h3>JSON</h3> - <p>Stable schemas, stable IDs, ETags on every response. Drop it straight into your code.</p> - </article> +<pre class="record-body"><code><span class="tk-p">{</span> + <span class="tk-k">"ein"</span><span class="tk-p">:</span> <span class="tk-s">"20-0049703"</span><span class="tk-p">,</span> + <span class="tk-k">"name"</span><span class="tk-p">:</span> <span class="tk-s">"Wikimedia Foundation, Inc."</span><span class="tk-p">,</span> + <span class="tk-k">"fiscal_year"</span><span class="tk-p">:</span> <span class="tk-n">2023</span><span class="tk-p">,</span> + <span class="tk-k">"revenue_usd"</span><span class="tk-p">:</span> <span class="tk-n">180249000</span><span class="tk-p">,</span> + <span class="tk-k">"expenses_usd"</span><span class="tk-p">:</span> <span class="tk-n">169106000</span><span class="tk-p">,</span> + <span class="tk-k">"net_assets_usd"</span><span class="tk-p">:</span> <span class="tk-n">254971000</span><span class="tk-p">,</span> + <span class="tk-k">"source"</span><span class="tk-p">:</span> <span class="tk-s">"https://apps.irs.gov/app/eos/details/?ein=200049703"</span> +<span class="tk-p">}</span></code></pre> + </div> - <article class="format-card"> - <div class="format-icon" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"> - <path d="M4 4h16v16H4z"/> - <path d="M4 9h16"/> - <path d="M9 4v16"/> - </svg> + <div class="record-row"> + <div class="record-tag"> + <span class="tag-name">bulk</span> + <span class="tag-mime">application/x-ndjson</span> + <span class="tag-note">streaming, one record per line</span> </div> - <h3>XML & CSV</h3> - <p>For the pipelines that have been around longer than your team has. Strict, well-formed, no surprises.</p> - </article> +<pre class="record-body"><code><span class="tk-p">{</span><span class="tk-k">"ein"</span><span class="tk-p">:</span><span class="tk-s">"20-0049703"</span><span class="tk-p">,</span><span class="tk-k">"name"</span><span class="tk-p">:</span><span class="tk-s">"Wikimedia Foundation, Inc."</span><span class="tk-p">,</span><span class="tk-k">"revenue_usd"</span><span class="tk-p">:</span><span class="tk-n">180249000</span><span class="tk-p">}</span> +<span class="tk-p">{</span><span class="tk-k">"ein"</span><span class="tk-p">:</span><span class="tk-s">"20-0097189"</span><span class="tk-p">,</span><span class="tk-k">"name"</span><span class="tk-p">:</span><span class="tk-s">"Mozilla Foundation"</span><span class="tk-p">,</span><span class="tk-k">"revenue_usd"</span><span class="tk-p">:</span><span class="tk-n">34019000</span><span class="tk-p">}</span> +<span class="tk-p">{</span><span class="tk-k">"ein"</span><span class="tk-p">:</span><span class="tk-s">"26-1544963"</span><span class="tk-p">,</span><span class="tk-k">"name"</span><span class="tk-p">:</span><span class="tk-s">"Khan Academy, Inc."</span><span class="tk-p">,</span><span class="tk-k">"revenue_usd"</span><span class="tk-p">:</span><span class="tk-n">85436000</span><span class="tk-p">}</span> +<span class="tk-c">…</span></code></pre> + </div> - <article class="format-card"> - <div class="format-icon" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"> - <circle cx="12" cy="12" r="8"/> - <path d="M12 8v4l2 2"/> - </svg> + <div class="record-row"> + <div class="record-tag"> + <span class="tag-name">summary</span> + <span class="tag-mime">text/plain</span> + <span class="tag-note">token-efficient, agent-ready</span> </div> - <h3>LLM chunks</h3> - <p>Already chunked, already cited, already embedding-ready. Drop them into your retriever and stop fighting tokenizers.</p> - </article> +<pre class="record-body"><code>Wikimedia Foundation, Inc. (EIN 20-0049703) reported +$180.25M in revenue against $169.11M in expenses on +its 2023 Form 990, ending the year with $254.97M in +net assets. - <article class="format-card"> - <div class="format-icon" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"> - <path d="M3 12h4l3-8 4 16 3-8h4"/> - </svg> - </div> - <h3>Streaming</h3> - <p>Webhooks and server-sent events the moment something changes. No polling, no stale caches.</p> - </article> +Source: https://apps.irs.gov/app/eos/details/?ein=200049703</code></pre> + </div> </div> </div> </section> -<section id="how" class="section"> +<section class="section section-soft"> <div class="container"> - <span class="eyebrow center">Who it’s for</span> - <h2 class="section-title center">Same data. Three kinds of readers.</h2> - <p class="section-lede center"> - People, programs, and agents all want different things from the same - dataset. Tidy Index gives each of them what they expect. + <p class="section-marker">§ 02 · what it is</p> + <h2 class="section-headline">Open data and licensed data, kept tidy.</h2> + <p class="section-body"> + Some of what we serve comes from the open web. The rest is licensed + from publishers, data vendors, and partners who’ve trusted us with + their private feeds. All of it lives behind the same API, with the same + stable schemas, the same stable IDs, and the same freshness guarantees + — and one key gets you every record in every shape your tools + (or your agents) prefer. </p> - - <div class="audience-grid"> - <div class="audience-card"> - <div class="audience-num">01</div> - <h3>For humans</h3> - <p> - A real web UI. Skim a schema, preview a few rows, grab a snapshot, - and copy a working curl command without leaving the page. - </p> - </div> - - <div class="audience-card audience-card-feature"> - <div class="audience-num">02</div> - <h3>For computers</h3> - <p> - Boring REST, the way you like it. OpenAPI specs, semver, ETags, - idempotent reads, and rate limits we’ll actually tell you about. - </p> - </div> - - <div class="audience-card"> - <div class="audience-num">03</div> - <h3>For LLM agents</h3> - <p> - Endpoints shaped like tool calls. Chunks shaped like context. Every - response carries its own provenance, so the model never has to guess - where the data came from. - </p> - </div> - </div> </div> </section> -<section class="section section-soft"> - <div class="container narrow"> - <span class="eyebrow center">Why Tidy Index</span> - <h2 class="section-title center">Less wrangling. More building.</h2> +<section class="section section-coverage"> + <div class="container container-wide"> + <p class="section-marker">§ 03 · what we cover</p> + <h2 class="section-headline">The index, abridged.</h2> + <p class="section-body"> + A small slice of what’s already in the catalog. + </p> - <ul class="value-list"> - <li> - <span class="value-check" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> - <polyline points="20 6 9 17 4 12"/> - </svg> - </span> - <div> - <strong>Curated, not crawled.</strong> - <p>A human looks at every dataset before it ships. We’d rather have ten that are right than ten thousand that are almost right.</p> - </div> - </li> - <li> - <span class="value-check" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> - <polyline points="20 6 9 17 4 12"/> - </svg> - </span> - <div> - <strong>Schemas that don’t move under you.</strong> - <p>Versioned endpoints, deprecation windows, and a changelog you can subscribe to. If something’s about to break, you’ll be the first to know.</p> - </div> - </li> - <li> - <span class="value-check" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> - <polyline points="20 6 9 17 4 12"/> - </svg> - </span> - <div> - <strong>Every record has a receipt.</strong> - <p>Each row links back to where it came from. Your auditors will love it. Your models will stop making things up.</p> + <div class="catalog"> + {{ range $.Site.Data.catalog.categories }} + <div class="catalog-col"> + <span class="catalog-cat">{{ .name }}</span> + <div class="catalog-window"> + <ul class="catalog-list"> + {{ range .items }}<li>{{ . }}</li> + {{ end }}{{ range .items }}<li aria-hidden="true">{{ . }}</li> + {{ end }} + </ul> </div> - </li> - <li> - <span class="value-check" aria-hidden="true"> - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> - <polyline points="20 6 9 17 4 12"/> - </svg> - </span> - <div> - <strong>One key, every format.</strong> - <p>JSON, XML, CSV, or LLM chunks. Flip a header — same data, different shape.</p> - </div> - </li> - </ul> + </div> + {{ end }} + </div> + + <p class="catalog-more"><strong>100+ datasets</strong> — and the next one we add is whichever one you ask for.</p> </div> </section> -<section id="contact" class="section"> - <div class="container narrow"> - <div class="cta-card"> - <span class="cta-glow" aria-hidden="true"></span> - <h2 class="cta-title">Ready when you are.</h2> - <a href="mailto:hello@tidyindex.com" class="btn btn-primary btn-lg cta-btn"> +<section class="section section-cta"> + <div class="container"> + <div class="cta-block"> + <div class="cta-text"> + <p class="section-marker">§ 04 · start</p> + <h2 class="section-headline">Ready when you are.</h2> + </div> + <a href="mailto:contact@tidyindex.com" class="btn btn-primary btn-lg"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <circle cx="7.5" cy="15.5" r="5.5"/> <path d="m11.5 11.5 9.5-9.5"/> diff --git a/landing/layouts/partials/footer.html b/landing/layouts/partials/footer.html index d6588fe..35cfacc 100644 --- a/landing/layouts/partials/footer.html +++ b/landing/layouts/partials/footer.html @@ -1,6 +1,6 @@ <footer class="site-footer"> <div class="container footer-inner"> - <div class="footer-brand"> + <div class="footer-line"> <span class="brand-mark" aria-hidden="true"> <svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect x="4" y="6" width="24" height="3" rx="1.5" fill="currentColor"/> @@ -8,9 +8,14 @@ <rect x="4" y="22" width="12" height="3" rx="1.5" fill="currentColor" opacity="0.4"/> </svg> </span> - <span>Tidy Index</span> + <span class="footer-name">Tidy Index</span> + <span class="footer-sep">·</span> + <span class="footer-tagline">Structured data, served simply.</span> </div> - <p class="footer-tagline">Structured data, served simply.</p> - <p class="footer-meta">© {{ now.Year }} Tidy Index. All rights reserved.</p> + <p class="footer-meta"> + <a href="mailto:contact@tidyindex.com">contact@tidyindex.com</a> + <span class="footer-sep">·</span> + © {{ now.Year }} + </p> </div> </footer> diff --git a/landing/layouts/partials/header.html b/landing/layouts/partials/header.html index 5f6d85b..e7a9d40 100644 --- a/landing/layouts/partials/header.html +++ b/landing/layouts/partials/header.html @@ -8,13 +8,11 @@ <rect x="4" y="22" width="12" height="3" rx="1.5" fill="currentColor" opacity="0.4"/> </svg> </span> - <span class="brand-name">Tidy Index</span> + <span class="brand-name">Tidy Index</span> </a> - <nav class="site-nav" aria-label="Primary"> - <a href="#what">What</a> - <a href="#formats">Formats</a> - <a href="#how">How it works</a> - <a href="#contact" class="nav-cta">Get access</a> - </nav> + <div class="header-meta"> + <span class="header-status"><span class="status-dot" aria-hidden="true"></span> Private beta</span> + <a href="mailto:contact@tidyindex.com" class="header-cta">API Key →</a> + </div> </div> </header> diff --git a/landing/static/css/style.css b/landing/static/css/style.css index 30665f6..33ddc1b 100644 --- a/landing/static/css/style.css +++ b/landing/static/css/style.css @@ -1,137 +1,147 @@ /* ---------------------------------------------------------------- - Tidy Index — landing styles - Palette: whites, soft blues, generous space. + Tidy Index — landing styles (editorial revision) + + The site is a typeset document, not a SaaS template. + Light palette, generous space, serif headlines, monospace + labels, hairline rules. ---------------------------------------------------------------- */ :root { --c-bg: #ffffff; - --c-bg-soft: #f6f9fc; + --c-bg-soft: #f7f9fc; --c-bg-tint: #eef4fb; - --c-border: #e3ecf5; - --c-border-soft: #eef2f7; + + --c-rule: #e3ecf5; + --c-rule-strong: #cbd6e6; --c-ink: #0b1f3a; --c-ink-soft: #3b4f6b; --c-ink-mute: #6b7c93; - --c-blue: #3b82f6; - --c-blue-deep: #2563eb; + --c-blue: #2563eb; + --c-blue-deep: #1d4ed8; --c-blue-soft: #dbeafe; --c-blue-tint: #eef4ff; - --c-accent: #60a5fa; - --shadow-sm: 0 1px 2px rgba(15, 38, 73, 0.04); - --shadow-md: 0 6px 24px -8px rgba(37, 99, 235, 0.18), - 0 2px 6px rgba(15, 38, 73, 0.04); - --shadow-lg: 0 24px 60px -20px rgba(37, 99, 235, 0.25), - 0 6px 16px rgba(15, 38, 73, 0.06); + --shadow-md: 0 8px 28px -10px rgba(37, 99, 235, 0.18), + 0 2px 6px rgba(15, 38, 73, 0.05); - --radius-sm: 8px; - --radius-md: 14px; - --radius-lg: 22px; + --radius-sm: 6px; + --radius-md: 12px; + --radius-lg: 18px; + --font-serif: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif; --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - --max-w: 1120px; - --max-w-narrow: 760px; + --max-w: 960px; + --max-w-wide: 1080px; + --gutter: clamp(20px, 4vw, 40px); } * { box-sizing: border-box; } -html { -webkit-text-size-adjust: 100%; } +html { + -webkit-text-size-adjust: 100%; +} body { margin: 0; font-family: var(--font-sans); font-size: 17px; - line-height: 1.6; + line-height: 1.65; color: var(--c-ink); background: var(--c-bg); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; - background-image: - radial-gradient(ellipse 80% 50% at 50% -10%, var(--c-blue-tint), transparent 70%), - radial-gradient(ellipse 60% 40% at 90% 10%, #f0f7ff, transparent 70%); - background-repeat: no-repeat; } a { - color: var(--c-blue-deep); + color: var(--c-blue); text-decoration: none; transition: color 160ms ease; } -a:hover { color: var(--c-blue); } +a:hover { color: var(--c-blue-deep); } img, svg { display: block; max-width: 100%; } -/* ---------- layout helpers ---------- */ +::selection { + background: var(--c-blue-soft); + color: var(--c-ink); +} + +/* ---------- layout ---------- */ .container { width: 100%; max-width: var(--max-w); margin: 0 auto; - padding: 0 24px; + padding: 0 var(--gutter); } -.container.narrow { max-width: var(--max-w-narrow); } - -.eyebrow { - display: inline-block; - font-size: 13px; - font-weight: 500; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--c-blue-deep); - background: var(--c-blue-tint); - padding: 6px 12px; - border-radius: 999px; - border: 1px solid var(--c-blue-soft); +.container-wide { + max-width: var(--max-w-wide); } -.eyebrow.center { display: inline-block; } - -.center { text-align: center; } -.center.eyebrow { display: inline-block; } .section { - padding: 120px 0; + padding: 96px 0; + border-top: 1px solid var(--c-rule); } +.section:first-of-type { border-top: 0; } + .section-soft { background: var(--c-bg-soft); - border-top: 1px solid var(--c-border-soft); - border-bottom: 1px solid var(--c-border-soft); } -.section-title { - font-size: clamp(28px, 4vw, 44px); - line-height: 1.15; - font-weight: 600; - letter-spacing: -0.02em; - margin: 18px 0 18px; +/* ---------- shared element styles ---------- */ + +.section-marker { + margin: 0 0 22px; + font-family: var(--font-mono); + font-size: 12px; + font-weight: 500; + letter-spacing: 0.04em; + color: var(--c-blue); + text-transform: lowercase; +} + +.section-headline { + margin: 0 0 28px; + font-family: var(--font-serif); + font-variation-settings: 'opsz' 144, 'SOFT' 30; + font-weight: 400; + font-size: clamp(32px, 4.6vw, 52px); + line-height: 1.08; + letter-spacing: -0.018em; color: var(--c-ink); + max-width: 22ch; } -.section-title.center { text-align: center; max-width: 720px; margin-left: auto; margin-right: auto; } -.section-lede { - font-size: 19px; - color: var(--c-ink-soft); - max-width: 640px; - margin: 0 auto 60px; +.section-headline em { + font-style: italic; + font-variation-settings: 'opsz' 144, 'SOFT' 100; + color: var(--c-blue); +} + +.section-body { + margin: 0 0 48px; + font-size: 18px; line-height: 1.6; + color: var(--c-ink-soft); + max-width: 60ch; } -.section-lede.center { text-align: center; } -/* center the eyebrow when wrapped */ -.section .eyebrow.center, -.container .eyebrow.center { - display: block; - margin-left: auto; - margin-right: auto; - width: max-content; +code { + font-family: var(--font-mono); + font-size: 0.92em; + background: var(--c-bg-soft); + padding: 1px 6px; + border-radius: 4px; + color: var(--c-ink); } /* ---------- header ---------- */ @@ -140,64 +150,80 @@ img, svg { display: block; max-width: 100%; } position: sticky; top: 0; z-index: 50; - background: rgba(255, 255, 255, 0.78); - backdrop-filter: saturate(180%) blur(14px); - -webkit-backdrop-filter: saturate(180%) blur(14px); - border-bottom: 1px solid var(--c-border-soft); + background: rgba(255, 255, 255, 0.85); + backdrop-filter: saturate(180%) blur(16px); + -webkit-backdrop-filter: saturate(180%) blur(16px); + border-bottom: 1px solid var(--c-rule); } .header-inner { display: flex; align-items: center; justify-content: space-between; - height: 72px; + height: 68px; } .brand { display: inline-flex; align-items: center; - gap: 10px; - font-weight: 600; - font-size: 17px; + gap: 12px; + font-family: var(--font-serif); + font-variation-settings: 'opsz' 24; + font-weight: 500; + font-size: 19px; + letter-spacing: -0.005em; color: var(--c-ink); - letter-spacing: -0.01em; } -.brand:hover { color: var(--c-blue-deep); } +.brand:hover { color: var(--c-blue); } .brand-mark { display: inline-flex; align-items: center; justify-content: center; - width: 32px; height: 32px; - color: var(--c-blue-deep); - background: var(--c-blue-tint); - border-radius: 9px; - border: 1px solid var(--c-blue-soft); + width: 30px; + height: 30px; + color: var(--c-blue); } -.brand-mark svg { width: 20px; height: 20px; } +.brand-mark svg { width: 22px; height: 22px; } -.site-nav { +.header-meta { display: flex; align-items: center; - gap: 32px; + gap: 28px; } -.site-nav a { - color: var(--c-ink-soft); - font-size: 15px; - font-weight: 500; + +.header-status { + display: inline-flex; + align-items: center; + gap: 8px; + font-family: var(--font-mono); + font-size: 12px; + letter-spacing: 0.03em; + color: var(--c-ink-mute); + text-transform: lowercase; } -.site-nav a:hover { color: var(--c-blue-deep); } -.nav-cta { - background: var(--c-ink); - color: #fff !important; - padding: 9px 16px; - border-radius: 999px; - transition: transform 160ms ease, background 160ms ease; +.status-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: #34d399; + box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.18); } -.nav-cta:hover { - background: var(--c-blue-deep); - transform: translateY(-1px); + +.header-cta { + font-family: var(--font-mono); + font-size: 13px; + font-weight: 500; + color: var(--c-ink); + letter-spacing: 0.01em; + border-bottom: 1px solid var(--c-ink); + padding-bottom: 1px; + transition: color 160ms ease, border-color 160ms ease; +} +.header-cta:hover { + color: var(--c-blue); + border-color: var(--c-blue); } /* ---------- buttons ---------- */ @@ -206,10 +232,11 @@ img, svg { display: block; max-width: 100%; } display: inline-flex; align-items: center; justify-content: center; - font-family: inherit; - font-size: 16px; + gap: 10px; + font-family: var(--font-sans); + font-size: 15px; font-weight: 500; - padding: 14px 24px; + padding: 13px 22px; border-radius: 999px; border: 1px solid transparent; cursor: pointer; @@ -217,421 +244,536 @@ img, svg { display: block; max-width: 100%; } letter-spacing: -0.005em; } +.btn svg { + width: 17px; + height: 17px; +} + .btn-primary { - background: var(--c-blue-deep); + background: var(--c-ink); color: #fff; - box-shadow: 0 6px 18px -6px rgba(37, 99, 235, 0.5); + box-shadow: 0 6px 18px -8px rgba(11, 31, 58, 0.5); } .btn-primary:hover { - background: #1d4ed8; + background: var(--c-blue); color: #fff; transform: translateY(-1px); - box-shadow: 0 10px 24px -8px rgba(37, 99, 235, 0.55); + box-shadow: 0 10px 22px -8px rgba(37, 99, 235, 0.5); } -.btn-ghost { - background: transparent; - color: var(--c-ink); - border-color: var(--c-border); +.btn-lg { + padding: 16px 26px; + font-size: 16px; } -.btn-ghost:hover { - background: #fff; - border-color: var(--c-blue-soft); - color: var(--c-blue-deep); +.btn-lg svg { + width: 18px; + height: 18px; } -.btn-lg { - padding: 16px 30px; - font-size: 16px; +.btn-link { + display: inline-flex; + align-items: center; + gap: 6px; + font-family: var(--font-sans); + font-size: 15px; + font-weight: 500; + color: var(--c-ink-soft); + border-bottom: 1px solid var(--c-rule-strong); + padding-bottom: 1px; +} +.btn-link:hover { + color: var(--c-blue); + border-color: var(--c-blue); } /* ---------- hero ---------- */ .hero { - padding: 120px 0 80px; + padding: 140px 0 110px; position: relative; overflow: hidden; } -.hero-inner { - text-align: center; - position: relative; +.hero::before { + content: ""; + position: absolute; + top: -200px; + right: -200px; + width: 600px; + height: 600px; + background: radial-gradient(closest-side, rgba(96, 165, 250, 0.20), rgba(96, 165, 250, 0) 70%); + pointer-events: none; + z-index: 0; } -.hero .eyebrow { - margin-bottom: 28px; +.hero .container { + position: relative; + z-index: 1; } -.hero-title { - font-size: clamp(40px, 6vw, 76px); - line-height: 1.05; - font-weight: 600; - letter-spacing: -0.035em; - margin: 0 auto 24px; - max-width: 12ch; +.hero-headline { + margin: 0 0 32px; + font-family: var(--font-serif); + font-variation-settings: 'opsz' 144, 'SOFT' 30; + font-weight: 400; + font-size: clamp(44px, 7.4vw, 92px); + line-height: 1.02; + letter-spacing: -0.025em; color: var(--c-ink); + max-width: 14ch; } -.hero-title .accent { - background: linear-gradient(120deg, var(--c-blue-deep), var(--c-accent)); - -webkit-background-clip: text; - background-clip: text; - color: transparent; +.hero-headline em { + font-style: italic; + font-variation-settings: 'opsz' 144, 'SOFT' 100; + color: var(--c-blue); + font-weight: 400; } .hero-sub { + margin: 0 0 44px; font-size: 20px; line-height: 1.55; color: var(--c-ink-soft); - max-width: 600px; - margin: 0 auto 40px; + max-width: 56ch; } .hero-cta { display: flex; - gap: 14px; - justify-content: center; + align-items: center; + gap: 28px; flex-wrap: wrap; - margin-bottom: 80px; } -/* ---------- code card ---------- */ +/* ---------- record demo ---------- */ + +.record { + margin-top: 8px; + background: #fff; + border: 1px solid var(--c-rule); + border-radius: var(--radius-md); + box-shadow: var(--shadow-sm); + overflow: hidden; +} -.hero-visual { +.record-head { display: flex; - justify-content: center; - margin-top: 16px; + align-items: baseline; + gap: 14px; + padding: 18px 26px; + background: var(--c-bg-soft); + border-bottom: 1px solid var(--c-rule); } -.code-card { - width: 100%; - max-width: 640px; - background: #ffffff; - border: 1px solid var(--c-border); - border-radius: var(--radius-lg); - box-shadow: var(--shadow-lg); - overflow: hidden; - text-align: left; - position: relative; +.record-label { + font-family: var(--font-mono); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--c-ink-mute); } -.code-card::before { - content: ""; - position: absolute; - inset: -1px; - border-radius: inherit; - padding: 1px; - background: linear-gradient(160deg, rgba(96,165,250,0.4), rgba(255,255,255,0) 60%); - -webkit-mask: - linear-gradient(#000 0 0) content-box, - linear-gradient(#000 0 0); - -webkit-mask-composite: xor; - mask-composite: exclude; - pointer-events: none; +.record-id { + font-family: var(--font-mono); + font-size: 14px; + font-weight: 500; + color: var(--c-ink); + background: transparent; + padding: 0; } -.code-card-head { +.record-meta { + margin-left: auto; + font-family: var(--font-mono); + font-size: 12px; + color: var(--c-ink-mute); +} + +.record-row { + display: grid; + grid-template-columns: 200px 1fr; + border-top: 1px solid var(--c-rule); +} + +.record-row:first-of-type { + border-top: 0; +} + +.record-tag { display: flex; - align-items: center; - gap: 8px; - padding: 14px 18px; - background: var(--c-bg-soft); - border-bottom: 1px solid var(--c-border-soft); + flex-direction: column; + justify-content: flex-start; + padding: 24px 26px; + background: #fff; + border-right: 1px solid var(--c-rule); } -.code-card-head .dot { - width: 10px; height: 10px; - border-radius: 50%; - background: #d6dde7; +.tag-name { + font-family: var(--font-serif); + font-variation-settings: 'opsz' 36, 'SOFT' 50; + font-weight: 500; + font-size: 22px; + font-style: italic; + color: var(--c-blue); + margin-bottom: 4px; } -.dot-a { background: #ffd1d1; } -.dot-b { background: #ffe5b4; } -.dot-c { background: #c8e6c9; } -.code-card-title { - margin-left: 12px; +.tag-mime { font-family: var(--font-mono); - font-size: 13px; + font-size: 11px; + letter-spacing: 0.02em; color: var(--c-ink-mute); } -.code-card-body { +.tag-note { + display: block; + margin-top: 10px; + font-family: var(--font-sans); + font-size: 12px; + line-height: 1.4; + color: var(--c-ink-mute); + max-width: 18ch; +} + +.record-body { margin: 0; - padding: 22px 24px; + padding: 22px 26px; font-family: var(--font-mono); font-size: 13.5px; - line-height: 1.65; + line-height: 1.7; color: var(--c-ink-soft); - background: #ffffff; + background: #fff; overflow-x: auto; white-space: pre; } -.code-card-body code { font-family: inherit; } +.record-body code { + background: transparent; + padding: 0; + font-size: inherit; + color: inherit; +} .tk-k { color: #2563eb; } .tk-s { color: #0f766e; } .tk-n { color: #b45309; } .tk-p { color: #94a3b8; } +.tk-x { color: #7c3aed; } +.tk-c { color: #cbd6e6; } -/* ---------- format grid ---------- */ +/* ---------- catalog (dataset coverage widget) ---------- */ -.format-grid { +.catalog { + margin: 8px 0 22px; display: grid; grid-template-columns: repeat(4, 1fr); - gap: 20px; - margin-top: 20px; + border-top: 1px solid var(--c-rule-strong); + border-bottom: 1px solid var(--c-rule); } -.format-card { - background: #fff; - border: 1px solid var(--c-border); - border-radius: var(--radius-md); - padding: 32px 26px; - box-shadow: var(--shadow-sm); - transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease; +.catalog-col { + padding: 30px 24px; + border-right: 1px solid var(--c-rule); } -.format-card:hover { - transform: translateY(-3px); - border-color: var(--c-blue-soft); - box-shadow: var(--shadow-md); +.catalog-col:first-child { padding-left: 0; } +.catalog-col:last-child { + border-right: 0; + padding-right: 0; } -.format-icon { - display: inline-flex; - width: 44px; - height: 44px; - align-items: center; - justify-content: center; - border-radius: 12px; - background: var(--c-blue-tint); - color: var(--c-blue-deep); +.catalog-cat { + display: block; + font-family: var(--font-mono); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.07em; + color: var(--c-blue); + text-transform: lowercase; margin-bottom: 18px; } -.format-icon svg { width: 22px; height: 22px; } - -.format-card h3 { - margin: 0 0 8px; - font-size: 18px; - font-weight: 600; - letter-spacing: -0.01em; - color: var(--c-ink); -} -.format-card p { - margin: 0; - font-size: 15px; - line-height: 1.55; - color: var(--c-ink-mute); -} - -/* ---------- audience grid ---------- */ - -.audience-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 24px; - margin-top: 20px; -} - -.audience-card { +.catalog-window { position: relative; - background: #fff; - border: 1px solid var(--c-border); - border-radius: var(--radius-lg); - padding: 40px 32px; - box-shadow: var(--shadow-sm); - transition: transform 200ms ease, box-shadow 200ms ease; + height: 188px; + overflow: hidden; + -webkit-mask-image: linear-gradient( + to bottom, + transparent 0%, + #000 14%, + #000 86%, + transparent 100% + ); + mask-image: linear-gradient( + to bottom, + transparent 0%, + #000 14%, + #000 86%, + transparent 100% + ); +} + +.catalog-list { + margin: 0; + padding: 0; + list-style: none; + display: flex; + flex-direction: column; + gap: 11px; + animation: catalog-scroll 64s linear infinite; + will-change: transform; } -.audience-card:hover { - transform: translateY(-3px); - box-shadow: var(--shadow-md); +.catalog-col:hover .catalog-list { + animation-play-state: paused; } -.audience-card-feature { - background: linear-gradient(180deg, #ffffff 0%, var(--c-blue-tint) 130%); - border-color: var(--c-blue-soft); -} +/* Stagger speeds slightly so columns don't move in lockstep */ +.catalog-col:nth-child(1) .catalog-list { animation-duration: 58s; } +.catalog-col:nth-child(2) .catalog-list { animation-duration: 72s; } +.catalog-col:nth-child(3) .catalog-list { animation-duration: 64s; } +.catalog-col:nth-child(4) .catalog-list { animation-duration: 68s; } -.audience-num { - font-family: var(--font-mono); - font-size: 13px; - font-weight: 500; - color: var(--c-blue-deep); - letter-spacing: 0.04em; - margin-bottom: 16px; +@keyframes catalog-scroll { + from { transform: translateY(0); } + to { transform: translateY(-50%); } } -.audience-card h3 { - margin: 0 0 12px; - font-size: 22px; - font-weight: 600; - letter-spacing: -0.015em; +.catalog-list li { + font-family: var(--font-serif); + font-variation-settings: 'opsz' 14, 'SOFT' 30; + font-weight: 400; + font-size: 15px; + line-height: 1.3; color: var(--c-ink); } -.audience-card p { +.catalog-more { margin: 0; - color: var(--c-ink-soft); - font-size: 16px; - line-height: 1.6; + font-family: var(--font-mono); + font-size: 12px; + letter-spacing: 0.02em; + color: var(--c-ink-mute); + text-align: right; +} +.catalog-more strong { + font-weight: 500; + color: var(--c-blue); } -/* ---------- value list ---------- */ +/* ---------- CTA section ---------- */ -.value-list { - list-style: none; - padding: 0; - margin: 40px 0 0; - display: grid; - gap: 22px; +.section-cta { + padding: 110px 0 130px; } -.value-list li { +.cta-block { display: flex; - align-items: flex-start; - gap: 18px; - background: #fff; - border: 1px solid var(--c-border); - border-radius: var(--radius-md); - padding: 22px 26px; - box-shadow: var(--shadow-sm); -} - -.value-check { - display: inline-flex; align-items: center; - justify-content: center; - width: 36px; - height: 36px; - flex: 0 0 36px; - border-radius: 50%; - background: var(--c-blue-tint); - color: var(--c-blue-deep); -} -.value-check svg { width: 18px; height: 18px; } - -.value-list strong { - display: block; - font-weight: 600; - font-size: 17px; - color: var(--c-ink); - margin-bottom: 4px; + justify-content: space-between; + gap: 40px; + padding-top: 56px; + border-top: 1px solid var(--c-rule-strong); + position: relative; } -.value-list p { - margin: 0; - color: var(--c-ink-mute); - font-size: 15.5px; - line-height: 1.55; +.cta-block::before { + content: ""; + position: absolute; + top: -1px; + left: 0; + width: 80px; + height: 2px; + background: var(--c-blue); } -/* ---------- CTA card ---------- */ +.cta-block .section-marker { margin-bottom: 14px; } +.cta-block .section-headline { margin: 0; } -.cta-card { - position: relative; +.cta-agents { + margin: 24px 0 0; display: flex; - flex-direction: column; align-items: center; - background: linear-gradient(160deg, #ffffff 0%, var(--c-blue-tint) 100%); - border: 1px solid var(--c-blue-soft); - border-radius: var(--radius-lg); - padding: 72px 40px; - box-shadow: var(--shadow-md); - overflow: hidden; + flex-wrap: wrap; + gap: 14px; + font-family: var(--font-mono); + font-size: 12px; + line-height: 1.5; + color: var(--c-ink-mute); } -.cta-glow { - position: absolute; - top: -120px; - left: 50%; - width: 360px; - height: 360px; - transform: translateX(-50%); - background: radial-gradient(closest-side, rgba(96, 165, 250, 0.35), rgba(96, 165, 250, 0) 70%); - pointer-events: none; - z-index: 0; +.cta-agents-label { + font-weight: 500; + letter-spacing: 0.06em; + text-transform: lowercase; + color: var(--c-blue); } -.cta-title { - position: relative; - z-index: 1; - margin: 0 0 28px; - font-size: clamp(26px, 3.4vw, 36px); - font-weight: 600; - letter-spacing: -0.02em; +.cta-agents a { + display: inline-flex; + align-items: center; + gap: 6px; color: var(--c-ink); - text-align: center; + border-bottom: 1px solid var(--c-rule-strong); + padding-bottom: 1px; + transition: color 160ms ease, border-color 160ms ease; } - -.cta-btn { - position: relative; - z-index: 1; - gap: 10px; +.cta-agents a code { + background: transparent; + padding: 0; + font-size: 12px; + color: inherit; +} +.cta-agents a:hover { + color: var(--c-blue); + border-color: var(--c-blue); } -.cta-btn svg { - width: 18px; - height: 18px; +.cta-agents-note { + font-style: italic; + color: var(--c-ink-mute); } /* ---------- footer ---------- */ .site-footer { - border-top: 1px solid var(--c-border-soft); + border-top: 1px solid var(--c-rule); background: var(--c-bg); - padding: 60px 0 50px; + padding: 40px 0; } .footer-inner { - text-align: center; + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + flex-wrap: wrap; } -.footer-brand { +.footer-line { display: inline-flex; align-items: center; - gap: 10px; - font-weight: 600; + gap: 12px; + font-size: 14px; + color: var(--c-ink-soft); +} +.footer-line .brand-mark { color: var(--c-blue); } +.footer-line .brand-mark svg { width: 18px; height: 18px; } + +.footer-name { + font-family: var(--font-serif); + font-variation-settings: 'opsz' 24; + font-weight: 500; color: var(--c-ink); - margin-bottom: 14px; } -.footer-brand .brand-mark { color: var(--c-blue-deep); } -.footer-brand .brand-mark svg { width: 20px; height: 20px; } .footer-tagline { - margin: 0 0 12px; - color: var(--c-ink-soft); - font-size: 15px; + font-style: italic; + color: var(--c-ink-mute); +} + +.footer-sep { + color: var(--c-rule-strong); } .footer-meta { margin: 0; + font-family: var(--font-mono); + font-size: 12px; color: var(--c-ink-mute); - font-size: 13px; +} +.footer-meta a { + color: var(--c-ink-soft); + border-bottom: 1px solid var(--c-rule-strong); +} +.footer-meta a:hover { + color: var(--c-blue); + border-color: var(--c-blue); } /* ---------- responsive ---------- */ -@media (max-width: 880px) { - .format-grid { grid-template-columns: repeat(2, 1fr); } - .audience-grid { grid-template-columns: 1fr; } - .section { padding: 90px 0; } - .hero { padding: 80px 0 40px; } -} - -@media (max-width: 640px) { +@media (max-width: 1020px) { + .catalog { + grid-template-columns: repeat(2, 1fr); + border-bottom: 0; + } + .catalog-col { + padding: 28px 24px; + border-right: 1px solid var(--c-rule); + border-bottom: 1px solid var(--c-rule); + } + .catalog-col:first-child { padding-left: 24px; } + .catalog-col:last-child { + border-right: 1px solid var(--c-rule); + padding-right: 24px; + } + .catalog-col:nth-child(2n) { border-right: 0; padding-right: 0; } + .catalog-col:nth-child(2n+1) { padding-left: 0; } + .catalog-col:nth-last-child(-n+2) { border-bottom: 0; } +} + +@media (max-width: 820px) { + .section { padding: 72px 0; } + .hero { padding: 90px 0 70px; } + .section-cta { padding: 80px 0 100px; } + + .record-row { + grid-template-columns: 1fr; + } + .record-tag { + flex-direction: row; + align-items: baseline; + gap: 12px; + padding: 16px 22px; + border-right: 0; + border-bottom: 1px solid var(--c-rule); + background: var(--c-bg-soft); + } + .tag-name { margin-bottom: 0; font-size: 18px; } + + .cta-block { + flex-direction: column; + align-items: flex-start; + } +} + +@media (max-width: 620px) { + .catalog { + grid-template-columns: 1fr; + } + .catalog-col { + padding: 24px 0; + border-right: 0; + border-bottom: 1px solid var(--c-rule); + } + .catalog-col:first-child { padding-top: 24px; } + .catalog-col:last-child { border-bottom: 0; padding-bottom: 0; } +} + +@media (max-width: 560px) { body { font-size: 16px; } - .site-nav { gap: 18px; } - .site-nav a:not(.nav-cta) { display: none; } - .header-inner { height: 64px; } - .hero-cta { flex-direction: column; align-items: stretch; } - .hero-cta .btn { width: 100%; } - .code-card-body { font-size: 12px; padding: 18px; } - .format-grid { grid-template-columns: 1fr; } - .cta-card { padding: 40px 24px; } + .header-status { display: none; } + .header-inner { height: 60px; } + .hero-cta { gap: 18px; } + .record-head { flex-wrap: wrap; padding: 16px 20px; } + .record-meta { margin-left: 0; flex-basis: 100%; } + .record-body { font-size: 12.5px; padding: 18px 20px; } + .footer-inner { flex-direction: column; align-items: flex-start; } } @media (prefers-reduced-motion: reduce) { * { transition: none !important; } + + .catalog-window { + overflow-y: auto; + -webkit-mask-image: none; + mask-image: none; + } + .catalog-list { + animation: none; + } + .catalog-list li[aria-hidden="true"] { + display: none; + } } diff --git a/landing/static/llms.txt b/landing/static/llms.txt new file mode 100644 index 0000000..9cf358a --- /dev/null +++ b/landing/static/llms.txt @@ -0,0 +1,99 @@ +# Tidy Index + +> Clean, well-structured datasets for humans, machines, and LLM agents. +> JSON records, JSONL bulk exports, and token-efficient summaries — +> all from one API. + +Status: private beta. The endpoints below are the planned shape. If you +hit one that isn't live yet, email contact@tidyindex.com and we'll let you +know when it ships. + + +## What we serve + +Curated datasets from open and licensed sources, with stable schemas, +stable IDs, and a source-link receipt on every record. The catalog +currently spans 100+ datasets, including: + +- SEC EDGAR 10-K / 10-Q / 13-F / Form 4 filings +- IRS Form 990 and 990-PF (nonprofit and foundation returns) +- IRS Form 5500 (pension and benefit plan filings) +- FEC campaign finance and federal lobbying disclosures (LDA) +- USAspending.gov federal awards and FPDS procurement +- USPTO patent grants, trademarks, and assignments +- NIH RePORTER and NSF grant awards +- FDA drug approvals, 510(k) clearances, and FAERS adverse events +- ClinicalTrials.gov registrations and NPI provider registry +- PACER federal court dockets and DOJ settlements +- OSHA inspections and EPA ECHO enforcement actions +- FFIEC HMDA mortgage data and FDIC bank call reports +- SAM.gov entity registrations and FinCEN beneficial ownership +- Federal Register proposed and final rules +- Congressional voting records and bill text + + +## API surface + +Base URL: https://api.tidyindex.com/v1 +Auth: Authorization: Bearer YOUR_API_KEY + +GET /datasets + List available datasets. + +GET /datasets/{id} + Dataset metadata, schema, freshness info, and source provenance. + +GET /datasets/{id}/records + Query records. Paginated, filterable. Returns application/json. + +GET /datasets/{id}/records/{record_id} + Single normalized record. Returns application/json. + +GET /datasets/{id}/bulk + Streaming export. Returns application/x-ndjson, one record per line. + +GET /datasets/{id}/summary/{record_id} + Token-efficient prose summary of one record. Returns text/plain. + Cheaper on context than the full JSON. Includes a source URL footer. + +Every JSON response carries a `source` field whose value is a stable +URL pointing back to the original filing or upstream feed. + + +## Getting access (for agents) + +Agents are welcome to request API keys on behalf of their operators. +Send a JSON POST to: + + POST https://api.tidyindex.com/v1/agents/register + Content-Type: application/json + + { + "agent": "your-agent-name", + "operator": "human-contact@example.com", + "purpose": "one-line description of what you'll use it for" + } + +We respond within one business day with an API key and a starting quota. +Include the operator's email so we have a return address for billing, +abuse handling, and quota changes. + + +## Conventions + +- All timestamps are ISO 8601 in UTC. +- Currency fields are named with their unit suffix (e.g., revenue_usd + is whole U.S. dollars as an integer). +- Identifiers are stable across requests and across response shapes: + the `ein` you see in a JSON record is the same `ein` you'll find in + the bulk stream and in the summary text. +- Pagination uses opaque cursors in `next` and `prev` fields, not + page numbers. +- Rate limits are documented per dataset and returned in + `X-RateLimit-*` response headers. + + +## Contact + +contact@tidyindex.com +https://tidyindex.com diff --git a/landing/static/robots.txt b/landing/static/robots.txt index f0d8319..6bddef4 100644 --- a/landing/static/robots.txt +++ b/landing/static/robots.txt @@ -2,3 +2,6 @@ User-agent: * Allow: / Sitemap: https://tidyindex.com/sitemap.xml + +# Machine-readable site description for LLM agents: +# https://tidyindex.com/llms.txt |
