Initial commit: SuiviCPT personal finance tracker

Laravel 11 + Livewire 3/Volt + Alpine.js + Tailwind app for household
budget planning, transaction tracking, and financial dashboards.

- Multi-tenant households with member invites
- Plan: monthly/yearly budget per category with overrides
- Suivi: transaction log with running balance (desktop + mobile quick-entry)
- Dashboard: budget vs tracked breakdown + Chart.js donuts
- Flux: Sankey diagram of income allocation
- WCAG 2.1 AA color tokens, dark mode, accessible tables/forms
- 50 Pest tests

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
jeremy bayse
2026-07-25 22:39:42 +02:00
co-authored by Claude Sonnet 5
commit d8dc57a5df
164 changed files with 19880 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/*
* Design tokens WCAG 2.1 AA / RGAA color system.
* Text on surface: >= 4.5:1. UI component borders (inputs, focus): >= 3:1.
* Verified via relative-luminance contrast calculation, not eyeballed.
*
* "Fill" tokens (white text placed on top of a solid color, e.g. section
* header bars, filled buttons) are intentionally mode-invariant: the same
* physical contrast math applies regardless of theme, so they don't swap
* under .dark.
*
* negative/positive/info are the three financial-category colors (depense
* / revenu / epargne) and are semantically distinct from `danger`, which is
* reserved for destructive UI actions (delete, remove) spending money is
* not the same concept as an irreversible action, so they get separate hues.
*/
:root {
--color-surface: 255 255 255; /* page/card background */
--color-surface-alt: 249 250 251; /* subtle zebra/alt background, gray-50 */
--color-text: 17 24 39; /* gray-900, 17.7:1 on surface */
--color-text-muted: 75 85 99; /* gray-600, 7.6:1 on surface */
--color-border: 209 213 219; /* gray-300, decorative dividers */
--color-border-strong: 107 114 128; /* gray-500, 4.8:1 — input/UI-component borders (>=3:1) */
--color-brand: 79 70 229; /* indigo-600, 6.3:1 on surface */
--color-brand-emphasis: 67 56 202; /* indigo-700, hover/active */
--color-positive: 21 128 61; /* green-700, 5.0:1 on surface — revenus/gains */
--color-positive-surface: 240 253 244; /* green-50 */
--color-negative: 194 65 12; /* orange-700, 5.2:1 on surface — depenses/pertes */
--color-negative-surface: 255 247 237; /* orange-50 */
--color-info: 29 78 216; /* blue-700, 6.7:1 on surface — epargne */
--color-info-surface: 239 246 255; /* blue-50 */
--color-danger: 185 28 28; /* red-700, 6.5:1 on surface — destructive UI actions */
--color-danger-surface: 254 242 242; /* red-50 */
--color-focus-ring: 99 102 241; /* indigo-500, 4.5:1 on surface */
/* fixed fill colors for solid-background elements (header bars, filled buttons) */
--color-positive-fill: 21 128 61; /* green-700: 5.0:1 white text, 3.5:1 vs dark surface */
--color-negative-fill: 194 65 12; /* orange-700: 5.2:1 white text, 3.4:1 vs dark surface */
--color-info-fill: 37 99 235; /* blue-600: 5.2:1 white text, 3.4:1 vs dark surface */
--color-danger-fill: 220 38 38; /* red-600: 4.8:1 white text, 3.7:1 vs dark surface */
}
.dark {
--color-surface: 24 24 27; /* #18181b zinc-900, not pure black */
--color-surface-alt: 39 39 42; /* zinc-800 card/alt surface */
--color-text: 244 244 245; /* zinc-100, 16.1:1 on surface */
--color-text-muted: 161 161 170; /* zinc-400, 6.9:1 on surface */
--color-border: 63 63 70; /* zinc-700, decorative dividers */
--color-border-strong: 113 113 122; /* zinc-500, 3.7:1 — input/UI-component borders (>=3:1) */
--color-brand: 129 140 248; /* indigo-400, 5.9:1 on surface */
--color-brand-emphasis: 165 180 252; /* indigo-300, hover/active */
--color-positive: 74 222 128; /* green-400, 10.2:1 on surface */
--color-positive-surface: 22 101 52; /* green-800, used at reduced opacity via bg-positive-surface/20 */
--color-negative: 251 146 60; /* orange-400, 7.8:1 on surface */
--color-negative-surface: 154 52 18; /* orange-800, used at reduced opacity via bg-negative-surface/20 */
--color-info: 96 165 250; /* blue-400, 7.0:1 on surface */
--color-info-surface: 30 58 138; /* blue-900, used at reduced opacity via bg-info-surface/20 */
--color-danger: 248 113 113; /* red-400, 6.4:1 on surface */
--color-danger-surface: 127 29 29; /* red-900, used at reduced opacity via bg-danger-surface/20 */
--color-focus-ring: 129 140 248; /* indigo-400, 5.9:1 on surface */
/* fill tokens stay identical to light mode — see rationale above */
--color-positive-fill: 21 128 61;
--color-negative-fill: 194 65 12;
--color-info-fill: 37 99 235;
--color-danger-fill: 220 38 38;
}