- Replace globe lines with 3x2 dot grid (characteristic padel racket holes)
- Makes racket immediately recognizable vs globe/frying pan shape
- Add ?v=3 to all favicon links to force browser cache refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace circle with rounded rectangle (rx=6, ~30% corner radius)
matching the typical padel racket head proportions
- Handle now connects from bottom edge of rect
- New favicon.svg plus regenerated ico/png/apple-touch-icon from same design
- Add SVG favicon link (modern browsers) with ico/png fallbacks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add /imprint route and template stub (fill in company details)
- Move About out of Legal into a new Company column
- Add /imprint to sitemap and RESERVED_PREFIXES
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Assigns visitors to experiment variants via cookie (30-day), sets g.ab_variant
and g.ab_tag, and conditionally adds data-tag to the Umami script tag so all
pageviews and events are automatically tagged in the Umami dashboard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix CSS-only billing toggle: radio inputs were nested inside
.s-billing-toggle, so ~ siblings couldn't reach plan card price
elements inside <form>. Moved radios to be direct siblings of both
.s-billing-toggle and <form>. Updated CSS selectors accordingly.
Removed .price-yearly{display:block} override that broke monthly view.
- Set Most Popular badge on Growth (not Pro) in signup wizard — Growth
is the natural entry point for lead-receiving suppliers
- Update public pricing page: Growth €149→€199, Pro €399→€499
- Refresh Pro feature list: logo+cover photo, full stats, verified badge
(no longer described as add-ons since they're built into Pro)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eliminated dual-maintenance of schema.sql + versioned migrations.
All databases (fresh and existing) now replay migrations in order
starting from 0000_initial_schema.py. Removed _is_fresh_db() and
the fresh-DB fast-path that skipped migration execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Paddle sandbox sends lifecycle events (subscription.updated, etc.) with
"custom_data": null. The .get("custom_data", {}) default only applies
when the key is missing, not when the value is explicitly null, causing
AttributeError on the next .get() call. Also guarded subscription.activated
to skip when user_id is absent (was inserting user_id=0 → FK violation).
Replaced manual HMAC verification with paddle_billing.Notifications.Verifier
via a lightweight _WebhookRequest wrapper satisfying the SDK's Request Protocol.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
24 tests for credits.py (balance, spend, unlock, refill, ledger) and
10 integration tests for supplier webhook handlers (credit packs, sticky
boosts, subscription activation, business plan purchase). Removed
test_mobile_nav_no_overflow which never asserted its JS result.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Supplier dashboard: impersonate redirects to supplier dashboard when user
owns a supplier, sidenav active tab updates on click, listing preview
capped at 420px, insufficient-credits error shows balance and buy CTA,
boost buy buttons resolve Paddle price IDs server-side.
Dev tooling: dev_run.sh kills child processes on Ctrl-C (process
substitution fix), syncs Paddle products to DB on each run,
setup_paddle.py gains --sync mode and fixes Duration/Interval SDK change.
Seed data: each claimed supplier gets its own owner user and subscription.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
run_with_label piped output through a while loop, so $! tracked the
formatter PID instead of the actual command. Ctrl-C killed the formatters
but left app/worker/css-watch running as orphans. Switch to process
substitution so $! is the real command PID, and pkill -P children before
killing tracked PIDs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Webhook handler called Verifier().verify() with raw bytes instead of a
request object, so signature verification always failed. Replaced with
manual HMAC check matching Paddle's ts=...;h1=... format. Updated tests
to produce correct signature format, mock the SDK instead of httpx for
manage/cancel routes, and expect JSON for overlay checkout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a complete content generation system for producing SEO articles
at scale with embedded financial scenario widgets. Includes DB schema
(published_scenarios, article_templates, template_data, articles with
FTS5), bulk generation pipeline with staggered publish dates, admin CRUD
for templates/scenarios/articles, public markets hub with HTMX filtering,
catch-all article serving from pre-rendered static HTML, sitemap
integration, and 94 pytest tests covering the full stack.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
setup_paddle.py creates a notification destination in Paddle and writes
the webhook secret + setting ID to .env. dev_run.sh resets the DB, seeds
data, and starts an ngrok tunnel to update the webhook URL automatically
for end-to-end checkout testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Quote wizard _accumulated hidden inputs used double-quote attribute delimiters
which broke on tojson output containing literal " characters — all step data was
lost by step 9. Admin dashboard crashed on credit_ledger queries referencing
wrong column names (amount/entry_type vs delta/event_type). Also: opaque nav bar,
pricing card button alignment, newsletter boost replaced with card color boost,
admin CRUD for suppliers/leads, dev seed data script, and playwright quote wizard
tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate all checkouts to Paddle.js overlay (no redirect), move Paddle price
IDs from env vars to DB table, add 4-tab supplier dashboard (overview, leads,
listing, boosts), business plan PDF export with WeasyPrint, enhanced supplier
landing page with live stats, admin supplier management + feedback widget.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Guest quote submissions now require email verification before the lead
goes live. The verification click also creates a user account and logs
them in. Logged-in users submitting with their own email skip verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Nav: Zillow-style centered logo, solid blue Sign In button
- Planner: center app at 72rem, center wizard steps/header/preview
- Country pills: UK/USA labels, remove Other, show permits slider
inline under country so the effect is transparent and adjustable
- Reset button: inline confirm (red "Sure? Reset") instead of alert
- Worker: print magic link to console when DEBUG=true for local dev
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parameter bindings for ORDER BY (now, country) were placed before WHERE
params, causing mismatched bindings when any filter was active. Also
switched hx-include from .dir-search class (shared by form + inputs)
to #dir-search-form ID to prevent duplicate parameters.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Toggle buttons (Indoor/Outdoor, Rent/Buy) now visually update
their active state on click
- Space requirement sliders start from minimum court size
(200m² double, 120m² single) instead of 0
- Defaults updated to court + 2m buffer (336/240/312/216 m²)
- Reference dimensions panel shows standard court sizes
- Chart.js font updated from JetBrains Mono to Commit Mono
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap magic link and welcome emails in a proper HTML email template
with navy header, white card body, CTA button, and muted footer.
Fallback plain-text URL included below the button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Pico CSS CDN with Tailwind v4 standalone CLI (no Node.js).
Brand theme with navy/electric/accent palette, component classes,
self-hosted Commit Mono font. Docker multi-stage CSS build.
Logo links to dashboard when logged in.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Namespace admin templates under admin/ subdirectory to prevent
Quart's template loader from resolving auth's login.html and
dashboard's index.html instead of admin's own templates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Expand migrate.py docstring with algorithm, protocol, and design decisions
- Add 20-test suite for migration framework (test_migrations.py)
- Fix: empty env vars (SECRET_KEY=) now fall back to defaults via _env() helper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Production DB had already been migrated by the manual script, so
the old lemonsqueezy columns no longer exist. Check column names
before attempting the rename.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the simple schema.sql runner with a proper sequential
migration system that tracks applied versions in a _migrations table.
Absorb scripts/migrate_to_paddle.py as versions/0001.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Run copier update with payment_provider=paddle to switch all billing
integration: routes, config, schema columns, webhook handling, tests,
and CI deploy secrets. Add one-time migration script for renaming
lemonsqueezy_* columns to paddle_* in production DB.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace toy-like sliders (rent/m², exit multiple) with more intuitive
inputs (build cost per court, equity %). Replace outputs (annual revenue,
equity IRR) with payback period and cash-on-cash return. Show model
assumptions inline. Remove "free" messaging from all CTAs and meta tags,
focus on the plan→suppliers→financing value chain instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The variable-based overrides (--pico-h1-color, --pico-color) weren't
reliably winning against Pico's multi-layer cascade of theme selectors,
prefers-color-scheme media queries, and variable indirection. Headings
were rendering near-white (#f0f1f3) on dark-OS systems despite
data-theme="light". Using !important on color is the pragmatic fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The heading color override (bare h1 selector, specificity 0,0,1) was
losing to Pico's theme-scoped heading rules ([data-theme=light] h1,
specificity 0,1,1). On systems with prefers-color-scheme: dark, Pico's
dark heading colors (#f0f1f3 — near white) leaked through, making
headings invisible on the light background.
Fix: scope heading overrides under [data-theme="light"] to match Pico's
specificity. Also bump nav logo from 24px to 32px, footer to 24px.
Visual tests now run with color_scheme="dark" to catch this class of bug.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Playwright visual tests need browser binaries (playwright install
chromium) which CI doesn't have. Mark them with pytest.mark.visual
and add addopts = "-m 'not visual'" so they're skipped by default.
Run locally with: uv run pytest -m visual tests/test_visual.py -v
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Trim logo background to transparent, use inline style height to
override Pico's img { height: auto } — nav 24px, footer 20px
- Fix heading colors by setting --pico-h1-color through --pico-h6-color
variables and --pico-color override on heading elements
- Add white-space:nowrap on nav CTA button to prevent wrapping
- Add Playwright visual test suite (11 tests): screenshots of landing,
login, signup, mobile; assertions for light background, dark headings,
logo presence, nav layout, no dark remnants
- Screenshots saved to tests/screenshots/ for manual review
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace dark navy backgrounds with soft white, update all CSS variables,
Chart.js colors, and inline styles across the app. Add logo to nav and
footer. Landing page teaser calculator, planner, and all inherited pages
now use the light theme with deep navy headings and electric blue accents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docker compose --profile stop also stops non-profiled services (router,
litestream), causing 502. Now explicitly names only slot services to stop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>