Skip to content

feat: Stadium v3 — rack/poster redesign + brightness dial + WebZero palette#92

Merged
sacha-l merged 20 commits into
developfrom
feat/v3-rack-design
May 20, 2026
Merged

feat: Stadium v3 — rack/poster redesign + brightness dial + WebZero palette#92
sacha-l merged 20 commits into
developfrom
feat/v3-rack-design

Conversation

@sacha-l
Copy link
Copy Markdown
Collaborator

@sacha-l sacha-l commented May 20, 2026

Summary

Full client design-system replacement: purple/dark-only → grayscale "rack-unit" hardware aesthetic with a continuous brightness dial that auto-tracks local time-of-day, a palette system so any color scheme drives the dial, and a built-in WebZero (cream / ink / vermillion / teal / lime) palette. All 9 pages rebuilt; 15 dead components removed.

What ships

Foundation (Phases 1–9)

  • Tokens — grayscale hardware tokens (shell, panel-*, hairline*, display*, body, label-*, led), 2px radius; old purple/dark token system removed.
  • Fonts — Inter (prose), JetBrains Mono (UI chrome/labels/LCDs), Archivo Black as font-display for hero titles.
  • Hardware utilities.panel, .lcd, .lcd-readout, .led / .led-sm / .led-pulse, .label-hw / .label-hw-dim, .scanlines. Old .hero-title, .purple-glow, .crt, .glass-panel gone.
  • Brightness systemlib/brightness.ts lerps full H/S/L between four anchors; lib/solar.ts maps local clock to a 0–100 cosine; hooks/use-brightness.ts owns state + localStorage.
  • BrightnessRack — slider + AUTO toggle + PALETTE picker, sticky in the Navigation on every page.
  • 6 new componentsUnitCard, UnitDetailModal, LCDStat, MilestoneTrack, InputBus, HardwareToggle.

Palette system

  • lib/palettes.ts registry — each palette = four anchors of 12 HSL tokens + a constant LED accent. Adding another palette is one object entry.
  • Two palettes ship: RACK (default grayscale, green LED) and WEBZERO (cream paper / ink type / vermillion + teal panel tints / lime LED).
  • Selection persists alongside brightness in localStorage.

All 9 pages rebuilt (Phase 10)

HomePage, M2ProgramPage (3-rack Under Review/Building/Graduates layout), WinnersPage, ProgramsPage, ProgramDetailPage, AdminProgramPage, AdminPage (LCDStats + panel sections + rack-styled action buttons), ProjectDetailsPage (hero chrome restyled; data + tabs preserved), NotFound. Every page preserves its existing data fetching, filtering, wallet flows, and modals; only the chrome is rebuilt.

Cleanup (Phases 11/12/14)

  • 15 dead components deleted after import-graph audit:
    theme-toggle, Header, ProjectCard, ProjectBubble, ProgramCard, ProjectCarousel, ProjectDetailsDrawer, M2StatusOverview, DemoVideoModal, DemoPlayer, ProjectDetailModal, M2ProgramGuideModal, M2ProjectTable, EditTeamModal, UpdatePayoutModal.
  • Live components scrubbed of leftover purple / glass-panel: M2SubmissionTimeline, M2AgreementSection, TeamPaymentSection, EditM2AgreementModal, TestPaymentModal.
  • index.html meta theme-color#0A0A0A.
  • Vite-boilerplate App.css deleted.
  • Phase 13 (chart palette): n/a — no chart libs in the app.

Grep audits — all return zero

purple / violet / 9333EA / C084FC / atariGreen|Blue  → 0
hero-title / purple-glow / .crt / glass-panel        → 0
Orbitron / Righteous / Space Mono / Redaction20      → 0
rounded-xl|2xl|3xl / shadow-md|lg|xl / backdrop-blur → 0

