Files
cali_scraper/design/INDEX.html
T
2026-09-06 10:18:26 -07:00

91 lines
6.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Legislative Dashboard — Design deliverables (index)</title>
<style>
:root{--ink:#1a1a1a;--muted:#5b5b5b;--paper:#fff;--surface:#f4f5f7;--border:#d5d9df;
--accent:#0b5394;--accent-ink:#08345f;
--ring:0 0 0 2px #fff,0 0 0 4px var(--accent);
--font-ui:-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
--radius:4px;--shadow:0 1px 2px rgba(0,0,0,.06),0 2px 8px rgba(0,0,0,.05);--maxw:900px}
*{box-sizing:border-box}html,body{margin:0}
body{font-family:var(--font-ui);color:var(--ink);background:var(--surface);font-size:15px;line-height:1.55;text-wrap:pretty}
a{color:var(--accent);text-underline-offset:2px}h1,h2{line-height:1.2;margin:0}
:where(a,button):focus-visible{outline:none;box-shadow:var(--ring);border-radius:var(--radius)}
.wrap{max-width:var(--maxw);margin:0 auto;padding:32px 20px 64px}
.eyebrow{font-size:12px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);font-weight:600}
h1{font-size:26px;margin:6px 0 4px}
.lede{color:var(--muted);max-width:64ch;margin:0 0 22px}
.card{display:block;background:var(--paper);border:1px solid var(--border);border-radius:var(--radius);
padding:16px 18px;margin-bottom:12px;box-shadow:var(--shadow);text-decoration:none;color:inherit}
.card:hover{border-color:var(--accent)}
.card .t{font-weight:600;font-size:16px}
.card .d{color:var(--muted);font-size:14px;margin-top:3px}
.card .k{font-family:ui-monospace,Menlo,monospace;font-size:12px;color:var(--accent);margin-top:8px;display:block}
h2{font-size:14px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:26px 0 10px}
.open{background:var(--paper);border:1px solid var(--warn,#8a5a00);border-radius:var(--radius);padding:14px 16px}
.open b{color:#8a5a00}
.open ul{margin:8px 0 0;padding-left:18px}.open li{margin:4px 0}
footer{color:var(--muted);font-size:12px;border-top:1px solid var(--border);padding-top:14px;margin-top:24px}
</style>
</head>
<body>
<div class="wrap">
<div class="eyebrow">Spec §5 · UI lane · wireframes + contract</div>
<h1>Legislative Dashboard — Design deliverables</h1>
<p class="lede">The UX design for the anonymous + personalized California-legislature dashboard. One surface, two personas: anonymous sees a chronological overview of <em>upcoming</em> legislation; logged-in users set a ZIP → find legislators → watch them + opt into topics, and matching bills float to the top. This is the design a backend/frontend engineer implements — not the build itself.</p>
<h2>Read first</h2>
<a class="card" href="DESIGN_DASHBOARD.md">
<span class="t">DESIGN_DASHBOARD.md — the design</span>
<span class="d">Information architecture, the two flows (anonymous vs. logged-in), the "float to top" ranking model, the "upcoming" definition, layouts, all six empty states, the ZIP→legislator resolution model, and the visual/interaction system.</span>
<span class="k">design/DESIGN_DASHBOARD.md</span>
</a>
<a class="card" href="API_CONTRACT.md">
<span class="t">API_CONTRACT.md — what the UI consumes</span>
<span class="d">Shared JSON shapes (bill list, watched-legislator / preference blob, tag cloud, ZIP-district resolve, error envelope) so the build, correlation, and LLM lanes share one contract. Auth-agnostic, field-name-stable, degradeable.</span>
<span class="k">design/API_CONTRACT.md</span>
</a>
<h2>Wireframes (open in a browser)</h2>
<a class="card" href="wireframes/anon-dashboard.html">
<span class="t">01 · Anonymous dashboard</span>
<span class="d">Chronological "upcoming legislation" queue grouped by day, personalization-lite filters (no login), a non-annoying "unlock" affordance that names the value, top-topics teaser.</span>
<span class="k">design/wireframes/anon-dashboard.html</span>
</a>
<a class="card" href="wireframes/logged-in-dashboard.html">
<span class="t">02 · Logged-in dashboard</span>
<span class="d">The floated "Relevant to you" band with meaning-cued indicators + "why is this here?" transparency, the ZIP-setup empty state (with all four resolve outcomes), and live watch/opt-in toggles that re-rank. Top toggle switches between personalized / setup / anon states.</span>
<span class="k">design/wireframes/logged-in-dashboard.html</span>
</a>
<a class="card" href="wireframes/watch-and-opt-in-controls.html">
<span class="t">03 · Watch / opt-in controls</span>
<span class="d">Every control and every state (default, checked, focus, disabled, pending) for legislator-watch toggles and topic opt-in chips, plus the zoomed-up legend for the float-reason indicators.</span>
<span class="k">design/wireframes/watch-and-opt-in-controls.html</span>
</a>
<h2>Open decisions (for the orchestrator / owner — not silently assumed)</h2>
<div class="open">
<b>D1 · Auth method.</b>
<ul>
<li><b>Recommended:</b> minimal email + local account (D1a), with OAuth (Google/Apple) offered as an alternative for residents who don't want a new password (D1b).</li>
<li>The <em>preferences/personalization shape is identical under either</em> — that's the point of keeping auth out of the data contract. <code>/person</code>, <code>/prefs</code>, <code>/watch</code>, <code>/topics</code> just need a bearer token.</li>
</ul>
<b>D2 · ZIP vs. full address as the primary input + data-source provenance/freshness.</b>
<ul>
<li><b>Design position (flagged, not decided):</b> a ZIP <em>alone cannot reliably resolve a California district</em> — zips straddle Assembly/Senate boundaries (e.g., 95602 Auburn ≈ 31% A-1 / 69% A-5). The authoritative path is <code>findyourrep.legislature.ca.gov</code> by full address; ZIP-district boundaries come from published datasets (Legislature / <code>data.ca.gov</code>, Esri zip-derived).</li>
<li><b>Recommended:</b> ZIP as the fast path with an automatic "verify by address / pick a district manually" fallback on ambiguous/zero/out-of-state; consider making address the <em>primary</em> input if we don't want to ship "possibly wrong district" personalization. Owner must decide which is primary and <em>ratify the data source + its redistricting refresh cadence</em> re: the correlation lane.</li>
</ul>
<b>D3 · Ranking weights.</b>
<ul>
<li>Design default: <code>score = 3·(author watched) + 2·(sits-in watched legislator's committee) + 2·(opted-in tag matches) + 1·(home-chamber)</code>. Weights are tunable; owner may adjust, but the band-membership rule (<code>score &gt; 0</code> = relevant) is the contract the build must keep stable.</li>
</ul>
</div>
<footer>Design by the UI/UX lane · 2026-09-05 · Companion to scraper/schema.py (BillAction) + LLM tag lane (per-bill tags) + correlation lane (districts/members/rosters). Wireframes are HTML mockups, not the implementation.</footer>
</div>
</body>
</html>