diff --git a/frontend/src/app/router.tsx b/frontend/src/app/router.tsx index 18f4b2a..1336976 100644 --- a/frontend/src/app/router.tsx +++ b/frontend/src/app/router.tsx @@ -25,6 +25,9 @@ const ImportsPage = lazy(() => const LoginPage = lazy(() => import('@/pages/LoginPage').then((module) => ({ default: module.LoginPage })), ) +const OverviewPage = lazy(() => + import('@/pages/OverviewPage').then((module) => ({ default: module.OverviewPage })), +) const NotFoundPage = lazy(() => import('@/pages/NotFoundPage').then((module) => ({ default: module.NotFoundPage })), ) @@ -72,7 +75,7 @@ export function AppRoutes() { } /> }> }> - } /> + } /> } /> } /> } /> diff --git a/frontend/src/components/layout/AppLayout.tsx b/frontend/src/components/layout/AppLayout.tsx index 6a2b92d..747802b 100644 --- a/frontend/src/components/layout/AppLayout.tsx +++ b/frontend/src/components/layout/AppLayout.tsx @@ -1,67 +1,97 @@ -import { Link, NavLink, Outlet, useNavigate } from 'react-router-dom' +import { Link, NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { Button } from '@/components/ui/Button' import { LangSwitcher } from '@/components/layout/LangSwitcher' import { useLogout, useMe } from '@/hooks/useAuth' const NAV_ITEMS = [ - { to: '/accounts', key: 'nav.accounts' }, - { to: '/budget', key: 'nav.budget' }, - { to: '/operations', key: 'nav.operations' }, - { to: '/review', key: 'nav.review' }, - { to: '/imports', key: 'nav.imports' }, - { to: '/analytics', key: 'nav.analytics' }, - { to: '/settings', key: 'nav.settings' }, + { to: '/', key: 'nav.month', end: true }, + { to: '/budget', key: 'nav.budget', end: false }, + { to: '/operations', key: 'nav.operations', end: false }, + { to: '/imports', key: 'nav.imports', end: false }, + { to: '/review', key: 'nav.review', end: false }, + { to: '/analytics', key: 'nav.analytics', end: false }, + { to: '/settings', key: 'nav.settings', end: false }, + { to: '/accounts', key: 'nav.accounts', end: false }, ] as const +const MOBILE_NAV_ITEMS = NAV_ITEMS.filter((item) => + ['/', '/operations', '/imports', '/analytics', '/settings'].includes(item.to), +) + export function AppLayout() { const { t } = useTranslation() const me = useMe() const logout = useLogout() const navigate = useNavigate() + const location = useLocation() + const pageKey = location.pathname.split('/').filter(Boolean)[0] ?? 'overview' + + const handleLogout = () => + logout.mutate(undefined, { + onSettled: () => navigate('/login', { replace: true }), + }) return (
{t('common.skipToContent')} -
- -
+ ) +} diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 7ba727a..852d9d6 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -1,26 +1,27 @@ +@import url('https://fonts.googleapis.com/css2?family=Funnel+Sans:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600;700&display=swap'); + :root { - --bg: #0a1120; - --surface: #101a2e; - --surface-2: #16233c; - --border: #26395a; - --border-strong: #3a5480; - --text: #e8eef8; - --muted: #9db0c9; - --accent: #34d399; - --accent-strong: #10b981; - --accent-ink: #04281c; - --amber: #fbbf24; - --amber-ink: #2d2002; - --danger: #f87171; - --danger-ink: #3d0a0a; - --info: #7dd3fc; - --info-ink: #04283c; - --radius: 10px; - --radius-sm: 6px; - --shadow: 0 10px 30px rgba(2, 8, 20, 0.55); - --font: - 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif; - --mono: ui-monospace, 'Cascadia Mono', 'JetBrains Mono', Menlo, Consolas, monospace; + color-scheme: light; + --paper: #f7f5ef; + --paper-deep: #efede6; + --white: #ffffff; + --ink: #161616; + --ink-soft: #252525; + --muted: #6c6b67; + --line: #d7d4cc; + --line-dark: #393939; + --blue: #1769ff; + --blue-dark: #0c2f73; + --blue-soft: #e8eefc; + --green: #14804a; + --green-soft: #ddf4e7; + --amber: #9a5b00; + --amber-soft: #fff0c7; + --red: #b42f25; + --red-soft: #fbe2df; + --font-ui: 'Funnel Sans', 'Arial Narrow', Arial, sans-serif; + --font-data: 'Geist Mono', 'SFMono-Regular', Consolas, monospace; + --sidebar: 238px; } * { @@ -28,48 +29,62 @@ } html { - color-scheme: dark; + min-width: 320px; + background: var(--paper); + scroll-behavior: smooth; } body { margin: 0; - font-family: var(--font); + min-width: 320px; + min-height: 100vh; + font-family: var(--font-ui); font-size: 15px; - line-height: 1.5; - color: var(--text); - background-color: var(--bg); - background-image: - linear-gradient(rgba(125, 211, 252, 0.035) 1px, transparent 1px), - linear-gradient(90deg, rgba(125, 211, 252, 0.035) 1px, transparent 1px); - background-size: 26px 26px; + line-height: 1.45; + color: var(--ink); + background: var(--paper); + -webkit-font-smoothing: antialiased; +} + +button, +input, +select, +textarea { + font: inherit; +} + +a { + color: var(--blue); + text-underline-offset: 0.18em; +} + +::selection { + color: var(--white); + background: var(--blue); +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--blue) var(--paper-deep); +} + +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: var(--paper-deep); +} + +::-webkit-scrollbar-thumb { + background: var(--blue); + border: 3px solid var(--paper-deep); } :focus-visible { - outline: 2px solid var(--info); - outline-offset: 2px; - border-radius: 2px; -} - -.num { - font-variant-numeric: tabular-nums; - font-family: var(--mono); - font-size: 0.95em; -} - -.pos { - color: var(--accent); -} - -.neg { - color: var(--danger); -} - -.transfer { - color: var(--info); -} - -.muted { - color: var(--muted); + outline: 2px solid var(--blue); + outline-offset: 3px; } .visually-hidden { @@ -84,1106 +99,742 @@ body { border: 0; } -.skip-link { - position: absolute; - left: 12px; - top: -48px; - z-index: 100; - padding: 8px 14px; - background: var(--accent); - color: var(--accent-ink); - border-radius: var(--radius-sm); - font-weight: 700; - text-decoration: none; - transition: top 0.15s ease; +.num { + font-family: var(--font-data); + font-variant-numeric: tabular-nums lining-nums; + letter-spacing: -0.02em; } -.skip-link:focus { - top: 12px; +.pos { color: var(--green); } +.neg { color: var(--red); } +.transfer { color: var(--blue); } +.muted { color: var(--muted); } + +.skip-link { + position: fixed; + left: 20px; + top: -56px; + z-index: 200; + padding: 10px 14px; + color: var(--white); + background: var(--blue); + text-decoration: none; } +.skip-link:focus { top: 16px; } + .app-shell { + display: grid; + grid-template-columns: var(--sidebar) minmax(0, 1fr); min-height: 100vh; - display: flex; - flex-direction: column; } -.app-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - padding: 14px 20px; - border-bottom: 1px solid var(--border); - background: rgba(10, 17, 32, 0.85); - backdrop-filter: blur(6px); +.app-sidebar { position: sticky; top: 0; - z-index: 20; + height: 100vh; + display: grid; + grid-template-rows: auto 1fr auto; + gap: 34px; + padding: 26px 24px 20px; + overflow-y: auto; + color: var(--white); + background: var(--ink); +} + +.sidebar-top { + display: grid; + gap: 38px; } .brand { display: inline-flex; align-items: center; - gap: 10px; - font-weight: 800; - font-size: 17px; - letter-spacing: 0.02em; - color: var(--text); + gap: 12px; + width: fit-content; + color: inherit; + font-family: var(--font-data); + font-size: 12px; + font-weight: 700; + letter-spacing: 0.1em; text-decoration: none; } .brand-mark { - width: 22px; - height: 22px; - border-radius: 6px; - background: - linear-gradient(var(--amber), var(--amber)) 0 6px / 16px 3px no-repeat, - linear-gradient(var(--accent), var(--accent)) 0 13px / 10px 3px no-repeat, - linear-gradient(var(--muted), var(--muted)) 0 20px / 16px 3px no-repeat, - var(--surface-2); - border: 1px solid var(--border-strong); + display: inline-grid; + place-items: center; + width: 32px; + height: 32px; + color: var(--white); + background: var(--blue); + font-size: 10px; + letter-spacing: 0; } -.header-side { - display: flex; - align-items: center; - gap: 12px; - flex-wrap: wrap; +.space-identity { + display: grid; + gap: 5px; } -.user-chip { - max-width: 180px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - padding: 4px 10px; - border: 1px dashed var(--border-strong); - border-radius: 999px; - color: var(--muted); - font-size: 13px; +.space-identity span, +.space-identity small, +.sync-state, +.profile-block small { + font-family: var(--font-data); + font-size: 9px; + letter-spacing: 0.07em; + text-transform: uppercase; } -.lang-switch { - display: inline-flex; - gap: 4px; -} - -.lang-switch .is-active { - color: var(--accent-ink); - background: var(--accent); - border-color: var(--accent); -} +.space-identity span { color: #81817d; } +.space-identity strong { font-size: 15px; font-weight: 500; } +.space-identity small { color: #a9c4ff; } .app-nav { - display: flex; - flex-wrap: wrap; - gap: 8px; - padding: 12px 20px 0; + display: grid; + align-content: start; + gap: 3px; } .nav-pill { - padding: 7px 14px; - border: 1px solid var(--border); - border-radius: 999px; - color: var(--muted); - text-decoration: none; - font-weight: 600; + position: relative; + display: flex; + align-items: center; + min-height: 40px; + padding: 0 12px; + color: #aaa9a5; font-size: 14px; - transition: - color 0.12s ease, - border-color 0.12s ease, - background-color 0.12s ease; + font-weight: 500; + text-decoration: none; } -.nav-pill:hover { - color: var(--text); - border-color: var(--border-strong); +.nav-pill::before { + content: ''; + width: 4px; + height: 4px; + margin-right: 12px; + background: #595955; } +.nav-pill:hover { color: var(--white); background: #202020; } + .nav-pill[aria-current='page'] { - color: var(--accent-ink); - background: var(--accent); - border-color: var(--accent); + color: var(--white); + background: var(--blue); } +.nav-pill[aria-current='page']::before { background: var(--white); } + +.sidebar-footer { + display: grid; + gap: 16px; + padding-top: 16px; + border-top: 1px solid #333331; +} + +.sync-state { + display: flex; + align-items: center; + gap: 8px; + margin: 0; + color: #989894; + text-transform: none; + letter-spacing: 0; +} + +.sync-state span { + width: 6px; + height: 6px; + background: var(--green); + border-radius: 50%; +} + +.profile-block { + display: grid; + grid-template-columns: 32px minmax(0, 1fr); + gap: 10px; + align-items: center; +} + +.profile-avatar { + display: grid; + place-items: center; + width: 32px; + height: 32px; + color: var(--white); + background: #30302f; + font-family: var(--font-data); + font-size: 10px; +} + +.profile-block > span:last-child { display: grid; min-width: 0; } +.profile-block strong { overflow: hidden; font-size: 12px; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; } +.profile-block small { overflow: hidden; color: #777773; text-overflow: ellipsis; white-space: nowrap; } + +.sidebar-controls { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.mobile-header, +.mobile-nav { display: none; } + .app-main { - flex: 1; + min-width: 0; width: 100%; - max-width: 1180px; - margin: 0 auto; - padding: 20px 20px 56px; -} - -.app-footer { - padding: 16px 20px; - border-top: 1px solid var(--border); - color: var(--muted); - font-size: 13px; + padding: 40px 42px 64px; + overflow: hidden; } .page-header { display: flex; align-items: flex-end; justify-content: space-between; - gap: 16px; - flex-wrap: wrap; - margin-bottom: 18px; + gap: 24px; + min-height: 64px; + margin-bottom: 26px; } .page-title { margin: 0; - font-size: 26px; - line-height: 1.2; - letter-spacing: -0.01em; + font-size: clamp(28px, 3vw, 40px); + font-weight: 600; + line-height: 1; + letter-spacing: -0.035em; } .page-subtitle { - margin: 6px 0 0; + max-width: 68ch; + margin: 8px 0 0; color: var(--muted); -} - -.page-actions { - display: flex; - gap: 10px; - flex-wrap: wrap; -} - -.page-actions-row { - display: flex; - align-items: center; - gap: 10px; - flex-wrap: wrap; -} - -.section-title { - margin: 0 0 12px; - font-size: 17px; - border-left: 3px solid var(--accent); - padding-left: 10px; -} - -.card { - background: var(--surface); - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 18px; - margin-bottom: 18px; - box-shadow: var(--shadow); -} - -.card-danger { - border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); -} - -.stats { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); - gap: 12px; - margin: 0 0 18px; - padding: 0; -} - -.stat { - background: var(--surface); - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 12px 14px; - border-top: 3px solid var(--border-strong); -} - -.stat dt { - color: var(--muted); - font-size: 12.5px; - text-transform: uppercase; - letter-spacing: 0.06em; -} - -.stat dd { - margin: 6px 0 0; - font-size: 18px; - font-weight: 700; -} - -.stats-compact .stat { - padding: 8px 10px; -} - -.stats-compact .stat dd { - font-size: 15px; -} - -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; - padding: 8px 16px; - border-radius: var(--radius-sm); - border: 1px solid transparent; - font: inherit; - font-weight: 700; - cursor: pointer; - text-decoration: none; - transition: - filter 0.12s ease, - background-color 0.12s ease, - border-color 0.12s ease; -} - -.btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.btn-primary { - background: var(--accent); - color: var(--accent-ink); -} - -.btn-primary:hover:not(:disabled) { - filter: brightness(1.08); -} - -.btn-ghost { - background: transparent; - color: var(--muted); - border-color: var(--border); -} - -.btn-ghost:hover:not(:disabled) { - color: var(--text); - border-color: var(--border-strong); -} - -.btn-subtle { - background: var(--surface-2); - color: var(--text); - border-color: var(--border); -} - -.btn-subtle:hover:not(:disabled) { - border-color: var(--border-strong); -} - -.btn-danger { - background: var(--danger); - color: var(--danger-ink); -} - -.btn-danger:hover:not(:disabled) { - filter: brightness(1.06); -} - -.btn-small { - padding: 4px 10px; - font-size: 13px; -} - -.btn-icon { - padding: 4px 10px; - font-size: 16px; - line-height: 1; -} - -.badge { - display: inline-block; - padding: 2px 9px; - border-radius: 999px; - font-size: 12px; - font-weight: 700; - border: 1px solid; - margin-left: 6px; - vertical-align: middle; -} - -.badge-neutral { - color: var(--muted); - border-color: var(--border-strong); - background: rgba(157, 176, 201, 0.08); -} - -.badge-accent { - color: var(--accent); - border-color: color-mix(in srgb, var(--accent) 55%, transparent); - background: rgba(52, 211, 153, 0.1); -} - -.badge-warn { - color: var(--amber); - border-color: color-mix(in srgb, var(--amber) 55%, transparent); - background: rgba(251, 191, 36, 0.1); -} - -.badge-danger { - color: var(--danger); - border-color: color-mix(in srgb, var(--danger) 55%, transparent); - background: rgba(248, 113, 113, 0.1); -} - -.badge-info { - color: var(--info); - border-color: color-mix(in srgb, var(--info) 55%, transparent); - background: rgba(125, 211, 252, 0.1); -} - -.data-table { - width: 100%; - border-collapse: collapse; - background: var(--surface); - border: 1px solid var(--border); - border-radius: var(--radius); - overflow: hidden; font-size: 14px; } -.data-table thead th { - position: sticky; - top: 0; - background: var(--surface-2); - color: var(--muted); - text-align: left; - font-size: 12.5px; - text-transform: uppercase; - letter-spacing: 0.05em; - padding: 10px 12px; - border-bottom: 1px solid var(--border-strong); -} - -.data-table tbody th, -.data-table tbody td { - padding: 9px 12px; - border-bottom: 1px dashed var(--border); - text-align: left; - vertical-align: middle; -} - -.data-table tbody tr:last-child th, -.data-table tbody tr:last-child td { - border-bottom: none; -} - -.data-table tbody tr:hover { - background: rgba(125, 211, 252, 0.04); -} - -.data-table th[scope='row'] { - font-weight: 600; -} - -.data-table td.num, -.data-table th.num { - text-align: right; -} - -.data-table thead th.num { - text-align: right; -} - -tr[data-voided] th, -tr[data-voided] td { - opacity: 0.55; - text-decoration: line-through solid rgba(248, 113, 113, 0.5); -} - -tr[data-voided] td[data-label]:first-child, -tr[data-voided] .badge { - text-decoration: none; -} - -.mini-table { - width: 100%; - border-collapse: collapse; - font-size: 13.5px; - margin-top: 8px; -} - -.mini-table th, -.mini-table td { - padding: 6px 8px; - border-bottom: 1px dashed var(--border); - text-align: left; -} - -.mini-table th.num, -.mini-table td.num { - text-align: right; -} - -.filters { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); - gap: 10px 14px; - align-items: end; - background: var(--surface); - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 14px; - margin-bottom: 18px; -} - -.checkbox-field { - display: flex; - align-items: center; - gap: 8px; - padding-bottom: 8px; - font-weight: 600; - color: var(--muted); -} - -.checkbox-field input { - width: 16px; - height: 16px; - accent-color: var(--accent-strong); -} - -.inline-actions { - display: flex; - gap: 8px; - align-items: center; -} - -.pagination { - display: flex; - justify-content: flex-end; - gap: 10px; - margin-top: 14px; -} - -.form-grid { - display: grid; - gap: 14px; -} - -.field { - display: grid; - gap: 5px; -} - -.field-label { - font-weight: 700; - font-size: 13.5px; -} - -.field-hint { - margin: 0; - color: var(--muted); - font-size: 12.5px; -} - -.field-error { - margin: 0; - color: var(--danger); - font-size: 12.5px; - font-weight: 600; -} - -.input { - width: 100%; - padding: 8px 11px; - border-radius: var(--radius-sm); - border: 1px solid var(--border-strong); - background: var(--bg); - color: var(--text); - font: inherit; -} - -.input:focus-visible { - outline: 2px solid var(--info); - outline-offset: 1px; - border-color: var(--info); -} - -.input[aria-invalid='true'] { - border-color: var(--danger); -} - -.select { - appearance: auto; -} - -textarea.input { - resize: vertical; -} - -input[type='date'].input { - color-scheme: dark; -} - -input[type='file'].input { - padding: 6px; -} - -input[type='file']::file-selector-button { - margin-right: 10px; - border: 1px solid var(--border-strong); - background: var(--surface-2); - color: var(--text); - border-radius: var(--radius-sm); - padding: 5px 10px; - font: inherit; - cursor: pointer; -} - -.money-field { - position: relative; -} - -.money-field .input { - padding-right: 34px; -} - -.money-suffix { - position: absolute; - right: 10px; - top: 50%; - transform: translateY(-50%); - color: var(--muted); - pointer-events: none; -} - -.inline-label { - display: inline-flex; - align-items: center; - gap: 8px; - font-weight: 600; - color: var(--muted); -} - -.inline-label .select { - width: auto; -} - -.banner { - border: 1px solid; - border-radius: var(--radius); - padding: 12px 14px; - margin-bottom: 16px; -} - -.banner ul { - margin: 6px 0 0; - padding-left: 20px; -} - -.banner-danger { - border-color: color-mix(in srgb, var(--danger) 55%, transparent); - background: rgba(248, 113, 113, 0.09); - color: var(--danger); -} - -.banner-warn { - border-color: color-mix(in srgb, var(--amber) 55%, transparent); - background: rgba(251, 191, 36, 0.08); - color: var(--amber); -} - -.banner summary { - cursor: pointer; - font-weight: 700; -} - -.modal { - border: 1px solid var(--border-strong); - border-radius: var(--radius); - background: var(--surface); - color: var(--text); - padding: 0; - width: min(520px, calc(100vw - 32px)); - box-shadow: var(--shadow); -} - -.modal::backdrop { - background: rgba(4, 9, 20, 0.7); - backdrop-filter: blur(2px); -} - -.modal-head { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 14px 18px; - border-bottom: 1px solid var(--border); -} - -.modal-title { - margin: 0; - font-size: 17px; -} - -.modal-body { - padding: 18px; -} - -.modal-actions { - display: flex; - justify-content: flex-end; - gap: 10px; - margin-top: 14px; -} - -.confirm-body { - margin: 0 0 6px; -} - -.kind-tabs { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 16px; -} - -.month-switch { - display: inline-flex; - align-items: center; - gap: 8px; -} - -.month-label { - min-width: 150px; - text-align: center; - font-weight: 700; -} - -.steps { - display: flex; - flex-wrap: wrap; - gap: 8px; - list-style: none; - padding: 0; - margin: 0 0 18px; -} - -.step { - padding: 5px 12px; - border-radius: 999px; - border: 1px dashed var(--border-strong); - color: var(--muted); - font-size: 13px; - font-weight: 600; -} - -.step-done { - color: var(--accent); - border-style: solid; - border-color: color-mix(in srgb, var(--accent) 55%, transparent); -} - -.step-current { - color: var(--accent-ink); - background: var(--accent); - border-style: solid; - border-color: var(--accent); -} - -.chip-list { - list-style: none; - margin: 0; - padding: 0; - display: flex; - flex-wrap: wrap; - gap: 6px; -} - -.chip { - padding: 2px 8px; - border-radius: 999px; - background: rgba(251, 191, 36, 0.12); - border: 1px solid color-mix(in srgb, var(--amber) 50%, transparent); - color: var(--amber); - font-size: 12px; -} - -.kv { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); - gap: 12px; - margin: 0 0 12px; -} - -.kv dt { - color: var(--muted); - font-size: 12.5px; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.kv dd { - margin: 4px 0 0; - font-weight: 600; -} - -.chart-figure { - margin: 0; -} - +.page-actions, +.page-actions-row, +.inline-actions, +.pagination, +.kind-tabs, .chart-legend { display: flex; align-items: center; gap: 8px; - color: var(--muted); - font-size: 13px; - margin-bottom: 10px; + flex-wrap: wrap; } -.legend-dot { - width: 10px; - height: 10px; - border-radius: 3px; - display: inline-block; - margin-left: 10px; -} - -.legend-dot:first-child { - margin-left: 0; -} - -.dot-accent { - background: var(--accent); -} - -.dot-danger { - background: var(--danger); -} - -.dot-muted { - background: var(--border-strong); -} - -.hbars { - display: grid; - gap: 8px; -} - -.hbar-row { - display: grid; - grid-template-columns: minmax(90px, 34%) 1fr minmax(80px, auto); - align-items: center; - gap: 10px; -} - -.hbar-label { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-size: 13.5px; -} - -.hbar-track { +.section-heading { display: flex; - height: 14px; - border-radius: 4px; - background: rgba(125, 211, 252, 0.06); - border: 1px solid var(--border); - overflow: hidden; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 14px; } -.hbar-fill { - height: 100%; - border-radius: 3px; +.section-heading h2, +.section-title { + margin: 0; + font-size: 17px; + font-weight: 600; + letter-spacing: -0.015em; } -.fill-accent { - background: var(--accent); -} - -.fill-info { - background: var(--info); -} - -.fill-warn { - background: var(--amber); -} - -.fill-muted { - background: var(--border-strong); -} - -.fill-accent-overlay { - background: var(--accent); - opacity: 0.85; -} - -.hbar-value { - font-size: 13px; - color: var(--muted); - text-align: right; -} - -.column-chart { - width: 100%; - height: auto; - margin-bottom: 6px; -} - -.chart-baseline { - stroke: var(--border-strong); - stroke-width: 1.5; -} - -.bar-income { - fill: var(--accent); -} - -.bar-expense { - fill: var(--danger); -} - -.chart-label { - fill: var(--muted); +.section-heading > span { + color: var(--blue); + font-family: var(--font-data); font-size: 10px; -} - -.table-toggle { - margin-top: 12px; -} - -.table-toggle summary { - cursor: pointer; - color: var(--info); font-weight: 600; - font-size: 13.5px; + letter-spacing: 0.06em; + text-transform: uppercase; } -.analytics-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); - gap: 18px; +.section-title { + margin: 34px 0 14px; + padding-bottom: 10px; + border-bottom: 1px solid var(--ink); } -.analytics-grid .card { - margin-bottom: 0; -} - -.error-state { - border: 1px solid color-mix(in srgb, var(--danger) 50%, transparent); - background: rgba(248, 113, 113, 0.07); - color: var(--danger); - border-radius: var(--radius); - padding: 18px; - display: grid; - gap: 12px; - justify-items: start; - margin-bottom: 16px; -} - -.error-state-message { - margin: 0; - font-weight: 600; -} - -.empty-state { - border: 1px dashed var(--border-strong); - border-radius: var(--radius); - padding: 28px; - text-align: center; - color: var(--muted); - display: grid; - gap: 12px; - justify-items: center; - margin-bottom: 16px; -} - -.empty-state-title { - margin: 0; - font-weight: 700; -} - -.spinner-row { - display: flex; +.btn { + min-height: 38px; + display: inline-flex; align-items: center; - gap: 10px; - color: var(--muted); - padding: 18px 0; -} - -.spinner { - width: 18px; - height: 18px; - border-radius: 50%; - border: 2.5px solid var(--border-strong); - border-top-color: var(--accent); - animation: spin 0.9s linear infinite; -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -.toasts { - position: fixed; - right: 16px; - bottom: 16px; - display: grid; + justify-content: center; gap: 8px; - z-index: 100; - max-width: min(360px, calc(100vw - 32px)); + padding: 8px 14px; + border: 1px solid transparent; + border-radius: 0; + cursor: pointer; + font-family: var(--font-ui); + font-size: 13px; + font-weight: 600; + line-height: 1; + text-decoration: none; + transition: background-color 140ms ease, color 140ms ease, border-color 140ms ease; } -.toast { - padding: 10px 14px; - border-radius: var(--radius-sm); - border: 1px solid var(--border-strong); - background: var(--surface-2); - color: var(--text); - box-shadow: var(--shadow); - font-size: 14px; +.btn:disabled { cursor: not-allowed; opacity: 0.42; } +.btn-primary { color: var(--white); background: var(--blue); border-color: var(--blue); } +.btn-primary:hover:not(:disabled) { background: var(--blue-dark); border-color: var(--blue-dark); } +.btn-subtle { color: var(--ink); background: var(--white); border-color: var(--ink); } +.btn-subtle:hover:not(:disabled) { color: var(--white); background: var(--ink); } +.btn-ghost { color: inherit; background: transparent; border-color: transparent; } +.btn-ghost:hover:not(:disabled) { color: var(--white); background: #2b2b2b; } +.btn-danger { color: var(--white); background: var(--red); border-color: var(--red); } +.btn-danger:hover:not(:disabled) { background: #8e241d; } +.btn-small { min-height: 28px; padding: 5px 8px; font-family: var(--font-data); font-size: 9px; } +.btn-icon { width: 36px; min-height: 36px; padding: 0; } + +.lang-switch { display: inline-flex; } +.lang-switch .btn { color: #81817d; } +.lang-switch .is-active { color: var(--white); background: var(--blue); } + +.badge { + display: inline-flex; + align-items: center; + min-height: 22px; + margin-left: 6px; + padding: 4px 7px; + border: 0; + border-radius: 2px; + font-family: var(--font-data); + font-size: 9px; + font-weight: 700; + line-height: 1; + letter-spacing: 0.04em; + text-transform: uppercase; } -.toast-success { - border-color: color-mix(in srgb, var(--accent) 60%, transparent); +.badge-neutral { color: var(--ink); background: var(--paper-deep); } +.badge-accent { color: var(--green); background: var(--green-soft); } +.badge-warn { color: var(--amber); background: var(--amber-soft); } +.badge-danger { color: var(--red); background: var(--red-soft); } +.badge-info { color: var(--blue-dark); background: var(--blue-soft); } + +.stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + margin: 0 0 28px; + padding: 0; + color: var(--white); + background: var(--blue); } -.toast-error { - border-color: color-mix(in srgb, var(--danger) 60%, transparent); - background: rgba(61, 10, 10, 0.9); +.stat { + min-width: 0; + padding: 19px 20px 20px; + border-right: 1px solid #ffffff55; } -.toast-info { - border-color: color-mix(in srgb, var(--info) 60%, transparent); +.stat:last-child { border-right: 0; } +.stat dt { color: #d8e5ff; font-family: var(--font-data); font-size: 9px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; } +.stat dd { margin: 8px 0 0; color: var(--white); font-family: var(--font-data); font-size: clamp(17px, 2vw, 23px); font-weight: 600; } +.stat small { display: block; margin-top: 3px; color: #cadcff; font-size: 10px; } +.stats-compact { background: var(--ink); } +.stats-compact .stat { padding: 14px; } +.stats-compact .stat dd { font-size: 16px; } +.stats-compact .stat .pos { color: #87dbae; } +.stats-compact .stat .neg { color: #ff9a92; } + +.card { + margin: 0; + padding: 20px; + background: var(--white); + border: 1px solid var(--line); + border-radius: 0; + box-shadow: none; } +.card-danger { color: var(--red); background: var(--red-soft); border-color: var(--red); } + +.data-table, +.mini-table { + width: 100%; + border-collapse: collapse; + color: var(--ink); + background: var(--white); + font-size: 13px; +} + +.data-table { border: 1px solid var(--line); } +.data-table th, +.data-table td, +.mini-table th, +.mini-table td { text-align: left; vertical-align: middle; } +.data-table thead th { padding: 10px 12px; color: var(--muted); background: var(--paper-deep); border-bottom: 1px solid var(--ink); font-family: var(--font-data); font-size: 9px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; } +.data-table tbody th, +.data-table tbody td { padding: 12px; border-bottom: 1px solid var(--line); } +.data-table tbody tr:last-child > * { border-bottom: 0; } +.data-table tbody tr:hover { background: #f0f4ff; } +.data-table th[scope='row'] { font-weight: 500; } +.data-table .num, +.mini-table .num { text-align: right; } +.data-table a { color: var(--ink); font-weight: 600; } +.mini-table { font-size: 12px; } +.mini-table th, +.mini-table td { padding: 9px 8px; border-bottom: 1px solid var(--line); } + +tr[data-voided] > * { color: #989894; text-decoration: line-through; } +tr[data-voided] .badge { text-decoration: none; } + +.filters { + display: grid; + grid-template-columns: minmax(220px, 1.8fr) repeat(3, minmax(120px, 0.7fr)); + gap: 0; + margin: 0 0 18px; + background: var(--white); + border: 1px solid var(--line); +} + +.filters .field { border-right: 1px solid var(--line); } +.filters .field:nth-of-type(n + 5), +.filters .checkbox-field { border-top: 1px solid var(--line); } +.filters .field-label { padding: 7px 10px 0; } +.filters .input { border: 0; } +.filters .checkbox-field { margin: 0; padding: 10px; } + +.field { display: grid; gap: 6px; } +.form-grid { display: grid; gap: 16px; } +.field-label { font-family: var(--font-data); font-size: 9px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; } +.field-hint, +.field-error { margin: 0; font-size: 11px; } +.field-hint { color: var(--muted); } +.field-error { color: var(--red); font-weight: 600; } + +.input { + width: 100%; + min-height: 44px; + padding: 10px 12px; + color: var(--ink); + background: var(--white); + border: 1px solid var(--line); + border-radius: 0; +} + +.input:hover { border-color: #a5a29a; } +.input:focus-visible { border-color: var(--blue); outline: 2px solid var(--blue); outline-offset: -2px; } +.input[aria-invalid='true'] { border-color: var(--red); background: var(--red-soft); } +.select { appearance: auto; } +textarea.input { min-height: 84px; resize: vertical; } +input[type='file'].input { padding: 7px; } +input[type='file']::file-selector-button { min-height: 30px; margin-right: 10px; padding: 5px 10px; color: var(--white); background: var(--ink); border: 0; cursor: pointer; } + +.money-field { position: relative; } +.money-field .input { padding-right: 36px; font-family: var(--font-data); font-size: 18px; } +.money-suffix { position: absolute; right: 12px; top: 50%; color: var(--muted); transform: translateY(-50%); pointer-events: none; } +.checkbox-field { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 13px; } +.checkbox-field input { width: 16px; height: 16px; accent-color: var(--blue); } +.inline-label { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-family: var(--font-data); font-size: 10px; text-transform: uppercase; } +.inline-label .select { width: auto; min-height: 38px; } + +.pagination { justify-content: flex-end; margin-top: 14px; } + +.banner { + margin: 0 0 16px; + padding: 12px 14px; + border: 1px solid; + font-size: 13px; +} + +.banner ul { margin: 8px 0 0; padding-left: 18px; } +.banner-danger { color: var(--red); background: var(--red-soft); border-color: #e7a49e; } +.banner-warn { color: var(--amber); background: var(--amber-soft); border-color: #e5c16a; } +.banner-success { color: var(--green); background: var(--green-soft); border-color: #82c7a1; } +.banner summary { cursor: pointer; font-weight: 600; } + +.modal { + width: min(430px, 100vw); + max-width: none; + height: 100dvh; + max-height: none; + margin: 0 0 0 auto; + padding: 0; + color: var(--white); + background: var(--ink); + border: 0; + border-radius: 0; + box-shadow: -18px 0 40px rgba(0, 0, 0, 0.2); +} + +.modal::backdrop { background: rgba(22, 22, 22, 0.56); } +.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 22px 24px; border-bottom: 1px solid #3a3a38; } +.modal-title { margin: 0; font-size: 18px; font-weight: 600; } +.modal-body { padding: 24px; } +.modal .field-label { color: #9d9d98; } +.modal .field-hint { color: #858580; } +.modal .input { color: var(--white); background: #1d1d1d; border-color: #3d3d3a; } +.modal .input:focus-visible { border-color: var(--blue); } +.modal .money-field .input { min-height: 64px; font-size: 28px; } +.modal .muted { color: #9d9d98; } +.modal .btn-primary { width: 100%; min-height: 48px; } +.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; } +.confirm-body { margin: 0; } +.kind-tabs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; margin-bottom: 24px; border: 1px solid #3d3d3a; } +.kind-tabs .btn { min-width: 0; padding-inline: 6px; color: #858580; border: 0; border-right: 1px solid #3d3d3a; font-family: var(--font-data); font-size: 8px; } +.kind-tabs .btn:last-child { border-right: 0; } +.kind-tabs .btn-primary { width: auto; min-height: 38px; color: var(--white); background: var(--blue); } + +.month-switch { display: inline-flex; align-items: center; } +.month-label { min-width: 145px; text-align: center; font-family: var(--font-data); font-size: 11px; font-weight: 600; } + +.steps { + display: grid; + grid-template-columns: repeat(5, 1fr); + margin: 0 0 22px; + padding: 0; + list-style: none; + border: 1px solid var(--line); +} + +.step { padding: 10px; color: var(--muted); border-right: 1px solid var(--line); font-family: var(--font-data); font-size: 9px; text-align: center; } +.step:last-child { border-right: 0; } +.step-done { color: var(--green); background: var(--green-soft); } +.step-current { color: var(--white); background: var(--blue); } + +.chip-list { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; padding: 0; list-style: none; } +.chip { padding: 3px 6px; color: var(--amber); background: var(--amber-soft); font-family: var(--font-data); font-size: 9px; } + +.kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0; margin: 0; border-top: 1px solid var(--line); border-left: 1px solid var(--line); } +.kv > div { padding: 14px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); } +.kv dt { color: var(--muted); font-family: var(--font-data); font-size: 9px; letter-spacing: 0.06em; text-transform: uppercase; } +.kv dd { margin: 6px 0 0; font-weight: 500; } + +.analytics-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); } +.analytics-grid .card { min-width: 0; border-width: 0 1px 1px 0; } +.analytics-grid .section-title { margin-top: 0; } +.chart-figure { margin: 0; } +.chart-legend { margin: 0 0 12px; color: var(--muted); font-size: 11px; } +.legend-dot { width: 8px; height: 8px; display: inline-block; } +.dot-accent { background: var(--blue); } +.dot-danger { background: var(--red); } +.dot-muted { background: #a8a7a2; } +.hbars { display: grid; gap: 13px; } +.hbar-row { display: grid; grid-template-columns: minmax(80px, 28%) minmax(80px, 1fr) minmax(80px, auto); align-items: center; gap: 10px; } +.hbar-label { overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; } +.hbar-track { display: flex; height: 4px; overflow: hidden; background: var(--paper-deep); } +.hbar-track-stacked { position: relative; } +.hbar-track-stacked .hbar-fill { position: absolute; inset-block: 0; left: 0; } +.hbar-fill { display: block; height: 100%; } +.fill-accent, +.fill-accent-overlay { background: var(--blue); } +.fill-info { background: var(--green); } +.fill-warn { background: var(--amber); } +.fill-muted { background: #a8a7a2; } +.hbar-value { color: var(--ink); font-size: 11px; text-align: right; } +.column-chart { width: 100%; height: auto; } +.chart-baseline { stroke: var(--line); } +.bar-income { fill: var(--blue); } +.bar-expense { fill: var(--red); } +.chart-label { fill: var(--muted); font: 9px var(--font-data); } +.table-toggle { margin-top: 16px; } +.table-toggle summary { color: var(--blue); cursor: pointer; font-size: 12px; } + +.empty-state, +.error-state { display: grid; gap: 12px; justify-items: start; margin: 0 0 16px; padding: 24px; border: 1px solid var(--line); } +.empty-state { color: var(--muted); background: var(--white); border-style: dashed; } +.error-state { color: var(--red); background: var(--red-soft); border-color: var(--red); } +.empty-state-title, +.error-state-message { margin: 0; font-weight: 600; } + +.spinner-row, +.center-page { display: grid; place-items: center; gap: 12px; min-height: 120px; color: var(--muted); } +.center-page { min-height: 100vh; } +.spinner { width: 22px; height: 22px; border: 2px solid var(--line); border-top-color: var(--blue); border-radius: 50%; animation: spin 800ms linear infinite; } +@keyframes spin { to { transform: rotate(360deg); } } + +.toasts { position: fixed; right: 18px; bottom: 18px; z-index: 300; display: grid; gap: 8px; width: min(360px, calc(100vw - 36px)); } +.toast { padding: 12px 14px; color: var(--white); background: var(--ink); border: 1px solid var(--line-dark); font-size: 13px; } +.toast-success { border-color: var(--green); } +.toast-error { border-color: var(--red); } +.toast-info { border-color: var(--blue); } + +.overview-page .page-header { margin-bottom: 20px; } +.mobile-pool { display: none; } +.overview-workbench { display: grid; grid-template-columns: minmax(0, 1.75fr) minmax(260px, 0.75fr); gap: 16px; margin-bottom: 28px; } +.month-story { padding: 18px 0 0; } +.story-list { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--line); } +.story-list li { display: flex; justify-content: space-between; gap: 20px; padding: 14px 4px; border-bottom: 1px solid var(--line); } +.story-list li span { font-size: 13px; } +.story-list li strong { font-size: 12px; font-weight: 600; } +.decision-panel { padding: 20px; color: var(--white); background: var(--ink); } +.decision-panel .section-heading { padding-bottom: 12px; border-bottom: 1px solid #3b3b38; } +.decision-panel ul { margin: 0 0 18px; padding: 0; list-style: none; } +.decision-panel li { padding: 10px 0; color: #d5d5d1; border-bottom: 1px solid #323230; font-size: 12px; } +.decision-panel p { color: #b9b9b5; font-size: 12px; } +.decision-panel .btn { width: 100%; color: #a8a8a3; background: #2e2e2c; border: 0; } +.category-pulse { padding-top: 4px; } +.pulse-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); } +.pulse-item { display: grid; grid-template-columns: 1fr auto; gap: 5px 12px; min-width: 0; padding: 16px; background: var(--white); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); } +.pulse-item > span:first-child { overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; } +.pulse-item strong { font-size: 11px; } +.pulse-item small { color: var(--muted); font-family: var(--font-data); font-size: 8px; } +.pulse-track { grid-column: 1 / -1; height: 3px; margin-top: 4px; background: var(--paper-deep); } +.pulse-track span { display: block; height: 100%; background: var(--blue); } +.mobile-primary-action { display: none; } + .auth-page { min-height: 100vh; display: grid; place-items: center; - padding: 24px; + padding: 34px; + background: linear-gradient(90deg, var(--ink) 0 39%, var(--paper) 39% 100%); } .auth-card { - width: min(420px, 100%); + width: min(560px, calc(61vw - 96px)); + margin-left: 39vw; + padding: 34px 0; } -.auth-top { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - margin-bottom: 18px; -} - -.auth-alt { - margin: 16px 0 0; - color: var(--muted); -} - -.auth-alt a { - color: var(--info); -} - -.center-page { - min-height: 100vh; +.auth-card::before { + content: 'FS'; + position: fixed; + left: 56px; + top: 54px; display: grid; - place-content: center; - justify-items: center; - gap: 16px; - padding: 24px; + place-items: center; + width: 40px; + height: 40px; + color: var(--white); + background: var(--blue); + font: 700 11px var(--font-data); } -@media (max-width: 880px) { - .data-table thead { - display: none; - } +.auth-card::after { + content: 'Your household ledger, sealed by design.'; + position: fixed; + left: 56px; + top: 150px; + width: min(31vw, 410px); + color: var(--white); + font-size: clamp(34px, 4vw, 52px); + font-weight: 600; + line-height: 0.98; + letter-spacing: -0.035em; +} +.auth-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 44px; } +.auth-top .brand { color: var(--blue); } +.auth-top .brand-mark { display: none; } +.auth-card .page-title { font-size: 38px; } +.auth-card .page-subtitle { margin-bottom: 28px; } +.auth-card .form-grid { margin-top: 22px; } +.auth-card .btn-primary { width: 100%; min-height: 48px; } +.auth-alt { margin: 16px 0 0; color: var(--muted); font-size: 13px; } + +@media (max-width: 1120px) { + :root { --sidebar: 214px; } + .app-sidebar { padding-inline: 18px; } + .app-main { padding-inline: 28px; } + .filters { grid-template-columns: repeat(3, minmax(0, 1fr)); } + .filters .field { border-top: 1px solid var(--line); } + .pulse-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } +} + +@media (max-width: 760px) { + body { font-size: 14px; } + .app-shell { display: block; min-height: 100dvh; } + .app-sidebar { display: none; } + .mobile-header { + position: sticky; + top: 0; + z-index: 40; + display: flex; + align-items: center; + justify-content: space-between; + min-height: 58px; + padding: 10px 14px; + color: var(--white); + background: var(--ink); + } + .mobile-header .brand-mark { width: 28px; height: 28px; } + .mobile-nav { + position: fixed; + inset: auto 0 0; + z-index: 50; + display: grid; + grid-template-columns: repeat(5, 1fr); + min-height: 62px; + background: var(--white); + border-top: 1px solid var(--line); + } + .mobile-nav a { position: relative; display: grid; place-items: center; padding: 11px 3px 8px; color: var(--muted); font-family: var(--font-data); font-size: 8px; text-align: center; text-decoration: none; text-transform: uppercase; } + .mobile-nav a::before { content: ''; position: absolute; top: -1px; left: 28%; right: 28%; height: 2px; background: transparent; } + .mobile-nav a[aria-current='page'] { color: var(--blue); } + .mobile-nav a[aria-current='page']::before { background: var(--blue); } + .app-main { padding: 22px 14px 88px; overflow: visible; } + .page-header { align-items: flex-start; min-height: 0; margin-bottom: 20px; } + .page-title { font-size: 27px; } + .page-subtitle { font-size: 12px; } + .page-actions { justify-content: flex-end; } + .page-actions-row { justify-content: flex-end; } + .page-actions .btn { min-height: 34px; padding-inline: 10px; font-size: 11px; } + .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-inline: -14px; } + .stat { padding: 14px 10px; } + .stat:nth-child(n + 4) { display: none; } + .stat dt { font-size: 7px; } + .stat dd { font-size: 12px; } + .stat small { display: none; } + .overview-page .page-header { display: none; } + .mobile-pool { display: grid; gap: 3px; margin: -22px -14px 0; padding: 22px 14px 20px; color: var(--white); background: var(--ink); } + .mobile-pool span, + .mobile-pool small { color: #a9a9a4; font-family: var(--font-data); font-size: 8px; text-transform: uppercase; } + .mobile-pool strong { margin: 4px 0; font-size: 28px; } + .overview-stats .stat:first-child { display: none; } + .overview-workbench { display: block; margin-top: 20px; } + .month-story { display: none; } + .decision-panel { margin-bottom: 24px; padding: 14px; color: var(--ink); background: var(--amber-soft); } + .decision-panel .section-heading { border-color: #d4ad52; } + .decision-panel .section-heading h2, + .decision-panel p, + .decision-panel li { color: var(--ink); } + .decision-panel li { border-color: #e0c57f; } + .decision-panel .btn { color: var(--ink); background: transparent; border: 1px solid var(--ink); } + .pulse-grid { display: block; border: 0; } + .pulse-item { padding: 13px 0; border-width: 0 0 1px; background: transparent; } + .mobile-primary-action { position: fixed; right: 12px; bottom: 72px; z-index: 45; display: block; } + .mobile-primary-action .btn { width: 48px; height: 48px; padding: 0; overflow: hidden; color: transparent; } + .mobile-primary-action .btn::after { content: '+'; color: var(--white); font: 500 25px var(--font-ui); } + .filters { grid-template-columns: 1fr 1fr; } + .filters .field:first-child { grid-column: 1 / -1; } + .filters .checkbox-field { grid-column: 1 / -1; } + .data-table thead { display: none; } .data-table, .data-table tbody, .data-table tr, .data-table th, - .data-table td { - display: block; - width: 100%; - } - - .data-table { - background: transparent; - border: none; - } - - .data-table tbody tr { - background: var(--surface); - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 10px 12px; - margin-bottom: 12px; - box-shadow: var(--shadow); - } - + .data-table td { display: block; width: 100%; } + .data-table { background: transparent; border: 0; } + .data-table tbody tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; padding: 11px 0; border-bottom: 1px solid var(--line); } .data-table tbody th, - .data-table tbody td { - display: flex; - justify-content: space-between; - align-items: center; - gap: 12px; - padding: 5px 0; - border-bottom: 1px dashed var(--border); - } - - .data-table tbody th, - .data-table tbody td { - text-align: left; - } - - .data-table td.num { - text-align: right; - } - - .data-table tbody tr th:last-child, - .data-table tbody tr td:last-child { - border-bottom: none; - } - + .data-table tbody td { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; padding: 5px 0; border: 0; } + .data-table tbody th { grid-column: 1 / -1; font-size: 14px; } + .data-table tbody td { font-size: 11px; } .data-table tbody th::before, - .data-table tbody td::before { - content: attr(data-label); - color: var(--muted); - font-weight: 700; - font-size: 12px; - text-transform: uppercase; - letter-spacing: 0.05em; - flex-shrink: 0; - } - - .data-table tbody th[scope='row']::before { - content: attr(data-label); - } - - .data-table tbody td .btn, - .data-table tbody td .inline-actions { - width: 100%; - justify-content: flex-end; - } - - .page-title { - font-size: 21px; - } - - .app-main { - padding: 16px 14px 48px; - } - - .app-nav { - padding: 10px 14px 0; - } - - .hbar-row { - grid-template-columns: minmax(70px, 40%) 1fr minmax(70px, auto); - } + .data-table tbody td::before { content: attr(data-label); flex-shrink: 0; color: var(--muted); font-family: var(--font-data); font-size: 7px; letter-spacing: 0.05em; text-transform: uppercase; } + .data-table tbody th::before { display: none; } + .data-table tbody td:nth-child(even) { justify-content: flex-start; } + .data-table tbody td:nth-child(odd) { justify-content: flex-end; text-align: right; } + .data-table tbody td:last-child { grid-column: 1 / -1; justify-content: flex-end; } + .data-table tbody td .inline-actions { width: 100%; } + .analytics-grid { display: block; border: 0; } + .analytics-grid .card { padding: 20px 0; border-width: 0 0 1px; background: transparent; } + .hbar-row { grid-template-columns: minmax(70px, 34%) 1fr minmax(64px, auto); } + .steps { overflow-x: auto; grid-template-columns: repeat(5, minmax(100px, 1fr)); } + .kv { grid-template-columns: 1fr 1fr; } + .modal { width: 100vw; } + .modal-head { padding: 18px 16px; } + .modal-body { padding: 18px 16px 90px; } + .auth-page { display: block; padding: 0; background: var(--paper); } + .auth-card { width: 100%; min-height: 100vh; margin: 0; padding: 96px 20px 40px; } + .auth-card::before { position: absolute; left: 20px; top: 24px; } + .auth-card::after { display: none; } + .auth-top { margin-bottom: 34px; } + .auth-card .page-title { font-size: 32px; } } @media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } - - .spinner { - animation: none; - border-top-color: var(--accent); - } + html { scroll-behavior: auto; } + *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } + .spinner { animation: none; } }