Adaptations from the spec

  • Spec used wouter; this repo uses react-router-dom v6Navigation and page links adapted accordingly.
  • Spec proposed lowercase component filenames; existing pages keep their PascalCase convention (Navigation.tsx, HomePage.tsx, …). New components are kebab-case (unit-card.tsx, …), consistent with the repo's existing theme-provider.tsx style.
  • Spec only fully restyled Home + M2; the user chose full restyle of every page — included.

Test plan

  • cd client && npm run build (tsc + vite) — green at every commit.
  • cd client && npm run lint (--max-warnings 0) — green at every commit.
  • ⚠️ Visual review needs a browser:
    • cd client && npm run dev
    • Exercise the brightness dial 0 → 100 on each palette; confirm scanlines fade, role-inversion at 50%.
    • Navigate every route (/, /m2-program, /programs, /programs/<slug>, /admin, /admin/programs/<slug>, /m2-program/<id>, /winners/<hackathon>, /this-does-not-exist).
    • Toggle palette RACK ↔ WEBZERO; confirm cream/ink + lime LED render correctly.
    • Sign-in flows (Polkadot-JS / MetaMask / Phantom) unchanged from feat: multi-chain sign-in — Substrate + Ethereum + Solana #84 — verify connect + sign still work.

Known limitations — by design

  • Inner section components inherit the token swap but keep their pre-v3 layouts. TeamPaymentSection, M2AgreementSection, M2SubmissionTimeline, ApplicationCard, WinnersTable, M2ProjectsTable, ProgramsTable, FilterSidebar, ApplyToProgramModal, the family of edit/submit/share modals, NotificationsCard, ProjectUpdatesTab, ProjectProgramsSection, FundingSignalBadge — all render grayscale (or WebZero) and work, but their internal Card/Badge/Button chrome isn't "rack-polished." Each is a focused follow-up.
  • The "What is the M2 Program?" disclosure (previously in M2ProgramGuideModal) was dropped with the dead-file purge. Easy to bring back as a small panel if you want.

Sequencing with launch

