Adds app/static/logo.svg — the official Palladium logo (fetched from the
palladium-coin/palladium-web-site repo), reprocessed for crisp display at
small sizes: the white/blue boundary is sharpened (steep contrast curve
instead of the soft anti-aliasing baked into the low-res source) and the
outer circle uses an analytically computed alpha edge instead of a
rasterized ellipse, so it stays perfectly round with no pixel staircase at
any size. Shape and colors are otherwise identical to the source artwork.
Wired up as the navbar brand mark (replacing the plain amber "P" square) in
index.html, and as the favicon for both index.html and admin.html.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Checking it disables the amount field, autofills it with the current
balance, and keeps it in sync if the balance changes while checked. The
actual withdrawal request uses the raw balance_sats value directly instead
of round-tripping through the PLM input field, avoiding float-rounding
drift when withdrawing the exact full balance.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Restructures app/static/index.html's visual design without touching any JS
logic or element IDs:
- Typography switched to IBM Plex Sans (financial/trustworthy pairing),
Fira Code kept for addresses and numeric mono values.
- Design tokens extended with elevation shadows, an inset-surface color,
and a scaled border-radius system; cards/buttons get subtle depth instead
of flat borders.
- Navigation goes adaptive: a native-app-style fixed bottom tab bar on
mobile (thumb-reachable), promoted back to an inline tab strip once the
viewport is wide enough (>=720px) to fit one comfortably under the header.
- Top bar decluttered: balance shown as a highlighted pill (icon + value),
Guida/Segnala un bug/Esci condensed into icon buttons with tooltips and
aria-labels instead of full-text links.
- Round-status card gets a subtle gradient "hero" treatment to read as the
central live widget of the dashboard.
- Content width now adapts from 480px (mobile) to 620px (>=720px) instead
of staying phone-narrow on desktop; safe-area insets reserved for the
fixed bottom bar and toast stack.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a navbar-balance span next to the username, kept in sync by the
existing refreshMe() calls (login, after a bet, after a withdrawal, manual
refresh) — no new endpoint needed, /users/me already returns balance_sats.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Serves docs/guida-utente.md as plain text at GET /guida (no markdown
rendering, kept simple) and links it from the navbar next to a "Segnala un
bug" button. The bug-report link is a placeholder GitHub issues URL
(REPLACE_ME) until a real repo exists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
embit's address_to_scriptpubkey only knows Bitcoin's network prefixes, not
PLM's — so a legacy P2PKH address (prefix 55, "P...") silently produces a
None scriptpubkey instead of a clear rejection, and P2SH only works by
coincidence. Until the address decoding is fixed to use PLM's own network
prefixes, surface the current limitation to users in the withdrawal form
and the user guide instead of letting them lose funds to a broken address.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The round timer relied on each client's own wall clock, so two browsers with
skewed local clocks showed different countdowns for the same round; the
server now also returns server_time so the frontend can correct for clock
skew. Also drop out-of-order /rounds/current responses (multiple independent
triggers could resolve late and revert the UI to a stale drawing/result
state) and prune per-round bookkeeping maps on round transitions.
Separately, place_bet only checked status == "open", leaving a window (up to
the scheduler's 5s tick interval) after a round's timer hit zero where a new
bet could still be accepted. place_bet now checks the round's own deadline
directly (round_accepts_bets), acting as an immediate "yellow light" for new
entries while still letting already-broadcast bets confirm before the round
closes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Session hardening: / and /admin now respond with Cache-Control: no-store, and
both pages re-derive their auth state on pageshow (event.persisted) as a
safety net against bfcache showing a stale logged-in/out view across
back/forward navigation. The user page also syncs logout across tabs via the
storage event, since localStorage is shared but in-memory JS state isn't.
Password recovery: admin gets a "Reset" button per user (POST
/admin/users/{id}/reset-password) that generates and sets a new password,
shown once — passwords are Argon2-hashed and can never be recovered, only
replaced. Users get self-service password change (POST
/users/me/change-password, requires the current password) under a new
Profilo tab, alongside read-only account info (username, address, balance,
join date).
Round display robustness: the user dashboard now refreshes immediately on
tab visibility change (background tabs get their timers throttled hard),
shows an explicit "connessione persa" state after repeated failed polls
instead of silently freezing on stale data, and polls faster both right when
the countdown hits zero and through the gap where the round is past its
deadline but still waiting for in-flight bets to confirm before the server
actually closes it.
RoundConfig gets a paused flag toggled via new POST /admin/pause and
/admin/resume endpoints (audit-logged, surfaced as a "Manutenzione" card in
the admin Parametri view). Pausing only stops the *next* round from opening
once the current one closes — rounds/service.py:open_new_round_if_needed
still lets an in-progress round finish, draw, and pay out its winner
normally. GET /rounds/current exposes lottery_paused so the user page shows
a maintenance banner (even while logged out) instead of silently going idle.
Also replaces the user dashboard's stacked account-bar card + bento-grid
menu with a single sticky navbar (identity row + Deposito/Bet/Prelievo
tabs), and moves the page content into a dedicated .app-shell container so
the navbar itself can span full width.
The user page's login screen was a bare test dashboard with no explanation
of how the lottery works; it now leads with a hero (3-step explainer, trust
pills) shown only while logged out, plus a bento-style nav and a glowing
round card during the draw.
Both the user and admin pages now show the current chain tip height and
lottery status (open / drawing / waiting for next round) via a small status
strip, polled from /rounds/current (extended with chain_tip_height sourced
from ElectrumListener.tip_height).
When the round leaves "open" (closing/drawing/paying_out), the round
card swaps its timer for a spinning "Estrazione del vincitore in
corso…" state instead — bets are already rejected server-side once the
round isn't open, this just reflects that visually. Once winner_user_id
is set AND at least draw_animation_seconds has elapsed since the round
started closing (client-tracked per round_id), it reveals "🎉 Hai
vinto! +N PLM" (compared against the user's own id from /users/me) or
"Non hai vinto questa volta.", with a success toast on a win. The
result stays on screen through the cooldown gap and only clears once a
genuinely new round opens (tracked via activeResultRoundId), not the
instant the old round has no active status.
Polling is now dynamic (setTimeout-chained, not setInterval): 3s while
the round is closing/drawing/paying_out for a responsive reveal, 15s
while open.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Registration now requires the password twice, rejected client-side on
mismatch before hitting the API. The admin page gets a Utenti card:
loads the user list (id, username, address, balance in PLM) and a
per-row "Mostra" button that reveals the private key after an explicit
confirm() — click again to hide it. A persistent warning banner notes
that every reveal is audit-logged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A card above the section menu polls GET /rounds/current every 15s and
ticks a mm:ss countdown to closes_at every second locally, showing
status (aperto/in chiusura/estrazione/pagamento), participant count
and jackpot in PLM. Refreshed immediately after placing a bet, and
timers are cleared on logout.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Deposito/Bet/Prelievo are now separate panels behind a top nav instead
of one long scroll of cards, and the Deposito panel renders the
deposit address as a QR code (via GET /qr/{address}) alongside the
existing copy-to-clipboard address box.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New visual system from the ui-ux-pro-max skill (gold/purple accents,
Fira Sans + Fira Code, light mode, WCAG AA contrast): card layout,
tabbed login/register, loading states on every button, and toast
feedback instead of a raw request/response JSON dump. The dump is gone
from both pages — diagnosing an error now means reading logs/app.log,
not staring at the page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Balance, withdrawal amount and bet_amount_sats are entered/displayed in
PLM in both static pages; conversion to sats happens client-side right
before the API call, since the backend contract stays sats-based.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Moves the fee_address/bet_amount_sats config form out of the main test
UI into a dedicated admin.html, served by a GET /admin route
(registered ahead of the StaticFiles mount so it doesn't shadow the
existing GET/PUT /admin/config API). Deliberately not linked from the
test UI in either direction: reachable only by knowing the URL.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lets an operator load and update fee_address/bet_amount_sats from a
form (using the X-Admin-Token header) instead of curl/Swagger, with
inline status feedback and the same request/response log as the rest
of the page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Single-page vanilla HTML/JS frontend (register/login, balance,
place bet, withdraw) served by FastAPI at the same origin so it can
exercise the live API without CORS setup. Manual-testing aid only,
not part of the MVP spec.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>