visual redesign: landing, dashboard overview, session calendar (2.3.1)

- Redesign landing page hero with split layout, features section, and in-app session/result demos
- Add fixed sidebar scroll isolation (app-shell overflow lock pattern)
- Redesign leagues index cards with initial badge, podium leader chips, and action links
- Redesign league dashboard: color-coded nav tiles, cash/stats overview strip, session history heatmap calendar
- Dashboard cash stats use real cash only (excludes rollovers and carry-ins)
- Session history calendar: JS-driven full-year grid, year navigation, hover tooltips, full-width responsive layout
- Bump leaderboard tile color from gold to blue (distinct from ledger orange)
- Bump version to 2.3.1
This commit is contained in:
SowinskiBraeden committed 2026-06-26 21:24:00 -07:00
1 parent 56c9a1084c
commit a5cb488b91
22 files changed
+2975 -597

No files matched your search

+283 -137
View File
@@ -1,157 +1,303 @@
{% extends "base.html" %}
{% block title %}myboker.org · Poker league records{% endblock %}
{% block page_class %}page--landing{% endblock %}
{% block content %}
<section class="l-hero">
<p class="l-hero__kicker">For private poker leagues</p>
<h1 class="l-hero__h1">Your home game,<br>properly tracked.</h1>
<p class="l-hero__sub">Sessions, ledgers, leaderboards, and settlement visibility — built for home groups that want clean records without a payment app or social network in the way.</p>
<div class="l-hero__cta">
{% if is_logged_in %}
<a class="btn btn--primary" href="{{ url_for('leagues.index') }}">Open leagues</a>
{% else %}
<a class="btn btn--primary" href="{{ url_for('account.register') }}">Create account</a>
<a class="btn btn--ghost" href="{{ url_for('account.login') }}">Sign in</a>
<a class="btn btn--ghost" href="{{ url_for('public.explore') }}">Explore league stats</a>
{% endif %}
</div>
</section>
<div class="l-preview" aria-hidden="true">
<div class="l-preview__panel">
<div class="l-preview__head">
<span class="kicker" style="margin:0;">Leaderboard</span>
<span class="l-preview__tag">All-time</span>
<div class="lp-hero">
<div class="lp-hero__content">
<span class="lp-eyebrow">Home poker tracking</span>
<h1 class="lp-h1">
<span class="lp-h1__line">Your</span>
<span class="lp-h1__line">league,</span>
<span class="lp-h1__accent">on record.</span>
</h1>
<p class="lp-sub">Sessions, leaderboards, and settlement tracking for home poker groups. No fees, no payment apps in the way.</p>
<div class="lp-cta">
{% if is_logged_in %}
<a class="btn btn--primary btn--lg" href="{{ url_for('leagues.index') }}">Open my leagues →</a>
{% else %}
<a class="btn btn--primary btn--lg" href="{{ url_for('account.register') }}">Start your league →</a>
<a class="btn btn--ghost btn--lg" href="{{ url_for('account.login') }}">Sign in</a>
{% endif %}
</div>
<div class="l-preview__rows">
<div class="l-preview__row">
<span class="l-preview__rank">1</span>
<span class="l-preview__player">Rivera</span>
<span class="l-preview__val l-preview__val--pos">+$1,420</span>
</div>
<div class="l-preview__row">
<span class="l-preview__rank">2</span>
<span class="l-preview__player">Chen</span>
<span class="l-preview__val l-preview__val--pos">+$640</span>
</div>
<div class="l-preview__row">
<span class="l-preview__rank">3</span>
<span class="l-preview__player">Okafor</span>
<span class="l-preview__val l-preview__val--neg">-$210</span>
</div>
<div class="l-preview__row l-preview__row--faded">
<span class="l-preview__rank">4</span>
<span class="l-preview__player">Walsh</span>
<span class="l-preview__val l-preview__val--neg">-$850</span>
</div>
<div class="lp-trust">
<span>No fees</span>
<span class="lp-trust__sep">·</span>
<span>Append-only ledger</span>
<span class="lp-trust__sep">·</span>
<span>Private by default</span>
{% if not is_logged_in %}
<span class="lp-trust__sep">·</span>
<a href="{{ url_for('public.explore') }}" style="color:inherit;text-decoration:underline;text-decoration-color:rgba(255,255,255,.2);">Explore public leagues</a>
{% endif %}
</div>
</div>
<div class="l-preview__panel l-preview__panel--featured">
<div class="l-preview__head">
<span class="kicker" style="margin:0;">Session #18</span>
<span class="live-badge">live</span>
</div>
<div class="l-preview__stats">
<div class="l-preview__stat">
<span class="kicker" style="margin:0;">Cash in</span>
<strong>$1,200</strong>
<div class="lp-hero__visual" aria-hidden="true">
<div class="lp-demo__card">
<div class="lp-demo__head">
<div>
<span class="lp-demo__kicker">Friday Night Poker</span>
<span class="lp-demo__title">Leaderboard · Eligible</span>
</div>
<span class="lp-demo__meta">18 sessions · 5 players</span>
</div>
<div class="l-preview__stat">
<span class="kicker" style="margin:0;">Players</span>
<strong>8</strong>
</div>
<div class="l-preview__stat">
<span class="kicker" style="margin:0;">Open debts</span>
<strong style="color:var(--warn);">$180</strong>
</div>
</div>
<div class="l-preview__evts">
<div class="l-preview__evt">
<span class="pill pill-buyin">buy-in</span>
<span class="l-preview__evt-name">Rivera</span>
<span class="l-preview__evt-val">$200</span>
</div>
<div class="l-preview__evt">
<span class="pill pill-front">front</span>
<span class="l-preview__evt-name">Chen</span>
<span class="l-preview__evt-val">$200</span>
</div>
<div class="l-preview__evt">
<span class="pill pill-cashout">cashout</span>
<span class="l-preview__evt-name">Okafor</span>
<span class="l-preview__evt-val">$450</span>
</div>
</div>
</div>
<div class="l-preview__panel">
<div class="l-preview__head">
<span class="kicker" style="margin:0;">Open debts</span>
<span class="l-preview__tag">Session #17</span>
</div>
<div class="l-preview__rows">
<div class="l-preview__row">
<span class="l-preview__player">Walsh</span>
<span class="l-preview__val" style="color:var(--owes);">owes $120</span>
</div>
<div class="l-preview__row">
<span class="l-preview__player">Okafor</span>
<span class="l-preview__val" style="color:var(--owes);">owes $60</span>
</div>
<div class="l-preview__row l-preview__row--faded">
<span class="l-preview__player">Chen</span>
<span class="l-preview__val" style="color:var(--pos);">settled</span>
</div>
<div class="l-preview__row l-preview__row--faded">
<span class="l-preview__player">Rivera</span>
<span class="l-preview__val" style="color:var(--pos);">settled</span>
<div class="lp-demo__table">
<div class="lp-demo__thead lp-demo__thead--lb">
<span class="lp-demo__th">#</span>
<span class="lp-demo__th">Player</span>
<span class="lp-demo__th">Δ</span>
<span class="lp-demo__th">Net</span>
<span class="lp-demo__th">Win%</span>
<span class="lp-demo__th">ROI</span>
</div>
<div class="lp-demo__row lp-demo__row--lb">
<span class="lp-demo__rank lp-demo__rank--1">1</span>
<span class="lp-demo__player">Rivera</span>
<span class="lp-demo__delta lp-demo__delta--up">▲1</span>
<span class="lp-demo__num lp-demo__num--pos">+$1,420</span>
<span class="lp-demo__num lp-demo__num--pos">72%</span>
<span class="lp-demo__num lp-demo__num--pos">+46%</span>
</div>
<div class="lp-demo__row lp-demo__row--lb">
<span class="lp-demo__rank lp-demo__rank--2">2</span>
<span class="lp-demo__player">Chen</span>
<span class="lp-demo__delta"></span>
<span class="lp-demo__num lp-demo__num--pos">+$640</span>
<span class="lp-demo__num lp-demo__num--pos">56%</span>
<span class="lp-demo__num lp-demo__num--pos">+18%</span>
</div>
<div class="lp-demo__row lp-demo__row--lb">
<span class="lp-demo__rank lp-demo__rank--3">3</span>
<span class="lp-demo__player">Okafor</span>
<span class="lp-demo__delta lp-demo__delta--down">▼1</span>
<span class="lp-demo__num lp-demo__num--neg">$210</span>
<span class="lp-demo__num lp-demo__num--neg">43%</span>
<span class="lp-demo__num lp-demo__num--neg">7%</span>
</div>
<div class="lp-demo__row lp-demo__row--lb lp-demo__row--fade">
<span class="lp-demo__rank">4</span>
<span class="lp-demo__player">Walsh</span>
<span class="lp-demo__delta"></span>
<span class="lp-demo__num lp-demo__num--neg">$850</span>
<span class="lp-demo__num lp-demo__num--neg">31%</span>
<span class="lp-demo__num lp-demo__num--neg">27%</span>
</div>
<div class="lp-demo__row lp-demo__row--lb lp-demo__row--fade2">
<span class="lp-demo__rank">5</span>
<span class="lp-demo__player">Novak</span>
<span class="lp-demo__delta lp-demo__delta--down">▼2</span>
<span class="lp-demo__num lp-demo__num--neg">$1,000</span>
<span class="lp-demo__num lp-demo__num--neg">25%</span>
<span class="lp-demo__num lp-demo__num--neg">42%</span>
</div>
</div>
</div>
</div>
</div>
<section class="l-features">
<div class="l-feature">
<div class="l-feature__icon">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true">
<rect x="1" y="7" width="14" height="13" rx="2" stroke="currentColor" stroke-width="1.5"/>
<path d="M5 7V5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<!-- Features -->
<section class="lp-features">
<div class="lp-features__inner">
<div class="lp-sec-head">
<span class="lp-eyebrow">What's included</span>
<h2 class="lp-sec-title">No spreadsheets. No Venmo math. No guessing.</h2>
</div>
<h3 class="l-feature__title">League workspaces</h3>
<p class="l-feature__desc">Each league has its own players, sessions, leaderboard, and accounting. One account can manage multiple leagues independently.</p>
</div>
<div class="l-feature">
<div class="l-feature__icon">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true">
<rect x="3" y="3" width="16" height="16" rx="2" stroke="currentColor" stroke-width="1.5"/>
<path d="M7 8h8M7 11h6M7 14h4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
<div class="lp-feat-grid">
<div class="lp-feat">
<div class="lp-feat__icon">
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
<rect x="2" y="4" width="16" height="14" rx="2.5" stroke="currentColor" stroke-width="1.5"/>
<path d="M6 2v4M14 2v4M2 9h16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<path d="M6 12.5h3M6 15.5h5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
</svg>
</div>
<h3 class="lp-feat__title">Game-night sessions</h3>
<p class="lp-feat__desc">Open a session at the start of the night, log buy-ins and cashouts as they happen, then close it when the last player leaves. Multiple sessions on the same date auto-sequence as S1, S2.</p>
</div>
<div class="lp-feat">
<div class="lp-feat__icon">
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
<rect x="1.5" y="11" width="4.5" height="7" rx="1.2" stroke="currentColor" stroke-width="1.5"/>
<rect x="7.75" y="7" width="4.5" height="11" rx="1.2" stroke="currentColor" stroke-width="1.5"/>
<rect x="14" y="2" width="4.5" height="16" rx="1.2" stroke="currentColor" stroke-width="1.5"/>
</svg>
</div>
<h3 class="lp-feat__title">Rankings that earn their spot</h3>
<p class="lp-feat__desc">Set a minimum session count so regulars rank and one-time guests go provisional until they qualify. Sort by net, ROI, win rate, or recent form. Every number is derived directly from raw ledger events.</p>
</div>
<div class="lp-feat">
<div class="lp-feat__icon">
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true">
<rect x="3" y="2" width="14" height="16" rx="2" stroke="currentColor" stroke-width="1.5"/>
<path d="M7 7h6M7 10.5h6M7 14h3.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</div>
<h3 class="lp-feat__title">Settlement without the spreadsheet</h3>
<p class="lp-feat__desc">Every event is logged and kept: buy-ins, cashouts, fronts, corrections. Nothing is deleted; mistakes get fixed by appending. When a session closes, the house knows exactly what it holds and who is owed what.</p>
</div>
</div>
<h3 class="l-feature__title">Append-only ledger</h3>
<p class="l-feature__desc">Buy-ins, fronts, cashouts, rollovers, debt repayments, and write-offs stay permanently on record. Events are never deleted.</p>
</div>
<div class="l-feature">
<div class="l-feature__icon">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true">
<path d="M3 17L8 11L13 14L20 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 20h18" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</div>
<h3 class="l-feature__title">Performance analytics</h3>
<p class="l-feature__desc">Net, ROI, win rate, and all-time cash movement are computed from ledger events. Rankings stay separate from settlement records.</p>
</div>
<div class="l-feature">
<div class="l-feature__icon">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true">
<path d="M7 5h8M15 5l-3-3m3 3l-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M15 17H7m0 0l3 3m-3-3l3-3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<h3 class="l-feature__title">Settlement visibility</h3>
<p class="l-feature__desc">Open debts, player payables, and house receivables are always tracked. Share settlement status with the group, not just final numbers.</p>
</div>
</section>
<!-- App demos -->
<section class="lp-showcase">
<div class="lp-showcase__inner">
<div class="lp-sec-head">
<span class="lp-eyebrow">In the app</span>
<h2 class="lp-sec-title">Sessions and results</h2>
<p class="lp-sec-sub">Every number your group tracks, in one place.</p>
</div>
<div class="lp-showcase__grid" aria-hidden="true">
<!-- Sessions panel -->
<div class="lp-demo__card">
<div class="lp-demo__head">
<div>
<span class="lp-demo__kicker">Friday Night Poker</span>
<span class="lp-demo__title">Sessions</span>
</div>
<span class="lp-demo__meta">6 total</span>
</div>
<div class="lp-sess-list">
<div class="lp-sess-row">
<div class="lp-sess-date">
<span class="lp-sess-date__mon">Jun</span>
<span class="lp-sess-date__day">21</span>
</div>
<div class="lp-sess-info">
<span class="lp-sess-label">Session 1</span>
<span class="lp-sess-meta">5 players · $250 pot</span>
</div>
<span class="lp-sess-pill lp-sess-pill--open">open</span>
</div>
<div class="lp-sess-row">
<div class="lp-sess-date">
<span class="lp-sess-date__mon">Jun</span>
<span class="lp-sess-date__day">14</span>
</div>
<div class="lp-sess-info">
<span class="lp-sess-label">Session 1</span>
<span class="lp-sess-meta">5 players · $300 pot</span>
</div>
<span class="lp-sess-pill lp-sess-pill--closed">closed</span>
</div>
<div class="lp-sess-row">
<div class="lp-sess-date">
<span class="lp-sess-date__mon">Jun</span>
<span class="lp-sess-date__day">7</span>
</div>
<div class="lp-sess-info">
<span class="lp-sess-label">Session 1</span>
<span class="lp-sess-meta">4 players · $200 pot</span>
</div>
<span class="lp-sess-pill lp-sess-pill--closed">closed</span>
</div>
<div class="lp-sess-row lp-sess-row--fade">
<div class="lp-sess-date">
<span class="lp-sess-date__mon">May</span>
<span class="lp-sess-date__day">31</span>
</div>
<div class="lp-sess-info">
<span class="lp-sess-label">Session 1</span>
<span class="lp-sess-meta">6 players · $350 pot</span>
</div>
<span class="lp-sess-pill lp-sess-pill--closed">closed</span>
</div>
<div class="lp-sess-row lp-sess-row--fade2">
<div class="lp-sess-date">
<span class="lp-sess-date__mon">May</span>
<span class="lp-sess-date__day">24</span>
</div>
<div class="lp-sess-info">
<span class="lp-sess-label">Session 1</span>
<span class="lp-sess-meta">5 players · $250 pot</span>
</div>
<span class="lp-sess-pill lp-sess-pill--closed">closed</span>
</div>
</div>
</div>
<!-- Session results panel -->
<div class="lp-demo__card">
<div class="lp-demo__head">
<div>
<span class="lp-demo__kicker">Friday Night Poker</span>
<span class="lp-demo__title">Session #006 · Jun 21</span>
</div>
<span class="lp-demo__meta">5 players · open</span>
</div>
<div class="lp-recon-grid">
<div class="lp-recon-cell">
<span class="lp-recon-label">Cash in</span>
<span class="lp-recon-val">$300</span>
</div>
<div class="lp-recon-cell">
<span class="lp-recon-label">Paid out</span>
<span class="lp-recon-val lp-demo__num--pos">$190</span>
</div>
<div class="lp-recon-cell">
<span class="lp-recon-label">House owes players</span>
<span class="lp-recon-val lp-demo__num--neg">$110</span>
</div>
<div class="lp-recon-cell">
<span class="lp-recon-label">Players owe house</span>
<span class="lp-recon-val">$0</span>
</div>
</div>
<div class="lp-result-thead">
<span>Player</span>
<span>Invested</span>
<span>Net</span>
<span>Open</span>
</div>
<div class="lp-result-row">
<span class="lp-demo__player">Rivera</span>
<span class="lp-demo__num">$50</span>
<span class="lp-demo__num lp-demo__num--pos">+$120</span>
<span class="lp-result-due">due $120</span>
</div>
<div class="lp-result-row">
<span class="lp-demo__player">Chen</span>
<span class="lp-demo__num">$100</span>
<span class="lp-demo__num lp-demo__num--pos">+$90</span>
<span class="lp-result-due">due $90</span>
</div>
<div class="lp-result-row">
<span class="lp-demo__player">Walsh</span>
<span class="lp-demo__num">$50</span>
<span class="lp-demo__num lp-demo__num--neg">-$50</span>
<span class="lp-result-settled">settled</span>
</div>
<div class="lp-result-row lp-demo__row--fade">
<span class="lp-demo__player">Okafor</span>
<span class="lp-demo__num">$50</span>
<span class="lp-demo__num lp-demo__num--pos">+$30</span>
<span class="lp-result-due">due $30</span>
</div>
<div class="lp-result-row lp-demo__row--fade2">
<span class="lp-demo__player">Novak</span>
<span class="lp-demo__num">$100</span>
<span class="lp-demo__num lp-demo__num--neg">-$100</span>
<span class="lp-result-settled">settled</span>
</div>
</div>
</div>
</div>
</section>
{% if not is_logged_in %}
<section class="lp-bottom-cta">
<div class="lp-bottom-cta__inner">
<h2 class="lp-bottom-cta__title">Start tracking your league</h2>
<p class="lp-bottom-cta__sub">Free to use. No payment processor. Your data stays yours.</p>
<div class="lp-cta" style="justify-content:center;">
<a class="btn btn--primary btn--lg" href="{{ url_for('account.register') }}">Create an account →</a>
<a class="btn btn--ghost btn--lg" href="{{ url_for('public.explore') }}">Browse public leagues</a>
</div>
</div>
</section>
{% endif %}
{% endblock %}