diff --git a/frontend/index.html b/frontend/index.html index 109d8e2..f1680ea 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,7 +5,7 @@ - + QuantaPool | Native QRL Pooled Staking on QRL 2.0 + + + \ No newline at end of file diff --git a/frontend/public/quantapool.svg b/frontend/public/quantapool.svg index eb30ec0..470332c 100644 --- a/frontend/public/quantapool.svg +++ b/frontend/public/quantapool.svg @@ -1,5 +1,5 @@ - - + + diff --git a/frontend/public/social-card.svg b/frontend/public/social-card.svg index ad30198..7a6cd31 100644 --- a/frontend/public/social-card.svg +++ b/frontend/public/social-card.svg @@ -1,15 +1,15 @@ - + - - + + QuantaPool Native QRL pooled staking. On-chain positions. Native QRL claims. - quantapool.com - + quantapool.com + diff --git a/frontend/src/components/ActivityCard.tsx b/frontend/src/components/ActivityCard.tsx index dfbe83c..7b8bb3d 100644 --- a/frontend/src/components/ActivityCard.tsx +++ b/frontend/src/components/ActivityCard.tsx @@ -114,13 +114,13 @@ export const ActivityCard = observer(() => { recovery cash.

)} -

+

Block {item.blockNumber.toString()}

{item.qrlAmount !== null && ( -

+

{formatAmount(item.qrlAmount)} {NATIVE_UNIT}

)} diff --git a/frontend/src/components/AmountInput.tsx b/frontend/src/components/AmountInput.tsx index aa5b4ec..11ade58 100644 --- a/frontend/src/components/AmountInput.tsx +++ b/frontend/src/components/AmountInput.tsx @@ -40,7 +40,7 @@ export function AmountInput({ const next = e.target.value.replace(",", "."); if (next === "" || /^\d*\.?\d*$/.test(next)) onChange(next); }} - className="font-data h-12 pr-16 text-lg" + className="font-numeric h-12 pr-16 text-lg" /> {symbol} diff --git a/frontend/src/components/StatsBar.tsx b/frontend/src/components/StatsBar.tsx index 9915d32..a397a3c 100644 --- a/frontend/src/components/StatsBar.tsx +++ b/frontend/src/components/StatsBar.tsx @@ -18,7 +18,7 @@ export const StatsBar = observer(() => { {stats.map(([label, value]) => (
{label}
-
+
{value === undefined ? "Unavailable" : `${formatAmount(value)} QRL`}
diff --git a/frontend/src/components/UI/Button.tsx b/frontend/src/components/UI/Button.tsx index bab75bf..7453ae4 100644 --- a/frontend/src/components/UI/Button.tsx +++ b/frontend/src/components/UI/Button.tsx @@ -10,7 +10,7 @@ const buttonVariants = cva( variants: { variant: { default: - "bg-primary text-primary-foreground shadow-[0_10px_24px_-12px_hsl(24_96%_45%/0.55),inset_0_1px_0_hsl(36_100%_80%/0.35)] hover:bg-primary/90", + "bg-primary text-primary-foreground shadow-[0_10px_24px_-12px_hsl(199_78%_45%/0.55),inset_0_1px_0_hsl(196_70%_86%/0.35)] hover:bg-primary/90", secondary: "bg-foreground/[0.06] text-foreground border border-foreground/10 hover:bg-foreground/10", destructive: diff --git a/frontend/src/components/WalletPickerModal.tsx b/frontend/src/components/WalletPickerModal.tsx index e3e1faf..359390f 100644 --- a/frontend/src/components/WalletPickerModal.tsx +++ b/frontend/src/components/WalletPickerModal.tsx @@ -49,12 +49,20 @@ export const WalletPickerModal = observer(() => { className="cursor-pointer flex w-full items-center gap-3 rounded-md border border-border bg-muted/30 px-3 py-3 text-left transition-colors hover:border-primary/40 hover:bg-primary/10" > {w.icon ? ( - + ) : ( - + )} - {w.name} - {w.rdns} + + {w.name} + + {w.rdns} + + )) )} diff --git a/frontend/src/index.css b/frontend/src/index.css index 5f1b0d6..41e2a10 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,17 +1,21 @@ -/* Self-hosted variable fonts (Sora display / Instrument Sans body / - JetBrains Mono data) are imported in main.tsx: importing them here would - let the Tailwind postcss pipeline inline the @font-face rules without +/* Self-hosted variable fonts (Sora display / Instrument Sans body / Inter + numeric / JetBrains Mono data) are imported in main.tsx: importing them here + would let the Tailwind postcss pipeline inline the @font-face rules without rewriting the package-relative woff2 URLs. */ @import "tailwindcss"; -/* Theme customization for Tailwind v4 - "Obsidian & Ember" token values - mirror myqrlwallet-frontend so QuantaPool reads as part of the same - product family. */ +/* Theme customization for Tailwind v4 - "QRL Blue" token values mirror + myqrlwallet-frontend so QuantaPool reads as part of the same product + family. */ @theme { /* Typography */ --font-sans: "Instrument Sans Variable", ui-sans-serif, system-ui, sans-serif; --font-display: "Sora Variable", ui-sans-serif, system-ui, sans-serif; --font-mono: "JetBrains Mono Variable", ui-monospace, "SF Mono", monospace; + /* Numeric voice: balances, amounts, fees, counts. Inter matches the + extension surface and the wider wallet ecosystem. */ + --font-numeric: "Inter Variable", "Instrument Sans Variable", ui-sans-serif, + system-ui, sans-serif; /* Border radius */ --radius-lg: var(--radius); @@ -55,50 +59,58 @@ /* CSS Custom Properties for theming. - "Obsidian & Ember": one deep warm-ink surface family, one ember-orange - action color (the QRL brand), champagne reserved for identity and informational + "QRL Blue": one deep navy surface family, QRL's sky blue as the single + action color, a pale ice blue reserved for identity and informational states, and layered glow + grain atmosphere behind everything. Values are the canonical set from myqrlwallet-frontend. */ @layer base { :root { - --background: 235 15% 4%; - --foreground: 36 20% 95%; + --background: 222 45% 6%; + --foreground: 210 30% 96%; - --card: 235 13% 7%; - --card-foreground: 36 20% 95%; + --card: 222 38% 9%; + --card-foreground: 210 30% 96%; - --popover: 235 14% 6%; - --popover-foreground: 36 20% 95%; + --popover: 222 40% 7%; + --popover-foreground: 210 30% 96%; - /* Ember: the single action color */ - --primary: 24 96% 55%; - --primary-foreground: 24 90% 6%; + /* QRL sky blue: the single action color */ + --primary: 199 78% 55%; + --primary-foreground: 205 80% 8%; - /* QRL Orange kept as the brand accent token (rails, edges, badges) */ - --secondary: 25 95% 53%; - --secondary-foreground: 24 90% 6%; + /* Brand accent token (rails, edges, badges), a sibling of primary */ + --secondary: 200 82% 52%; + --secondary-foreground: 205 80% 8%; - /* Champagne matches the wallet identity and information palette. */ - --identity-accent: 38 45% 76%; - --identity-accent-foreground: 38 60% 8%; + /* Ice blue: the identity color (addresses, account markers) and + informational states. Sky blue acts, ice blue identifies. */ + --identity-accent: 196 60% 78%; + --identity-accent-foreground: 205 60% 8%; --success: 152 55% 48%; --success-foreground: 152 80% 8%; - --muted: 235 10% 12%; - --muted-foreground: 234 8% 64%; + --muted: 222 30% 13%; + --muted-foreground: 215 15% 66%; - --accent: 235 11% 13%; - --accent-foreground: 36 20% 95%; + --accent: 222 30% 14%; + --accent-foreground: 210 30% 96%; - --destructive: 0 68% 46%; - --destructive-foreground: 0 0% 98%; + /* Lifted off the palette base (0 70% 55%) so 12px destructive text and + destructive text on a /15 tint both clear WCAG AA. The paired + foreground is a deep maroon, matching how primary pairs a dark + foreground with a bright accent. */ + --destructive: 0 72% 64%; + --destructive-foreground: 0 60% 10%; - --border: 235 10% 15%; - --input: 235 10% 17%; - --ring: 24 96% 55%; + --border: 220 30% 17%; + --input: 220 30% 20%; + --ring: 199 78% 55%; --radius: 0.75rem; + + /* Top edge of the hero-card gradient. */ + --hero-top: 205 55% 16%; } /* Customized scrollbar */ @@ -144,9 +156,9 @@ background-color: hsl(var(--background)); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E"), - radial-gradient(52rem 34rem at 12% -8%, hsl(24 96% 55% / 0.09), transparent 62%), - radial-gradient(44rem 30rem at 108% 112%, hsl(38 45% 76% / 0.04), transparent 60%), - radial-gradient(60rem 44rem at 50% 120%, hsl(236 40% 12% / 0.5), transparent 70%); + radial-gradient(52rem 34rem at 12% -8%, hsl(199 78% 55% / 0.09), transparent 62%), + radial-gradient(44rem 30rem at 108% 112%, hsl(196 60% 78% / 0.04), transparent 60%), + radial-gradient(60rem 44rem at 50% 120%, hsl(222 45% 12% / 0.5), transparent 70%); background-attachment: fixed; font-family: var(--font-sans); font-feature-settings: "ss01" on; @@ -214,13 +226,26 @@ outline-offset: 4px; } - /* Data voice: addresses, hashes, balances. */ + /* Data voice: addresses, hashes. Anything the user compares character by + character stays monospace. */ .font-data { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; } + /* Numeric voice: every balance, amount, fee, exchange rate and count. + Inter with fixed-width digits so a changing balance does not jitter. + font-feature-settings is set explicitly because body turns on "ss01", + which in Inter swaps in alternate digit shapes; "tnum" here replaces + that list and keeps the digits plain and tabular. */ + .font-numeric { + font-family: var(--font-numeric); + font-variant-numeric: tabular-nums; + font-feature-settings: "tnum" 1; + letter-spacing: normal; + } + /* Glass surface: the one card treatment used everywhere so pages stop feeling stitched together. Solid-ish ink with a soft top sheen. Deliberately NO backdrop-filter: it would give every card its own @@ -234,17 +259,19 @@ border: 1px solid hsl(var(--foreground) / 0.08); box-shadow: 0 1px 0 hsl(var(--foreground) / 0.05) inset, - 0 18px 40px -24px hsl(235 30% 2% / 0.9); + 0 18px 40px -24px hsl(222 50% 2% / 0.9); } - /* Ember edge treatment for "hero" cards (the stake form). */ + /* Lifted edge treatment for "hero" cards (the stake form). Utility name + kept from the previous theme so in-flight branches keep applying + cleanly; the values are now QRL Blue. */ .surface-ember { background: - linear-gradient(180deg, hsl(var(--primary) / 0.07), transparent 46%), hsl(var(--card) / 0.86); + linear-gradient(180deg, hsl(var(--hero-top) / 0.85), transparent 46%), hsl(var(--card) / 0.86); border: 1px solid hsl(var(--primary) / 0.22); box-shadow: 0 1px 0 hsl(var(--primary) / 0.14) inset, - 0 18px 44px -22px hsl(24 96% 40% / 0.28); + 0 18px 44px -22px hsl(199 78% 40% / 0.28); } } diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index c03b77c..2905532 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,10 +1,12 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; // Self-hosted variable fonts (CSP-safe, bundled by Vite): Sora = display, -// Instrument Sans = body, JetBrains Mono = data (addresses/amounts). -// Imported here, not in index.css, so Vite rewrites the woff2 asset URLs. +// Instrument Sans = body, Inter = numeric (balances/amounts/fees), +// JetBrains Mono = data (addresses/hashes). Imported here, not in index.css, +// so Vite rewrites the woff2 asset URLs. import "@fontsource-variable/sora/index.css"; import "@fontsource-variable/instrument-sans/index.css"; +import "@fontsource-variable/inter/index.css"; import "@fontsource-variable/jetbrains-mono/index.css"; import "./index.css"; import App from "./App"; diff --git a/frontend/src/pages/StakePage.tsx b/frontend/src/pages/StakePage.tsx index b5e308f..4fe1758 100644 --- a/frontend/src/pages/StakePage.tsx +++ b/frontend/src/pages/StakePage.tsx @@ -93,7 +93,7 @@ export const StakePage = observer(() => {

Wallet balance:{" "} - + {account ? `${formatAmount(account.qrlBalance)} QRL` : "Connect your wallet"} @@ -185,7 +185,7 @@ export const StakePage = observer(() => { className="flex flex-wrap justify-between gap-x-3 gap-y-1 text-sm" >

{label}
-
+
{formatAmount(value)} QRL
diff --git a/frontend/src/pages/StatsPage.tsx b/frontend/src/pages/StatsPage.tsx index f083cea..b2e4fe3 100644 --- a/frontend/src/pages/StatsPage.tsx +++ b/frontend/src/pages/StatsPage.tsx @@ -48,7 +48,7 @@ export const StatsPage = observer(() => { className="flex flex-wrap justify-between gap-2 text-sm" >
{label}
-
+
{value === undefined ? "Unavailable" : `${formatAmount(value)} QRL`} @@ -65,7 +65,7 @@ export const StatsPage = observer(() => {

Last applied execution block:{" "} - + {pool?.lastCheckpointBlock.toString() ?? "Unavailable"}

@@ -85,7 +85,7 @@ export const StatsPage = observer(() => {

Accounting recovery deadline: slot{" "} - + {pool?.poolRecoveryDeadlineSlot.toString() ?? "Unavailable"} . Only a completed and applied pool checkpoint can extend this diff --git a/frontend/src/pages/WithdrawalsPage.tsx b/frontend/src/pages/WithdrawalsPage.tsx index 2ad6392..5e739a4 100644 --- a/frontend/src/pages/WithdrawalsPage.tsx +++ b/frontend/src/pages/WithdrawalsPage.tsx @@ -104,7 +104,7 @@ export const WithdrawalsPage = observer(() => { {pool?.recovering ? "Frozen checkpoint reference" : "Last checkpoint value"} - : {formatAmount(available)} QRL + : {formatAmount(available)} QRL

{ -

+

{formatAmount(account.claimable)} QRL