This is a major visual change. You chose before launch — so the launch-checklist (PR #91) work resumes against the v3 chrome. The multi-chain sign-in (#84), domain check (#86), nonce/replay (#89), and M2 entitlement schema (#87) all still apply; only the visual layer changed.

🤖 Generated with Claude Code

sacha-l added 13 commits May 19, 2026 22:45
Begin the v3 rack-unit redesign — grayscale hardware aesthetic with a
continuous time-tracking brightness dial.

- index.css: replace purple light/dark tokens with grayscale hardware
  tokens (S=0, lightness-only); 2px radius; add panel/lcd/led/label-hw
  utility classes; drop hero-title/purple-glow/crt/glass-panel.
- Fonts: Inter + JetBrains Mono only; delete fonts.css (Redaction20)
  and the Orbitron/Righteous/Space Mono imports.
- tailwind.config: grayscale + hardware colour tokens; fontFamily
  reduced to sans/mono; drop atari*/sidebar/success/warning.
- Brightness system: lib/brightness.ts, lib/solar.ts,
  hooks/use-brightness.ts — a 0-100 dial that auto-tracks local time,
  inverts text/surface roles at 50%, persists to localStorage.
- App.tsx: remove forced dark mode; call useBrightness().
- Navigation + BrightnessRack components.

Client build + lint green. Components/pages restyled in later phases.
Six new rack-aesthetic components: UnitCard, UnitDetailModal, LCDStat,
MilestoneTrack, InputBus, HardwareToggle. Self-contained; wired into
pages in Phase 10. Build + lint green.
- Palettes are now data, not hard-coded. lib/palettes.ts holds a registry
  of palettes; each defines four brightness anchors (dark/dusk/dawn/light)
  as full H/S/L triplets plus a constant LED accent. Adding a palette is
  a single object entry.
- Brightness math (lib/brightness.ts) lerps H, S, and L across anchors,
  so the dial works with any colour scheme — not just grayscale.
- WebZero palette added: cream paper / ink type, vermillion + teal panel
  tints, lime LED. Grayscale ("RACK") remains the default.
- useBrightness exposes paletteKey + setPalette + palettes; selection
  persists alongside brightness in localStorage.
- BrightnessRack gains a PALETTE row with a HardwareToggle so users can
  switch palettes from the always-visible rack.
- Icons in UnitCard / UnitDetailModal action buttons sit at text-label-mid
  rather than full display, so they read cleanly across the brightness
  range instead of punching out at the high end.

Client build + lint green.
WebZero's hero typography is heavy uppercase poster type — the v3 spec
only carried Inter + JetBrains Mono. Adding Archivo Black as a third
role, `font-display`, for hero/title text:

- index.css: pull Archivo Black from Google Fonts alongside Inter and
  JetBrains Mono.
- tailwind.config: add a `display` fontFamily — Archivo Black with Inter
  as fallback.
- UnitCard title and UnitDetailModal title switch from font-mono bold to
  font-display uppercase with tight tracking, so unit names read as
  poster headlines rather than monospaced labels.

Inter (prose) and JetBrains Mono (UI chrome, LCD readouts, hardware
labels) stay where they are. Display font is global — works for both
RACK and WEBZERO palettes.

Client build + lint green.
Preserve all existing data fetching, filtering, hackathon select and
search; restructure the UI per the spec.

- Scanlines wrapper + Navigation.
- Hero: ·DIRECTORY / NOW SHOWING label, big uppercase font-display
  wordmark, body intro, partner logos (no cosmic background / purple
  glow).
- Index stats: panel with four LCDStats — Total Units, Winners (pulse),
  In M2, Paid (USDC sum across totalPaid).
- Featured "·NOW SHOWING" section: pinned UnitCard for the most recent
  M2 graduate (when available).
- Filter bar: InputBus search (⌘K), lcd-styled hackathon select,
  HardwareToggle for WINNERS/ALL, FILTERS sheet that still opens the
  existing FilterSidebar (unrestyled internals; gets its own pass).
- Grid: UnitCard per project, three columns.
- Footer panel with the rack signature row.

Removed in this rebuild: ProjectCard, ProjectDetailModal, SearchBar,
framer-motion animations, glass-panel hero card, rounded brand-color
stat cards — superseded by the rack components/utilities.

Client build + lint green.
Replace the old M2 page (cards/table view, glass-panel header,
emoji-heavy status cards) with the spec's three-rack layout. All data
fetching, the "mine" filter via wallet, search and status filters are
preserved.

- LCDStats: Building / Under Review (pulse) / Graduates — counts from
  the unfiltered cohort so totals don't shift with the filter.
- InputBus search + two HardwareToggles (ALL/MINE, ALL/BUILDING/REVIEW
  /GRAD).
- Three M2Racks (Under Review, Building, Graduates). Each row uses
  MilestoneTrack, with milestone position inferred from m2Status
  (schema has no per-project milestone breakdown today).
- Wallet-based "MINE" filter routed through useWalletAuth, so it works
  across all three sign-in chains (#84).
- Removed: M2StatusOverview, M2ProgramGuideModal, M2ProjectTable,
  ProjectCard, framer-motion, the Tabs/Select chrome.

Client build + lint green.
UnitCard grid + UnitDetailModal; preserved data fetching (hackathon
slug -> winners). Drops the trophy emoji header for label-hw rack
chrome; the trophy icon stays as an empty-state visual.

Client build + lint green.
Inline ProgramRackCard (lcd surface, font-display title, OPEN/pulse LED,
labelled event/applications dates). Drops the soft ProgramCard chrome.
Old ProgramCard component is no longer imported here; left in place
since other surfaces may still reference it.

Client build + lint green.
NotFound: panel-wrapped 404 page with rack chrome — drops the purple
underline link and the bg-gray-100 wash.

ProgramDetailPage: data unchanged (program lookup, wallet's projects,
existing-application lookup with focus-refetch). Restyled to scanlines
+ panels: hero with font-display name, LCD-styled status pill, key
dates in a panel, rack-styled Apply CTA covering every state (closed,
applied, no wallet, no projects, ready to apply). Wallet connect goes
through useWalletAuth — works across all three sign-in chains.

ApplyToProgramModal kept as-is (gets its own pass).

Client build + lint green.
- SIWS signing for the admin-gated listProgramApplications routed through
  auth.signAction (useWalletAuth) — drops the inline web3Enable/SiwsMessage
  block and works across all three sign-in chains (#84).
- Admin gating uses chain-aware isAdmin(address, chain).
- Status filters become a HardwareToggle (SUBMITTED/ACCEPTED/REJECTED/
  WITHDRAWN/ALL); LOAD/REFRESH is a rack button.
- Empty/loading/not-found states wrapped in panels with label-hw chrome.
- ApplicationCard kept as-is.

Client build + lint green.
Preserve all data + handlers (admin auth via useWalletAuth, M2 approve,
status change, M1/M2 payment confirm, modals). Restyle the chrome:

- Auth screen: panel + font-display title; error block is an lcd panel
  with the wallet/expected address lists in mono.
- Loading: panel-wrapped spinner.
- Header: font-display title, rack-styled action buttons (CREATE PROJECT,
  TEST PAYMENT, LOGOUT); admin identity shown in an lcd pill.
- Stats: four Cards -> four LCDStats (Total, Pending Review pulse, M2
  Graduates, Paid Out as compact USD).
- Pending Review: glass-panel -> panel; each project card is an lcd with
  font-display title, label-hw deliverables row, primary rack button for
  approve.
- All Winners / All M2 / Programs: wrapped in panels with label-hw
  headers. Sort Select replaced by a HardwareToggle (EVENT / A-Z /
  RECENT).
- WinnersTable / M2ProjectsTable / ProgramsTable / modals kept as-is.

Client build + lint green.
Targeted restyle on a 1500-line page — preserve every handler and the
existing tab/modal structure, just swap the chrome for the rack
aesthetic:

- scanlines wrapper; main no longer needs the pt-16 (Navigation is
  sticky, not fixed).
- Loading and not-found wrapped in panels with label-hw chrome and a
  rack-styled back link.
- Hero rebuilt: label-hw unit number, hard-rectangle WINNER/M2/category
  badges, font-display uppercase project name, label-hw-dim meta line
  in all caps, rack-styled (border-hairline, font-mono) link buttons
  for live/source/demo/slides/share/edit.

Inner tab content (Overview, Milestones, Team & Payments, Updates) and
the nested components (M2SubmissionTimeline, TeamPaymentSection,
ProjectUpdatesTab, NotificationsCard, etc.) inherit the token swap and
keep working — their finer polish stays for a focused later pass.

Client build + lint green.
- Phase 11 grep audit: replace remaining purple Tailwind classes with
  token-based equivalents in M2AgreementSection, EditM2AgreementModal,
  TestPaymentModal. Swap glass-panel for panel in M2SubmissionTimeline,
  M2AgreementSection, TeamPaymentSection.
- Delete 15 dead components confirmed orphan by import audit:
  theme-toggle, Header, ProjectCard, ProjectBubble, ProgramCard,
  ProjectCarousel, ProjectDetailsDrawer, M2StatusOverview, DemoVideoModal,
  DemoPlayer, ProjectDetailModal, M2ProgramGuideModal, M2ProjectTable,
  EditTeamModal, UpdatePayoutModal — replaced by the v3 components.
- Phase 12 audit: zero matches left for rounded-xl/2xl/3xl, shadow-md/
  lg/xl, backdrop-blur in app code (all violations were in the deleted
  files).
- Phase 14: add <meta name=theme-color content=#0A0A0A> to index.html;
  delete unused App.css (Vite boilerplate).

Phase 13 (chart palette) — no charts in this app, nothing to do.

Client build + lint green.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stadium Ready Ready Preview, Comment May 20, 2026 1:28pm

sacha-l added 4 commits May 20, 2026 14:41
- Card chrome -> lcd panels for read-only/edit member cards, payout
  display, payment history rows, M2 pending tile.
- Section headers (Team Members, Payment Information, Payment History)
  become label-hw chrome with icon.
- Badge -> bordered mono span for role, chain, milestone tags.
- text-green-500 -> text-led on the copy/confirm checks.
- Rack-styled action buttons (Edit, Add Member, Save, Cancel) replace
  the shadcn Button defaults.
- No data/handler changes; payout-save flow and multi-chain selectors
  unchanged.

Build + lint green.
…ack chrome

NotificationsCard: Card → panel; CardTitle → label-hw header; loading state
uses LOADING… label-hw-dim with led indicator on the email-on-file branch;
inputs keep shadcn Input but labels are uppercased; Save/Cancel become rack
buttons with bordered display fill.

M2AgreementSection: drops the unused Button/Badge shadcn imports; panel
header uses label-hw chrome with hairline separator; per-section headers
(Core Features / Documentation / Success Criteria) get label-hw with
appropriate icon tones (led for completion-style, label-mid for neutral,
destructive for the post-week-4 lock); content blocks become lcd panels;
bullet markers swap • → · in the display tone; footer note becomes
label-hw-dim or lcd destructive depending on lock state.

FundingSignalBadge: replaces shadcn Badge with a bordered mono span using
display tone + small LED, fitting the rack vocabulary while keeping the
signal.description body copy readable.
…ProjectModal

ApplyToProgramModal: DialogTitle becomes the poster font-display in
all-caps, body description keeps text-body; Labels become label-hw-dim
captions; the counter swaps between label-hw-dim / label-hw destructive
depending on overflow; Cancel and Submit buttons become rack-styled
ghost / display-fill respectively, with the same SUBMITTING… / ▸ idiom
the rest of the v3 chrome uses.

ProjectUpdatesTab: Card → panel for the empty state; per-update Cards
become panels with label-hw-dim meta row (mono-cased address + date),
text-body for the prose, mono link styling for u.linkUrl. Loading +
error states get label-hw chrome. Post button is rack-styled with
display fill.

ApplicationCard: shadcn Card/Badge/Button dropped in favor of a panel
with hairline-separated header. Status badge maps to a bordered mono
span — accepted gets display fill, withdrawn/rejected get hairline +
label-mid, submitted gets the bordered display-on-deep treatment.
Accept/Reject buttons mirror the apply-modal pattern (display fill +
hairline outline).

ShareProjectModal: title gets font-display + uppercase, Labels →
label-hw-dim, share buttons become rack-styled outlines with mono caps,
copy-affordance is a 36px square outlined button, the check icon flips
to text-led when copied. Drops the unused 'error' parameter on the
clipboard catch block.
ProjectProgramsSection: Card/Header/Content/Badge/Button → panel + label-hw
header + bordered mono status badge. Refresh button becomes an outlined
square sized to match the badge, with text-label-mid → display on hover.

FilterSidebar: shadcn Card and Separator dropped in favor of panel with
hairline-subtle dividers. Category and Winners rows become uniform
'rack rows' — mono uppercase with hairline borders, display fill for the
active winners pill, panel-deep fill for active categories. Clear-filters
becomes a centered ghost row. Yellow trophy treatment is gone; the
pulse animation on Trophy stays as the only motion.
sacha-l added 2 commits May 20, 2026 15:18
…, PostUpdateModal

M2SubmissionTimeline: Card/Header/Badge/Alert/Button dropped. The shell is
now a panel with label-hw header + LED-tagged status pill (display fill
for completed, panel-deep for under_review, hairline for building).
Checklist rows extracted into a small ChecklistRow helper rendering each
state as an lcd block with text-led for done items and label-hw-dim for
the trailing date/payout meta. The submitted-/-approved confirmation is a
border-led lcd; gated states (not connected / not team) become lcd
captions. Submit button is a wide rack action with display fill.

EditProjectDetailsModal: just the chrome — DialogTitle gets font-display
+ all-caps, footer Cancel/Save become the rack outline + display-fill
button pattern. The form fields themselves still use shadcn Input/Textarea
which already render in the new tokens.

UpdateTeamModal: per-member 'border-subtle/bg-muted/30' wrappers → lcd
panels; section headings → label-hw text-display; remove-member icon
button → small bordered square that goes hover-destructive; Add Member +
Cancel + Save Changes adopt the rack button pattern. All Labels become
label-hw-dim mono captions and Inputs get font-mono for the address feel.

PostUpdateModal: same treatment — DialogTitle font-display, label-hw-dim
labels, mono Textarea/Input, label-hw error + count row, rack-styled
footer buttons with the POSTING… / ▸ idiom.
…n payment modals

EditFundingSignalModal: full restyle — DialogTitle gets font-display, the
'Actively seeking funding' wrapper becomes an lcd block with label-hw
chrome + label-hw-dim help text, Switch unchanged. Inner Labels/Inputs/
Textarea/Select all swap to label-hw-dim labels + font-mono inputs.
Error + counter row uses the label-hw / label-hw-dim split. Footer
buttons are the rack outline + display-fill pattern.

FinalSubmissionModal: same treatment. The yellow Alert becomes an lcd
panel with the AlertTriangle icon + display-toned label-hw warning. The
checkbox confirmation sits inside an lcd panel so it reads as 'arming
the action.' Drops the unused Alert/Button shadcn imports.

SubmitM2DeliverablesModal: full restyle. Both Alerts (warning at top,
success-tone tip at bottom) become lcd panels with display-toned
AlertTriangle + LED-toned Lightbulb. Field labels gain their leading
lucide icon at h-3 in the label-hw line; inputs get font-mono. Error +
counter rows match the EditFundingSignalModal pattern. Footer buttons
are rack-styled. Replaces a console.error with import.meta.env.DEV
guard. Drops the discarded 'confirmed' from form data via void.

CreateProjectModal / ConfirmM1PayoutModal / ConfirmPaymentModal / TestPaymentModal:
chrome-only polish — DialogTitle to font-display uppercase, footer
Cancel/primary Buttons to rack outline + display-fill, payment-action
buttons in TestPaymentModal get matching rack styling with led / destructive
fills for the multi-step approve/cancel flow. The form bodies (heavy
admin workflows with recipient editors, multisig state, etc.) are left
untouched in this pass.
ProgramsTable: full restyle. Card/Header/Title/Badge/Button dropped.
Outer shell is a panel; header label-hw + rack-styled Create program
button. Status badges become bordered mono pills (display fill = open,
panel-deep = draft, hairline = closed/completed). Table head row uses
label-hw-dim captions, rows hover panel-deep, dates formatted in mono
caps with → separator, Edit action is a small rack outline button.

M2ProjectsTable: same treatment. Status pill extracted into a helper
returning a bordered mono span with the appropriate lucide icon at
h-2.5; completed gets led fill. Team-address chips use bordered
panel-deep with hairline-subtle border. Payment cells show check-led
when paid, View TX as a label-hw-dim link. Action icons (Eye, DollarSign)
become 28px outlined squares. Empty state is a panel with label-hw-dim
caption.

WinnersTable: chrome-only polish — filter row uses rack-styled
all/main-track/bounty buttons (display fill for active, hairline for
inactive), Mark All as Paid becomes a rack outline. Outer Card → panel
with overflow hidden; TableHead row uses label-hw-dim caps. The
getM2StatusDisplay helper now returns bordered mono pills matching the
M2 table's pattern (led-fill for completed, panel-deep for under_review/
active, hairline for the catch-all). The deep manage-project dialog and
the per-row action buttons are left for a focused follow-up — the file
is 976 lines and a full restyle would dwarf this commit.
@sacha-l sacha-l marked this pull request as ready for review May 20, 2026 15:29
@sacha-l sacha-l merged commit d3aed24 into develop May 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant