From e7daa57ab4f9681dc37aa26db840e39260022edf Mon Sep 17 00:00:00 2001 From: SatsFaucet Date: Tue, 9 Jun 2026 05:23:29 +0200 Subject: [PATCH] Redesign frontend with Sats Flow theme and restore homepage sidebars. Apply the glassmorphic Bitcoin-orange design system across the claim flow and all pages, add the eligibility draw animation, and flank the claim wizard with deposit and stats panels again. --- .gitignore | 4 + frontend/index.html | 14 +- frontend/src/App.tsx | 70 +- frontend/src/components/ClaimWizard.tsx | 54 +- frontend/src/components/ConfirmStep.tsx | 3 +- frontend/src/components/ConnectStep.tsx | 35 +- frontend/src/components/DrawAnimation.tsx | 66 + frontend/src/components/EligibilityStep.tsx | 4 + frontend/src/components/StepIndicator.tsx | 6 +- frontend/src/styles/global.css | 1414 ++++++++++++++++++- 10 files changed, 1567 insertions(+), 103 deletions(-) create mode 100644 frontend/src/components/DrawAnimation.tsx diff --git a/.gitignore b/.gitignore index 2cbc341..06b81cc 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ npm-debug.log* Thumbs.db # IDE / editor +.cursor/ .idea/ .vscode/ *.swp @@ -39,6 +40,9 @@ frontend/dist/ # Deploy config (server-specific) deploy/ +# Design assets (local reference only) +design/ + # Misc *.local .cache/ diff --git a/frontend/index.html b/frontend/index.html index 178d814..15082f4 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -6,9 +6,21 @@ Sats Faucet — Free Bitcoin for Nostr Users - + + + + + + + diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2f26996..115591b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -11,22 +11,6 @@ import { SponsorsPage } from "./pages/SponsorsPage"; import { MyAdsPage } from "./pages/MyAdsPage"; import { SponsorsSection } from "./components/SponsorsSection"; -const FaucetSvg = () => ( - - - - - - - - - - - - - -); - export default function App() { const [pubkey, setPubkey] = useState(null); const [loginMethod, setLoginMethod] = useState(null); @@ -75,7 +59,7 @@ export default function App() { return ( -
+
@@ -84,23 +68,27 @@ export default function App() { path="/" element={ <> -
- -
-
- -

Sats Faucet

-
- -
- -
+
+
+
+ +
+ +
+ +
+
} @@ -108,17 +96,15 @@ export default function App() { -
- -
+
+
} /> +
} @@ -126,10 +112,8 @@ export default function App() { -
- -
+
+
} /> diff --git a/frontend/src/components/ClaimWizard.tsx b/frontend/src/components/ClaimWizard.tsx index 52d54e6..f4d9ceb 100644 --- a/frontend/src/components/ClaimWizard.tsx +++ b/frontend/src/components/ClaimWizard.tsx @@ -8,8 +8,8 @@ import { EligibilityStep } from "./EligibilityStep"; import { ConfirmStep } from "./ConfirmStep"; import { SuccessStep } from "./SuccessStep"; import { ClaimDenialPanel } from "./ClaimDenialPanel"; +import { DrawAnimation } from "./DrawAnimation"; import { Modal } from "./Modal"; -import { ELIGIBILITY_PROGRESS_STEPS } from "../hooks/useClaimFlow"; const LIGHTNING_ADDRESS_REGEX = /^[^@]+@[^@]+$/; @@ -148,6 +148,14 @@ export function ClaimWizard({ pubkey, loginMethod, onPubkeyChange, onClaimSucces const quoteExpired = claim.quote != null && claim.quote.expires_at <= Math.floor(Date.now() / 1000); + const currentStep: 1 | 2 | 3 | 4 = !isConnected + ? 1 + : claim.loading === "quote" + ? 3 + : (claim.quote && !quoteExpired) || claim.loading === "confirm" || claim.success + ? 4 + : 2; + const modalTitle = useMemo(() => { if (claim.success) return "Sats sent!"; if (claim.confirmError) return "Something went wrong"; @@ -175,7 +183,7 @@ export function ClaimWizard({ pubkey, loginMethod, onPubkeyChange, onClaimSucces )}
- +
@@ -187,12 +195,7 @@ export function ClaimWizard({ pubkey, loginMethod, onPubkeyChange, onClaimSucces onDisconnect={handleDisconnect} /> ) : claim.loading === "quote" ? ( -
-
-

- {ELIGIBILITY_PROGRESS_STEPS[claim.eligibilityProgressStep ?? 0]} -

-
+ ) : claim.denial ? ( ) : claim.quote && !quoteExpired ? ( -
-

You're eligible!

-
- {claim.quote.payout_sats} - sats +
+

You Won

+
+ {claim.quote.payout_sats} + Sats
-

- To {lightningAddress} +

+
+ Destination +
+ bolt + {lightningAddress} +
+
+ +

+ Transaction will be sent instantly via the Lightning Network.

-
- -
) : (
)} diff --git a/frontend/src/components/StepIndicator.tsx b/frontend/src/components/StepIndicator.tsx index 582a216..5fd25ef 100644 --- a/frontend/src/components/StepIndicator.tsx +++ b/frontend/src/components/StepIndicator.tsx @@ -1,8 +1,8 @@ const STEPS = [ { step: 1, label: "Connect" }, - { step: 2, label: "Check" }, - { step: 3, label: "Confirm" }, - { step: 4, label: "Receive" }, + { step: 2, label: "Verify" }, + { step: 3, label: "Draw" }, + { step: 4, label: "Claim" }, ] as const; interface StepIndicatorProps { diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index f6cb818..3b823e3 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -1,24 +1,52 @@ * { margin: 0; padding: 0; box-sizing: border-box; } :root { - --bg: #0c1222; - --bg-card: #151d2e; - --bg-card-hover: #1a2438; - --text: #f1f5f9; - --text-muted: #94a3b8; - --text-soft: #64748b; - --accent: #f97316; - --accent-hover: #ea580c; - --accent-soft: #22c55e; - --accent-soft-hover: #16a34a; - --border: #334155; - --error: #f87171; - --error-bg: rgba(248, 113, 113, 0.1); - --success: #4ade80; - --shadow: 0 8px 24px rgba(0, 0, 0, 0.25); + /* ===== Sats Flow design tokens ===== */ + --sf-bg: #0a0a0b; + --sf-surface: #161618; + --sf-surface-hover: #1e1e20; + --sf-surface-border: #272727; + --sf-popover: #1c1c1e; + --sf-popover-border: #3a3a3c; + --sf-recessed: #0a0a0b; + --sf-primary: #f7931a; + --sf-primary-light: #ffab4a; + --sf-primary-hover: #e08618; + --sf-primary-glow: rgba(247, 147, 26, 0.2); + --sf-on-primary: #000000; + --sf-success: #00ffa3; + --sf-success-soft: #00e390; + --sf-success-hover: #00c47c; + --sf-text: #f1dfd2; + --sf-text-variant: #dbc2ae; + --sf-outline: #a38d7b; + --sf-outline-variant: #554335; + --sf-error: #ffb4ab; + --sf-radius-sm: 0.5rem; + --sf-radius-lg: 1rem; + --sf-radius-xl: 1.5rem; + --sf-font-display: "Hanken Grotesk", system-ui, sans-serif; + --sf-font-body: "Inter", system-ui, sans-serif; + --sf-font-mono: "JetBrains Mono", ui-monospace, monospace; + + /* Legacy tokens (mapped to Sats Flow) */ + --bg: var(--sf-bg); + --bg-card: var(--sf-surface); + --bg-card-hover: var(--sf-surface-hover); + --text: var(--sf-text); + --text-muted: var(--sf-text-variant); + --text-soft: var(--sf-outline); + --accent: var(--sf-primary); + --accent-hover: var(--sf-primary-hover); + --accent-soft: var(--sf-success-soft); + --accent-soft-hover: var(--sf-success-hover); + --border: var(--sf-surface-border); + --error: var(--sf-error); + --error-bg: rgba(255, 180, 171, 0.1); + --success: var(--sf-success); + --shadow: 0 8px 24px rgba(0, 0, 0, 0.4); --radius: 16px; --radius-card: 12px; - /* 8px spacing scale */ --space-xs: 8px; --space-sm: 16px; --space-md: 24px; @@ -28,9 +56,9 @@ } body { - font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; - background: var(--bg); - color: var(--text); + font-family: var(--sf-font-body); + background: var(--sf-bg); + color: var(--sf-text); line-height: 1.6; overflow-x: hidden; -webkit-tap-highlight-color: transparent; @@ -3383,3 +3411,1351 @@ h1 { .sponsor-edit-form { margin-top: 4px; } + +/* ============================================================ + SATS FLOW — App-wide design system + ============================================================ */ + +.material-symbols-outlined { + font-family: "Material Symbols Outlined"; + font-weight: normal; + font-style: normal; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: "liga"; + -webkit-font-smoothing: antialiased; + font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24; +} + +/* ---- Page scope ---- */ +.sats-flow { + position: relative; + background: var(--sf-bg); + color: var(--sf-text); + font-family: var(--sf-font-body); +} + +.claim-flow-page { + position: relative; + min-height: calc(100vh - 56px); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 56px 20px 72px; + overflow: hidden; +} +.claim-flow-page--grid { + justify-content: flex-start; + align-items: stretch; + padding: 48px 20px 64px; +} +@media (min-width: 768px) { + .claim-flow-page { + padding: 72px 40px 88px; + } + .claim-flow-page--grid { + padding: 60px 40px 72px; + } +} + +/* Homepage 3-column grid */ +.claim-flow-grid { + position: relative; + z-index: 1; + width: 100%; + max-width: 1400px; + margin: 0 auto; + display: flex; + flex-direction: column; + gap: 32px; +} +.claim-flow-main { + order: 1; + min-width: 0; + display: flex; + justify-content: center; +} +.claim-flow-grid .sidebar-left { + order: 2; + width: 100%; +} +.claim-flow-grid .sidebar-right { + order: 3; + width: 100%; +} +@media (min-width: 1280px) { + .claim-flow-grid { + display: grid; + grid-template-columns: 320px 1fr 360px; + column-gap: 48px; + align-items: start; + gap: 0; + } + .claim-flow-grid .sidebar-left, + .claim-flow-grid .sidebar-right { + order: unset; + width: auto; + } + .claim-flow-main { + order: unset; + } +} + +/* Ambient orange glow behind the card */ +.sf-ambient-glow { + position: absolute; + top: 50%; + left: 50%; + width: min(800px, 120vw); + height: min(800px, 120vw); + transform: translate(-50%, -50%); + background: radial-gradient(circle, var(--sf-primary) 0%, transparent 60%); + opacity: 0.12; + filter: blur(120px); + pointer-events: none; + z-index: 0; +} +@media (prefers-reduced-motion: no-preference) { + .sf-ambient-glow { + animation: sf-glow-breathe 8s ease-in-out infinite; + } +} +@keyframes sf-glow-breathe { + 0%, 100% { opacity: 0.1; } + 50% { opacity: 0.18; } +} + +/* ---- Glass utilities ---- */ +.sf-glass-card { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-xl); + box-shadow: 0 0 40px rgba(247, 147, 26, 0.1); +} +.sf-glass-popover { + background: rgba(28, 28, 30, 0.85); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border: 1px solid var(--sf-popover-border); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5); +} +.sf-mono-label { + font-family: var(--sf-font-mono); + font-size: 11px; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--sf-outline); +} + +/* ---- Claim wizard container ---- */ +.sats-flow .claim-wizard-content { + position: relative; + z-index: 1; + width: 100%; + display: flex; + justify-content: center; +} +.sats-flow .claim-wizard-root { + max-width: 520px; + width: 100%; + margin: 0 auto; + padding: 0; + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-xl); + box-shadow: 0 0 50px rgba(247, 147, 26, 0.1), 0 24px 60px rgba(0, 0, 0, 0.5); + overflow: hidden; + min-height: 0; +} +.sats-flow .claim-wizard-header { + padding: 28px 32px 20px; + border-bottom: 1px solid var(--sf-surface-border); + margin-bottom: 0; + background: linear-gradient(to bottom, rgba(247, 147, 26, 0.04), transparent); +} +.sats-flow .claim-wizard-header-row { + margin-bottom: 22px; +} +.sats-flow .claim-wizard-title { + font-family: var(--sf-font-display); + font-size: 1.4rem; + font-weight: 700; + letter-spacing: -0.01em; + color: var(--sf-text); +} +.sats-flow .claim-wizard-disconnect { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--sf-outline); + text-decoration: none; + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + padding: 6px 12px; + transition: border-color 0.2s, color 0.2s; +} +.sats-flow .claim-wizard-disconnect:hover { + color: var(--sf-primary); + border-color: var(--sf-primary); +} +.sats-flow .claim-wizard-body { + padding: 32px; + min-height: 0; +} + +/* ---- Step indicator ---- */ +.sats-flow .step-indicator-marker { + background: var(--sf-surface-border); + color: var(--sf-outline); + font-family: var(--sf-font-mono); +} +.sats-flow .step-indicator-connector { + background: var(--sf-surface-border); +} +.sats-flow .step-indicator-item--current .step-indicator-marker { + background: var(--sf-primary); + color: var(--sf-on-primary); + box-shadow: 0 0 16px var(--sf-primary-glow); +} +.sats-flow .step-indicator-item--completed .step-indicator-marker { + background: var(--sf-success-soft); + color: #00210f; +} +.sats-flow .step-indicator-label { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--sf-outline); +} +.sats-flow .step-indicator-item--current .step-indicator-label { + color: var(--sf-text); +} + +/* ---- Step titles / descriptions ---- */ +.sats-flow .claim-wizard-step-title { + font-family: var(--sf-font-display); + font-size: 1.35rem; + font-weight: 600; + letter-spacing: -0.01em; + color: var(--sf-text); +} +.sats-flow .claim-wizard-step-desc { + font-size: 15px; + color: var(--sf-text-variant); +} +.sats-flow .claim-wizard-input-hint { + color: var(--sf-text-variant); +} + +/* ---- Primary / secondary buttons (Sats Flow) ---- */ +.sats-flow .btn-primary, +.sats-flow .claim-wizard-connect-cta .address-row button { + background: var(--sf-primary); + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border: none; + border-radius: var(--sf-radius-sm); + font-family: var(--sf-font-body); + font-weight: 600; + letter-spacing: 0.01em; + box-shadow: 0 0 0 rgba(247, 147, 26, 0); + transition: filter 0.2s, box-shadow 0.25s, transform 0.1s; +} +.sats-flow .btn-primary:hover:not(:disabled), +.sats-flow .claim-wizard-connect-cta .address-row button:hover:not(:disabled) { + filter: brightness(1.08); + box-shadow: 0 0 24px var(--sf-primary-glow); +} +.sats-flow .btn-primary:active:not(:disabled), +.sats-flow .claim-wizard-connect-cta .address-row button:active:not(:disabled) { + transform: scale(0.98); +} +.sats-flow .btn-primary:disabled { + opacity: 0.45; +} +.sats-flow .btn-secondary { + background: transparent; + color: var(--sf-text); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + font-family: var(--sf-font-body); + font-weight: 600; + transition: border-color 0.2s, color 0.2s; +} +.sats-flow .btn-secondary:hover:not(:disabled) { + border-color: var(--sf-primary); + color: var(--sf-primary); +} + +/* ---- Screen 1: Connect / Login ---- */ +.sf-connect { + text-align: center; +} +.sf-connect-hero { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 28px; +} +.sf-connect-badge { + width: 88px; + height: 88px; + border-radius: 50%; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 24px; + box-shadow: 0 0 40px var(--sf-primary-glow); + position: relative; + overflow: hidden; +} +.sf-connect-badge::before { + content: ""; + position: absolute; + inset: 0; + background: radial-gradient(circle at 50% 30%, rgba(247, 147, 26, 0.18), transparent 70%); +} +.sf-connect-badge .material-symbols-outlined { + font-size: 44px; + color: var(--sf-primary); + position: relative; + z-index: 1; + font-variation-settings: "FILL" 1, "wght" 500; +} +.sf-connect-title { + font-family: var(--sf-font-display); + font-size: 2rem; + font-weight: 700; + letter-spacing: -0.02em; + color: var(--sf-text); + margin-bottom: 12px; +} +.sf-connect-subtitle { + font-size: 15px; + line-height: 1.6; + color: var(--sf-text-variant); + max-width: 340px; + margin: 0 auto; +} +.sf-connect-card { + background: var(--sf-popover); + border: 1px solid var(--sf-popover-border); + border-radius: var(--sf-radius-lg); + padding: 24px; + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.35); +} +.sats-flow .claim-wizard-connect-cta { + margin: 0; +} +.sats-flow .claim-wizard-connect-cta .address-row { + margin: 0; +} +.sf-connect-secure { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + margin-top: 20px; + color: var(--sf-outline); +} +.sf-connect-secure .material-symbols-outlined { + font-size: 15px; + font-variation-settings: "FILL" 1; +} +.sf-connect-secure span:last-child { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; +} + +/* ---- Faucet rules box ---- */ +.sats-flow .claim-wizard-rules { + margin-top: 24px; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-lg); + padding: 18px 20px; + text-align: left; +} +.sats-flow .claim-wizard-rules-title { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--sf-outline); + margin-bottom: 12px; +} +.sats-flow .claim-wizard-rules-list { + display: flex; + flex-direction: column; + gap: 8px; +} +.sats-flow .claim-wizard-rules-list li { + font-size: 14px; + color: var(--sf-text-variant); +} +.sats-flow .claim-wizard-rules-list strong { + color: var(--sf-text); +} + +/* ---- Connect pill (connected state) ---- */ +.sats-flow .connect-pill { + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); +} +.sats-flow .connect-pill-dot { + background: var(--sf-success); + box-shadow: 0 0 8px var(--sf-success); +} +.sats-flow .connect-pill-avatar { + background: var(--sf-surface-border); + color: var(--sf-text); +} +.sats-flow .connect-pill-name { + color: var(--sf-text); +} +.sats-flow .connect-pill-npub { + font-family: var(--sf-font-mono); + color: var(--sf-outline); +} +.sats-flow .connect-pill-disconnect { + background: var(--sf-recessed); + border-color: var(--sf-outline-variant); + color: var(--sf-outline); +} +.sats-flow .connect-pill-disconnect:hover { + border-color: var(--sf-primary); + color: var(--sf-primary); +} + +/* ---- Screen 2: Address verification ---- */ +.sf-eligibility-icon { + display: flex; + justify-content: center; + margin-bottom: 20px; +} +.sf-eligibility-icon .material-symbols-outlined { + font-size: 40px; + color: var(--sf-primary); + font-variation-settings: "FILL" 1; +} +.sats-flow .claim-wizard-step-eligibility { + text-align: center; +} +.sats-flow .claim-wizard-address-row { + text-align: left; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-lg); + padding: 18px 20px; + gap: 8px; +} +.sats-flow .claim-wizard-address-row label { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--sf-outline); +} +.sats-flow .claim-wizard-address-row input { + background: #050506; + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + color: var(--sf-text); + font-family: var(--sf-font-body); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4); +} +.sats-flow .claim-wizard-address-row input:focus { + outline: none; + border-color: var(--sf-primary); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4), 0 0 0 1px var(--sf-primary); +} +.sats-flow .claim-wizard-address-row input::placeholder { + color: rgba(163, 141, 123, 0.5); +} + +/* Profile card (Lightning address from profile) */ +.sats-flow .claim-wizard-profile-card { + display: flex; + align-items: center; + gap: 14px; + text-align: left; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-lg); + padding: 16px 18px; +} +.sats-flow .claim-wizard-profile-card-icon { + width: 38px; + height: 38px; + border-radius: 50%; + background: rgba(247, 147, 26, 0.12); + color: var(--sf-primary); + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + flex-shrink: 0; +} +.sats-flow .claim-wizard-profile-card-body { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; + flex: 1; +} +.sats-flow .claim-wizard-profile-card-label { + font-family: var(--sf-font-mono); + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--sf-outline); +} +.sats-flow .claim-wizard-profile-card-address { + font-family: var(--sf-font-mono); + font-size: 14px; + color: var(--sf-text); + word-break: break-all; +} +.sats-flow .claim-wizard-step-eligibility .btn-primary { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; +} +.sats-flow .claim-wizard-step-eligibility .btn-primary .material-symbols-outlined { + font-size: 18px; +} + +/* ---- Screen 3: Draw animation ---- */ +.sf-draw { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} +.sf-draw-icon { + width: 64px; + height: 64px; + border-radius: 50%; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 22px; +} +.sf-draw-icon .material-symbols-outlined { + font-size: 30px; + color: var(--sf-primary); +} +.sf-draw-title { + font-family: var(--sf-font-display); + font-size: 1.6rem; + font-weight: 700; + color: var(--sf-text); + text-shadow: 0 0 20px rgba(247, 147, 26, 0.3); + margin-bottom: 10px; +} +.sf-draw-desc { + font-size: 14px; + color: var(--sf-text-variant); + max-width: 320px; + margin: 0 auto 28px; +} +.sf-draw-ticker { + width: 100%; + height: 150px; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-lg); + overflow: hidden; + position: relative; + display: flex; + align-items: center; + justify-content: center; + gap: 28px; + margin-bottom: 28px; +} +.sf-draw-ticker::before { + content: ""; + position: absolute; + inset: 0; + background: linear-gradient(to bottom, var(--sf-recessed), transparent 35%, transparent 65%, var(--sf-recessed)); + z-index: 2; + pointer-events: none; +} +.sf-draw-col-window { + height: 150px; + overflow: hidden; + display: flex; + align-items: center; +} +.sf-draw-column { + display: flex; + flex-direction: column; + align-items: center; + font-family: var(--sf-font-display); + font-size: 44px; + font-weight: 700; + filter: blur(1px); +} +@media (prefers-reduced-motion: no-preference) { + .sf-draw-column { + animation: sf-draw-roll 0.7s linear infinite; + } + .sf-draw-col-window:nth-child(2) .sf-draw-column { animation-duration: 0.5s; } + .sf-draw-col-window:nth-child(3) .sf-draw-column { animation-duration: 0.85s; } +} +@keyframes sf-draw-roll { + from { transform: translateY(0); } + to { transform: translateY(-50%); } +} +.sf-draw-column span { + line-height: 1.2; + color: var(--sf-outline); + opacity: 0.35; +} +.sf-draw-column span:nth-child(3n + 2) { + color: var(--sf-primary); + opacity: 1; +} +.sf-draw-status { + display: inline-flex; + align-items: center; + gap: 10px; + background: var(--sf-surface); + border: 1px solid var(--sf-outline-variant); + border-radius: 999px; + padding: 10px 20px; + margin-bottom: 20px; +} +.sf-draw-status .material-symbols-outlined { + font-size: 18px; + color: var(--sf-primary); +} +@media (prefers-reduced-motion: no-preference) { + .sf-draw-status .material-symbols-outlined { + animation: sf-draw-spin 1.2s linear infinite; + } +} +@keyframes sf-draw-spin { + to { transform: rotate(360deg); } +} +.sf-draw-status-text { + font-family: var(--sf-font-mono); + font-size: 12px; + letter-spacing: 0.06em; + color: var(--sf-text); +} +.sf-draw-progress { + width: 100%; + height: 4px; + border-radius: 999px; + background: var(--sf-surface-border); + overflow: hidden; +} +.sf-draw-progress-fill { + height: 100%; + background: var(--sf-primary); + border-radius: 999px; + box-shadow: 0 0 12px var(--sf-primary-glow); + transition: width 0.3s ease; +} + +/* ---- Screen 4: You Won / Claim Sats ---- */ +.sf-won { + text-align: center; +} +.sf-won-title { + font-family: var(--sf-font-display); + font-size: 1.5rem; + font-weight: 600; + color: var(--sf-text); + margin-bottom: 12px; +} +.sf-won-amount { + display: flex; + align-items: baseline; + justify-content: center; + gap: 8px; + margin-bottom: 24px; +} +.sf-won-amount-value { + font-family: var(--sf-font-display); + font-size: 3.25rem; + font-weight: 700; + letter-spacing: -0.03em; + color: var(--sf-primary); + font-variant-numeric: tabular-nums; + line-height: 1; +} +.sf-won-amount-unit { + font-size: 1.4rem; + color: rgba(241, 223, 210, 0.5); + font-weight: 400; +} +.sf-won-divider { + height: 1px; + background: var(--sf-outline-variant); + opacity: 0.6; + margin: 0 auto 24px; +} +.sf-destination { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + margin-bottom: 32px; +} +.sf-destination-label { + font-family: var(--sf-font-mono); + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.16em; + color: var(--sf-outline); +} +.sf-destination-chip { + display: inline-flex; + align-items: center; + gap: 10px; + max-width: 100%; + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-sm); + padding: 10px 16px; + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4); +} +.sf-destination-chip .material-symbols-outlined { + font-size: 16px; + color: var(--sf-primary); + flex-shrink: 0; +} +.sf-destination-addr { + font-family: var(--sf-font-mono); + font-size: 14px; + color: var(--sf-text); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.sf-claim-btn { + width: 100%; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 10px; + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border: none; + border-radius: var(--sf-radius-lg); + padding: 18px 24px; + font-family: var(--sf-font-body); + font-size: 16px; + font-weight: 600; + cursor: pointer; + box-shadow: 0 0 20px var(--sf-primary-glow); + transition: filter 0.2s, box-shadow 0.25s, transform 0.1s; +} +.sf-claim-btn .material-symbols-outlined { + font-size: 20px; + font-variation-settings: "FILL" 1; +} +.sf-claim-btn:hover:not(:disabled) { + filter: brightness(1.1); + box-shadow: 0 0 32px rgba(247, 147, 26, 0.45); +} +.sf-claim-btn:active:not(:disabled) { + transform: scale(0.98); +} +.sf-claim-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} +.sf-claim-note { + font-size: 13px; + color: rgba(219, 194, 174, 0.7); + margin-top: 20px; +} + +/* ---- Confirm step (modal) ---- */ +.sats-flow .claim-wizard-quote-amount-value, +.modal .claim-wizard-quote-amount-value { + font-family: var(--sf-font-display); + color: var(--sf-primary); +} +.sats-flow .claim-wizard-quote-amount-unit, +.modal .claim-wizard-quote-amount-unit { + color: rgba(241, 223, 210, 0.5); +} +.sats-flow .claim-wizard-quote-destination, +.modal .claim-wizard-quote-destination { + color: var(--sf-text-variant); +} +.sats-flow .claim-wizard-quote-destination strong, +.modal .claim-wizard-quote-destination strong { + font-family: var(--sf-font-mono); + color: var(--sf-text); +} +.claim-wizard-btn-claim { + display: inline-flex; + align-items: center; + gap: 8px; +} +.claim-wizard-btn-claim .material-symbols-outlined { + font-size: 18px; + font-variation-settings: "FILL" 1; +} + +/* ---- Modal popover styling within claim flow ---- */ +.sats-flow .modal { + background: var(--sf-popover); + border: 1px solid var(--sf-popover-border); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5); +} +.sats-flow .modal-title { + font-family: var(--sf-font-display); + color: var(--sf-text); +} +.sats-flow .modal-overlay { + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); +} + +/* ---- Success step ---- */ +.modal .claim-wizard-success-icon { + color: var(--sf-success); +} +.modal .claim-wizard-step-success .claim-wizard-step-title { + font-family: var(--sf-font-display); +} +.modal .claim-wizard-success-amount-value { + font-family: var(--sf-font-display); + color: var(--sf-success); +} +.modal .claim-wizard-payment-hash-code { + font-family: var(--sf-font-mono); + background: var(--sf-recessed); + color: var(--sf-text-variant); +} + +/* ---- Denial panel ---- */ +.sats-flow .claim-denial-panel, +.modal .claim-denial-panel { + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-lg); +} +.sats-flow .claim-denial-panel-title, +.modal .claim-denial-panel-title { + font-family: var(--sf-font-display); + color: var(--sf-text); +} +.sats-flow .claim-denial-panel-message, +.modal .claim-denial-panel-message { + color: var(--sf-text-variant); +} + +.sats-flow .funding-panel, +.sats-flow .stats-box, +.sats-flow .deposit-box { + background: var(--sf-surface); + border-color: var(--sf-surface-border); +} +.sats-flow .funding-panel { + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); + padding: 24px; +} + +/* ---- Header / Footer accents ---- */ +.site-header { + background: var(--sf-surface); + border-bottom-color: var(--sf-surface-border); +} +.site-logo .site-logo-text { + font-family: var(--sf-font-display); + font-weight: 700; + color: var(--sf-primary); +} +.site-logo:hover .site-logo-text { + color: var(--sf-primary-light); +} +.site-nav-link { + font-family: var(--sf-font-mono); + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--sf-outline); +} +.site-nav-link:hover { + color: var(--sf-text); + background: rgba(247, 147, 26, 0.08); +} +.site-nav-link.active { + color: var(--sf-primary); + background: rgba(247, 147, 26, 0.1); +} +.header-login-btn { + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border-radius: var(--sf-radius-sm); + transition: filter 0.2s, box-shadow 0.25s; +} +.header-login-btn:hover { + filter: brightness(1.08); + box-shadow: 0 0 20px var(--sf-primary-glow); +} +.site-footer { + background: var(--sf-bg); + border-top-color: var(--sf-surface-border); +} +.site-footer-copy { + font-family: var(--sf-font-mono); + font-size: 12px; + color: var(--sf-outline); +} + +/* ---- Responsive ---- */ +@media (max-width: 600px) { + .sats-flow .claim-wizard-body { padding: 24px 20px; } + .sats-flow .claim-wizard-header { padding: 22px 20px 18px; } + .sf-won-amount-value { font-size: 2.6rem; } + .sf-connect-title { font-size: 1.7rem; } +} + +/* ============================================================ + SATS FLOW — Secondary pages + shared components + ============================================================ */ + +/* Page shell */ +.sf-page { + position: relative; + max-width: 1200px; + margin: 0 auto; + padding: 48px 20px 72px; + min-height: calc(100vh - 56px); +} +@media (min-width: 768px) { + .sf-page { + padding: 72px 40px 88px; + } +} +.sponsors-route.sf-page { + max-width: 1400px; + padding: 48px 20px 72px; +} +@media (min-width: 768px) { + .sponsors-route.sf-page { + padding: 72px 40px 88px; + } +} + +/* ---- Sidebar panels (homepage grid) ---- */ +.claim-flow-grid .funding-panel { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); + padding: 24px; + box-shadow: 0 0 30px rgba(247, 147, 26, 0.06); +} +.claim-flow-grid .stats-box { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); + padding: 24px; + box-shadow: 0 0 30px rgba(247, 147, 26, 0.06); +} +.sats-flow .deposit-box h3, +.sats-flow .stats-box h3 { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--sf-outline); +} +.sats-flow .deposit-box input { + background: var(--sf-recessed); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + color: var(--sf-text); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4); +} +.sats-flow .deposit-box input:focus { + outline: none; + border-color: var(--sf-primary); +} +.sats-flow .deposit-box button { + background: transparent; + border: 1px solid var(--sf-surface-border); + color: var(--sf-text-variant); + border-radius: var(--sf-radius-sm); +} +.sats-flow .deposit-box button:hover { + border-color: var(--sf-primary); + color: var(--sf-primary); +} +.sats-flow .stats-box .stats-balance { + font-family: var(--sf-font-display); + color: var(--sf-success-soft); +} +.sats-flow .stats-box .stats-progress-fill { + background: linear-gradient(90deg, var(--sf-primary), var(--sf-success-soft)); +} +.sats-flow .stats-box .stats-row { + border-bottom-color: var(--sf-outline-variant); +} +.sats-flow .stats-box .stats-recent-list li { + border-bottom-color: var(--sf-outline-variant); + font-family: var(--sf-font-mono); + font-size: 12px; +} + +/* ---- Transactions page ---- */ +.sf-page .tx-page { + max-width: none; + margin: 0; + padding: 0; +} +.sf-page .tx-page-title { + font-family: var(--sf-font-display); + font-weight: 700; + letter-spacing: -0.02em; + color: var(--sf-text); +} +.sf-page .tx-page-subtitle { + color: var(--sf-text-variant); +} +.sf-page .tx-filter-label { + font-family: var(--sf-font-mono); + color: var(--sf-outline); +} +.sf-page .tx-filter-select { + background: var(--sf-recessed); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + color: var(--sf-text); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3); +} +.sf-page .tx-filter-select:focus { + border-color: var(--sf-primary); + outline: none; +} +.sf-page .tx-card { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-xl); + box-shadow: 0 0 40px rgba(247, 147, 26, 0.08), 0 16px 40px rgba(0, 0, 0, 0.35); +} +.sf-page .tx-table-header { + font-family: var(--sf-font-mono); + color: var(--sf-outline); +} +.sf-page .tx-table-row:hover, +.sf-page .tx-table-row--alt:hover { + background: var(--sf-surface-hover); +} +.sf-page .tx-table-row--alt { + background: rgba(255, 255, 255, 0.02); +} +.sf-page .tx-td-amount { + font-family: var(--sf-font-display); + color: var(--sf-success-soft); +} +.sf-page .tx-td-details { + font-family: var(--sf-font-mono); + color: var(--sf-text-variant); +} +.sf-page .tx-badge--direction.tx-badge--in { + background: rgba(0, 227, 144, 0.15); + color: var(--sf-success-soft); +} +.sf-page .tx-badge--direction.tx-badge--out { + background: rgba(247, 147, 26, 0.15); + color: var(--sf-primary); +} +.sf-page .tx-badge--type { + background: var(--sf-surface-hover); + color: var(--sf-text-variant); + border: 1px solid var(--sf-surface-border); +} +.sf-page .tx-mobile-card { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); +} +.sf-page .tx-mobile-amount { + font-family: var(--sf-font-display); + color: var(--sf-success-soft); +} +.sf-page .tx-skeleton-card { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); +} +.sf-page .tx-empty-title { + font-family: var(--sf-font-display); + color: var(--sf-text); +} +.sf-page .tx-empty-desc { + color: var(--sf-text-variant); +} + +/* ---- Sponsors page + homepage strip ---- */ +.sf-page .sponsors-page { + max-width: none; + margin: 0; +} +.sf-page .sponsors-page-title { + font-family: var(--sf-font-display); + font-weight: 700; + letter-spacing: -0.02em; +} +.sf-page .sponsors-page-subtitle { + color: var(--sf-text-variant); +} +.sf-page .sponsors-pricing { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); + box-shadow: 0 0 30px rgba(247, 147, 26, 0.06); +} +.sf-page .sponsors-pricing h3 { + font-family: var(--sf-font-display); +} +.sf-page .sponsors-cta-btn { + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border-radius: var(--sf-radius-sm); + font-weight: 600; + box-shadow: 0 0 20px var(--sf-primary-glow); + transition: filter 0.2s, box-shadow 0.25s; +} +.sf-page .sponsors-cta-btn:hover { + filter: brightness(1.08); + box-shadow: 0 0 28px rgba(247, 147, 26, 0.35); + opacity: 1; +} +.sf-page .sponsors-section h2 { + font-family: var(--sf-font-display); +} +.sats-flow .sponsor-card { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); + transition: border-color 0.2s, box-shadow 0.25s; +} +.sats-flow .sponsor-card:hover { + background: var(--sf-surface); + border-color: var(--sf-primary); + box-shadow: 0 0 24px var(--sf-primary-glow); +} +.sats-flow .sponsor-card-title { + font-family: var(--sf-font-display); +} +.sats-flow .sponsor-card-cta { + color: var(--sf-primary); +} +.sats-flow .homepage-sponsors { + border-top-color: var(--sf-surface-border); + background: var(--sf-bg); +} +.sats-flow .homepage-sponsors-title { + font-family: var(--sf-font-mono); + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--sf-outline); +} +.sats-flow .homepage-sponsors-link a { + color: var(--sf-primary); +} + +/* ---- My Ads page ---- */ +.sf-page .my-ads-page { + max-width: none; + margin: 0; + padding: 0; +} +.sf-page .my-ads-header h1 { + font-family: var(--sf-font-display); + font-weight: 700; + letter-spacing: -0.02em; +} +.sf-page .my-ads-header p { + color: var(--sf-text-variant); +} +.sf-page .my-ads-table-wrap { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); + padding: 8px 0; + box-shadow: 0 0 30px rgba(247, 147, 26, 0.06); +} +.sf-page .my-ads-table th { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--sf-outline); + border-bottom: 1px solid var(--sf-outline-variant); +} +.sf-page .my-ads-table td { + border-bottom: 1px solid var(--sf-outline-variant); + color: var(--sf-text); +} +.sf-page .my-ads-table tr:hover td { + background: var(--sf-surface-hover); +} +.sf-page .my-ads-status--active { + background: rgba(0, 227, 144, 0.15); + color: var(--sf-success-soft); +} +.sf-page .my-ads-status--pending_payment { + background: rgba(247, 147, 26, 0.15); + color: var(--sf-primary); +} +.sf-page .my-ads-status--expired { + background: var(--sf-surface-hover); + color: var(--sf-outline); +} +.sf-page .my-ads-mobile-card { + background: var(--sf-surface); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-lg); +} +.sf-page .my-ads-create-link, +.sf-page .my-ads-edit-btn, +.sf-page .my-ads-mobile-action-link { + color: var(--sf-primary); +} +.sf-page .my-ads-pay-btn { + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border: none; + border-radius: var(--sf-radius-sm); + font-weight: 600; +} + +/* ---- Shared modals + forms ---- */ +.sats-flow .modal { + background: var(--sf-popover); + border: 1px solid var(--sf-popover-border); + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5); +} +.sats-flow .modal-overlay { + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); +} +.sats-flow .modal-title { + font-family: var(--sf-font-display); + color: var(--sf-text); +} +.sats-flow .login-modal-tab { + font-family: var(--sf-font-mono); + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.06em; +} +.sats-flow .login-modal-tab.active { + color: var(--sf-primary); + border-bottom-color: var(--sf-primary); +} +.sats-flow .login-modal-input, +.sats-flow .login-modal-textarea { + background: var(--sf-recessed); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + color: var(--sf-text); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3); +} +.sats-flow .login-modal-input:focus, +.sats-flow .login-modal-textarea:focus { + border-color: var(--sf-primary); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 1px var(--sf-primary); +} +.sats-flow .login-method-btn { + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border-radius: var(--sf-radius-sm); + font-weight: 600; +} +.sats-flow .sponsor-form-label { + font-family: var(--sf-font-mono); + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--sf-outline); +} +.sats-flow .sponsor-form-input, +.sats-flow .sponsor-form-textarea { + background: var(--sf-recessed); + border: 1px solid var(--sf-surface-border); + border-radius: var(--sf-radius-sm); + color: var(--sf-text); + box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3); +} +.sats-flow .sponsor-form-input:focus, +.sats-flow .sponsor-form-textarea:focus { + outline: none; + border-color: var(--sf-primary); +} +.sats-flow .sponsor-form-price { + background: var(--sf-recessed); + border: 1px solid var(--sf-outline-variant); + border-radius: var(--sf-radius-sm); +} +.sats-flow .sponsor-form-price-value { + font-family: var(--sf-font-display); + color: var(--sf-primary); +} +.sats-flow .sponsor-form-btn.primary { + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border-radius: var(--sf-radius-sm); + font-weight: 600; +} +.sats-flow .sponsor-form-btn.secondary { + background: transparent; + border: 1px solid var(--sf-surface-border); + color: var(--sf-text); + border-radius: var(--sf-radius-sm); +} +.sats-flow .sponsor-form-btn.secondary:hover { + border-color: var(--sf-primary); + color: var(--sf-primary); +} +.sats-flow .sponsor-invoice-copy { + background-image: linear-gradient(135deg, var(--sf-primary), var(--sf-primary-light)); + color: var(--sf-on-primary); + border-radius: var(--sf-radius-sm); + font-weight: 600; +} +.sats-flow .header-user-menu { + background: var(--sf-popover); + border-color: var(--sf-popover-border); +} +.sats-flow .site-footer-nav a { + font-family: var(--sf-font-mono); + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--sf-outline); +} +.sats-flow .site-footer-nav a:hover { + color: var(--sf-primary); +}