/*
 * CertainGravity: the one stylesheet for the public pages and the app.
 * Every value comes from docs/design.md. Mobile first: base styles are the
 * phone layout; min-width queries at 640px, 960px and 1280px only.
 */

/* ----- Tokens (docs/design.md §2 and §4) ----- */

:root {
    --bg: #FFFFFF;
    --surface: #F5F7FB;
    --surface-raised: #FFFFFF;
    --line: #E3E8F0;
    --line-subtle: #EEF1F6;
    --control-border: #8590A3;
    --ink: #18202B;
    --ink-secondary: #3E4756;
    --ink-muted: #5A6474;
    --accent: #2B55D9;
    --accent-hover: #1E3FA8;
    --on-accent: #FFFFFF;
    --accent-soft: #EAF0FE;
    --accent-soft-ink: #1E3FA8;
    --accent-ring: #9DB4F2;
    --track: #E4E9F2;
    --thumb: #FFFFFF;
    --chip-neutral: #EEF0F3;
    --band: #18202B;
    --band-ink: #FFFFFF;
    --band-muted: #C9D3E3;
    --danger: #B42318;
    --danger-soft: #FDECEA;
    --success: #1D7A4A;

    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    --space-7: 48px;
    --space-8: 72px;

    --radius-sm: 10px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --radius-xl: 20px;
    --radius-pill: 999px;

    --shadow-thumb: 0 1px 2px rgba(24, 32, 43, 0.12);

    --font: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0F141B;
        --surface: #161D27;
        --surface-raised: #1C2431;
        --line: #2A3442;
        --line-subtle: #222B38;
        --control-border: #5D6B80;
        --ink: #E8EDF4;
        --ink-secondary: #C5CDD8;
        --ink-muted: #A3AEBE;
        --accent: #6E95FF;
        --accent-hover: #9CB6FF;
        --on-accent: #0F141B;
        --accent-soft: #1E2B4A;
        --accent-soft-ink: #BCD0FF;
        --accent-ring: #3B5BB5;
        --track: #222B38;
        --thumb: #364256;
        --chip-neutral: #26303D;
        --band: #1C2431;
        --band-ink: #E8EDF4;
        --band-muted: #A3AEBE;
        --danger: #FF8A80;
        --danger-soft: #3A1B1A;
        --success: #6FD3A0;

        --shadow-thumb: 0 1px 2px rgba(0, 0, 0, 0.4);
    }
}

/* ----- Font (docs/design.md §3) ----- */

@font-face {
    font-family: "Plus Jakarta Sans";
    src: url("/fonts/PlusJakartaSans-Variable.ttf") format("truetype");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
}

/* ----- Base ----- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font);
    font-size: 16px;
    line-height: 26px;
    font-weight: 400;
}

h1,
h2,
h3,
p,
ol,
ul {
    margin: 0;
}

a {
    color: var(--accent);
}

a:hover {
    color: var(--accent-hover);
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

code {
    font-family: var(--font);
    font-variant-numeric: tabular-nums;
}

/* ----- Type styles (docs/design.md §3) ----- */

.display {
    font-size: 40px;
    line-height: 44px;
    font-weight: 800;
    letter-spacing: -0.025em;
}

.title-1 {
    font-size: 34px;
    line-height: 40px;
    font-weight: 800;
    letter-spacing: -0.015em;
}

.title-2 {
    font-size: 28px;
    line-height: 34px;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.title-3 {
    font-size: 20px;
    line-height: 28px;
    font-weight: 700;
}

.body-lg {
    font-size: 18px;
    line-height: 30px;
}

.body-sm,
.hint {
    font-size: 14px;
    line-height: 20px;
}

.hint {
    color: var(--ink-muted);
}

.label {
    font-size: 15px;
    line-height: 20px;
    font-weight: 600;
}

.caption {
    font-size: 13px;
    line-height: 18px;
    font-weight: 500;
}

.eyebrow {
    font-size: 14px;
    line-height: 20px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.tabular {
    font-variant-numeric: tabular-nums;
}

/* ----- Logo (docs/design.md §5) ----- */

.mark {
    flex: none;
    color: var(--accent);
}

.logo {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: var(--ink);
    text-decoration: none;
}

.logo:hover {
    color: var(--ink);
}

.wordmark {
    font-size: 20px;
    line-height: 28px;
    font-weight: 800;
    letter-spacing: -0.01em;
}

/* ----- Buttons (docs/design.md §6) ----- */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: var(--space-3) var(--space-5);
    border: 1.5px solid transparent;
    border-radius: var(--radius-md);
    font-family: var(--font);
    font-size: 16px;
    line-height: 20px;
    font-weight: 700;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

.button-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}

.button-primary:hover,
.button-primary:active {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: var(--on-accent);
}

.button-secondary {
    background: var(--surface-raised);
    border-color: var(--control-border);
    color: var(--ink);
}

.button-secondary:hover {
    color: var(--ink);
}

.button-icon,
.button-menu {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 44px;
    height: 44px;
    padding: 0;
    background: var(--surface-raised);
    border: 1.5px solid var(--control-border);
    border-radius: var(--radius-md);
    color: var(--ink);
    cursor: pointer;
}

.button-menu {
    border-radius: var(--radius-sm);
}

.button-block {
    display: flex;
    width: 100%;
}

/* ----- Forms (docs/design.md §6) ----- */

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.input {
    width: 100%;
    height: 50px;
    padding: 0 var(--space-3);
    background: var(--surface-raised);
    border: 1.5px solid var(--control-border);
    border-radius: var(--radius-md);
    color: var(--ink);
    font-family: var(--font);
    font-size: 16px;
    line-height: 26px;
}

.input[aria-invalid="true"] {
    border-color: var(--danger);
}

.field-error {
    color: var(--danger);
    font-size: 14px;
    line-height: 20px;
}

.check {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: 44px;
}

.check input {
    flex: none;
    width: var(--space-5);
    height: var(--space-5);
    margin: 0;
    accent-color: var(--accent);
}

.check label {
    font-size: 15px;
    line-height: 20px;
    font-weight: 600;
}

/* ----- Notices: always in words (docs/design.md §2) ----- */

.notice {
    padding: var(--space-3) var(--space-4);
    border: 1px solid;
    border-radius: var(--radius-md);
    font-weight: 600;
}

.notice-error {
    background: var(--danger-soft);
    border-color: var(--danger);
    color: var(--danger);
}

.notice-success {
    background: var(--surface-raised);
    border-color: var(--success);
    color: var(--success);
}

/* A notice with a button and a line under its message ("Restore with these details"). */
.notice-stack {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
}

.notice-stack .body-sm {
    font-weight: 400;
}

/* ----- Codes shown for copying (setup key, setup link, recovery codes) ----- */

.code-block {
    padding: var(--space-3) var(--space-4);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    overflow-wrap: anywhere;
}

.code-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2) var(--space-5);
    padding: var(--space-3) var(--space-4) var(--space-3) var(--space-6);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    font-weight: 600;
}

/* ----- Public pages (docs/design.md §7) ----- */

.page-public {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background: var(--bg);
}

.container {
    width: 100%;
    max-width: 1120px;
    margin: 0 auto;
    padding-left: var(--space-4);
    padding-right: var(--space-4);
}

.site-main {
    flex: 1 0 auto;
}

/* A plain section: heading and text (the 404 page and the pages other than Home). */
.section {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
    padding-top: var(--space-7);
    padding-bottom: var(--space-7);
}

.section-pad {
    padding-top: var(--space-7);
    padding-bottom: var(--space-7);
}

.section-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.surface-section {
    background: var(--surface);
}

.text-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

/* Home hero: the ring art is shown from 640px. */
.hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: var(--space-6);
}

.hero-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
}

.hero-text .eyebrow {
    color: var(--accent);
}

.hero-text .body-lg,
.about-text .body-lg {
    color: var(--ink-secondary);
}

.actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-2);
}

.hero-art {
    display: none;
    width: 100%;
    max-width: 360px;
    height: auto;
}

.art-surface {
    fill: var(--surface);
}

.art-ring {
    fill: none;
    stroke: var(--accent-ring);
    stroke-width: 2;
}

.art-ring-fill {
    fill: var(--accent-ring);
}

.art-accent {
    fill: var(--accent);
}

.art-ink {
    fill: var(--ink);
}

/* Product cards (Home and Products). */
.product-cards {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-5);
    width: 100%;
    margin-top: var(--space-4);
    padding: 0;
    list-style: none;
}

.product-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
    padding: 28px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.product-card p {
    color: var(--ink-secondary);
}

.icon-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    background: var(--accent-soft);
    border-radius: var(--radius-md);
    color: var(--accent);
}

.icon-tile svg {
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Home "About CertainGravity": heading left, text right from 640px. */
.about {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
}

.about-text {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* Contact band. */
.contact-band {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-6) var(--space-5);
    background: var(--band);
    border-radius: var(--radius-xl);
    color: var(--band-ink);
}

.contact-band p {
    color: var(--band-muted);
}

.button-white {
    background: var(--band-ink);
    border-color: var(--band-ink);
    color: var(--band);
}

.button-white:hover {
    color: var(--band);
}

.site-header {
    border-bottom: 1px solid var(--line);
}

.site-header-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-4);
    padding-top: var(--space-3);
    padding-bottom: var(--space-3);
}

.site-nav,
.menu-list,
.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    padding: 0;
    list-style: none;
}

.nav-link {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--ink-secondary);
    font-size: 15px;
    line-height: 20px;
    font-weight: 600;
    text-decoration: none;
}

.nav-link:hover {
    color: var(--ink);
}

/* nav-current: a section whose sub-page is the current page, styled as current without aria-current. */
.nav-link[aria-current="page"],
.nav-link.nav-current {
    background: var(--accent-soft);
    color: var(--accent-soft-ink);
    font-weight: 700;
}

.site-footer {
    border-top: 1px solid var(--line);
    color: var(--ink-muted);
    font-size: 15px;
    line-height: 20px;
}

.site-footer-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2) var(--space-4);
    padding-top: var(--space-5);
    padding-bottom: var(--space-5);
}

.footer-links {
    gap: var(--space-4);
}

.footer-links a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--ink-muted);
}

/* ----- Sign-in and second-factor pages (docs/design.md §7) ----- */

.page-sign-in {
    background: var(--surface);
}

.sign-in {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-5);
    min-height: 100vh;
    padding: var(--space-7) var(--space-4);
}

.panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    width: 100%;
    max-width: 420px;
    padding: 28px 22px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-xl);
}

.sign-in-footer {
    margin-top: auto;
    color: var(--ink-muted);
}

/* ----- App pages (docs/design.md §7) ----- */

.page-app {
    background: var(--surface);
}

/* A link to a spot on the page and a focused field land below the sticky top bar: 64px and its 1px border. */
html:has(> .page-app) {
    scroll-padding-top: 65px;
}

/*
 * The app column: at most 1280px wide, centered, with the page's side padding
 * (16px, 24px from 640px, 32px from 960px). The top bar's contents and <main>
 * both use it, so the mark lines up with the page title. Content-box, so the
 * 1280px limit is on the content, not the padding.
 */
.app-column {
    box-sizing: content-box;
    max-width: 1280px;
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--space-4);
    padding-right: var(--space-4);
}

/*
 * The top bar on every app page: 64px tall, its contents in the app column and
 * vertically centered, so the 44px items keep 10px from its edges. Below 960px:
 * the mark, the page title and the menu button. From 960px: the logo, the menu,
 * "Signed in as" and Sign out. It stays at the top of the window, above the page content.
 */
.top-bar {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface-raised);
    border-bottom: 1px solid var(--line);
}

.top-bar-inner {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    height: 64px;
}

/* Below 960px the wordmark is kept for screen readers only, as the link's name. */
.top-bar .wordmark {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.top-bar-title {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 20px;
    line-height: 28px;
    font-weight: 800;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.top-nav,
.top-bar-user {
    display: none;
}

.top-menu {
    display: flex;
    gap: var(--space-1);
    padding: 0;
    list-style: none;
}

/* A section with sub-pages: its name and a chevron open the dropdown. */
.nav-button {
    gap: var(--space-1);
    background: transparent;
    border: 0;
    font-family: var(--font);
    cursor: pointer;
    anchor-name: --menu-item;
}

.top-menu > li {
    anchor-scope: --menu-item;
}

.signed-in {
    color: var(--ink-muted);
}

/* Sign out in the top bar is 44px tall, the tallest item in the bar, so it keeps 10px from the bar's edges. */
.top-bar-user .button {
    min-height: 44px;
    padding-top: 0;
    padding-bottom: 0;
}

/*
 * Popovers: a section's dropdown and the phone menu. Esc or a click outside
 * closes them; there is no dimming backdrop and no JavaScript.
 */
.dropdown,
.app-menu {
    position: fixed;
    inset: auto;
    margin: 0;
    padding: var(--space-2);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    color: var(--ink);
    overflow-y: auto;
}

/* Directly under the top bar (64px and its 1px border); lined up with its menu item where the browser supports anchor positioning. */
.dropdown {
    top: 65px;
    left: var(--space-6);
    min-width: 220px;
}

@supports (left: anchor(left)) {
    .dropdown {
        position-anchor: --menu-item;
        left: anchor(left);
    }
}

.dropdown-list,
.menu-sub {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: 0;
    list-style: none;
}

/* The phone menu: 260px wide, under the top bar at the right. */
.app-menu {
    top: 65px;
    right: var(--space-4);
    width: 260px;
    max-width: calc(100% - 2 * var(--space-4));
    max-height: calc(100% - 65px - var(--space-4));
}

.app-menu:popover-open {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.menu-list {
    flex-direction: column;
}

/* A section's sub-pages, indented 16px under it. */
.menu-sub {
    margin-top: var(--space-1);
    padding-left: var(--space-4);
}

.menu-foot {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3) var(--space-3);
    border-top: 1px solid var(--line-subtle);
}

.menu-foot .button {
    width: 100%;
}

/* The page content, in the app column: back link, page head, notices and cards share its left edge. */
.app-main {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding-top: var(--space-4);
    padding-bottom: var(--space-4);
}

/*
 * The content grid: a page's cards with 24px gaps, one per row below 960px.
 * From 960px the cards in a row share it evenly: halves, and thirds from
 * 1280px. A wrapping flex row, so the last row's cards grow to fill it and a
 * row never ends in an empty column. card-wide always takes the full width.
 */
.content-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
}

.content-grid > * {
    flex: 1 1 100%;
    min-width: 0;
}

.content-grid > .card-wide {
    flex-basis: 100%;
}

/* A short form in a card: fields, hints and errors at most 560px wide, in one column, buttons below. */
.short-form {
    max-width: 560px;
}

/*
 * A long form: one column, two from 640px, three from 1280px; Notes and the
 * buttons span it. It is also a card, so .card.form-grid outranks .card's
 * display and gap.
 */
.card.form-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-5);
}

.form-grid .field-wide,
.form-grid .form-actions {
    grid-column: 1 / -1;
}

.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-5);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}

.card .stack {
    width: 100%;
}

/* A notice about a card's form sits in that card and spans it. */
.card > .notice {
    align-self: stretch;
}

/* A list inside a card (Past backups on the Backup page) spans it. */
.card > .expense-cards,
.card > .table-box {
    align-self: stretch;
}

/* The sections page: one card per section, each a link to it, in the content grid. */
.section-cards {
    padding: 0;
    list-style: none;
}

.section-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
    height: 100%;
    padding: var(--space-5);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    color: var(--ink);
    text-decoration: none;
}

.section-card:hover {
    color: var(--ink);
}

.section-card p {
    color: var(--ink-secondary);
}

/* Page head with a caption, a chip by the title and actions right (docs/design.md §7). */
.page-head-text {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.page-head-title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
}

.page-head .caption {
    color: var(--ink-muted);
}

.page-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.icon {
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* "Back to <page>": label style, accent, a 24px left chevron. */
.back-link {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: var(--space-1);
    min-height: 44px;
    font-size: 15px;
    line-height: 20px;
    font-weight: 600;
    text-decoration: none;
}

.muted {
    color: var(--ink-muted);
}

/* ----- Chips (docs/design.md §6) ----- */

.chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* A chip that can't fit wraps, no wider than its container, with centered lines; in a table it never wraps (below). */
.chip {
    display: inline-block;
    max-width: 100%;
    padding: 3px 10px;
    border-radius: var(--radius-pill);
    font-size: 13px;
    line-height: 18px;
    font-weight: 600;
    text-align: center;
    overflow-wrap: anywhere;
}

.chip-type {
    background: var(--accent-soft);
    color: var(--accent-soft-ink);
}

.chip-neutral {
    background: var(--chip-neutral);
    color: var(--ink-secondary);
}

/* ----- Expense pages (docs/design.md §6 and §7) ----- */

/* Pill filter: options share the width below 640px; the track fits its content from 640px. */
.pill-filter {
    display: flex;
    padding: var(--space-1);
    background: var(--track);
    border-radius: var(--radius-pill);
}

.pill {
    flex: 1 1 0;
    min-height: 40px;
    padding: 0 var(--space-4);
    background: transparent;
    border: 0;
    border-radius: var(--radius-pill);
    color: var(--ink-secondary);
    font-family: var(--font);
    font-size: 14px;
    line-height: 20px;
    font-weight: 600;
    cursor: pointer;
}

.pill[aria-pressed="true"] {
    background: var(--thumb);
    box-shadow: var(--shadow-thumb);
    color: var(--ink);
    font-weight: 800;
}

/* Expense list: cards below 640px, a table from 640px. */
.expense-cards {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 0;
    list-style: none;
}

.expense-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-3) 14px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    color: var(--ink);
    text-decoration: none;
}

.expense-card:hover {
    color: var(--ink);
}

.expense-card-top {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
}

.expense-card-vendor {
    min-width: 0;
    font-weight: 700;
    overflow-wrap: anywhere;
}

.expense-card-amount {
    flex: none;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.expense-card-meta {
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 20px;
}

.table-box {
    display: none;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow-x: auto;
}

.expense-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
    line-height: 20px;
}

.expense-table th,
.expense-table td {
    padding: 14px var(--space-4);
    text-align: left;
    vertical-align: top;
}

.expense-table th {
    color: var(--ink-muted);
    font-size: 13px;
    line-height: 18px;
    font-weight: 700;
    white-space: nowrap;
}

.expense-table td {
    border-top: 1px solid var(--line-subtle);
}

.expense-table .num {
    text-align: right;
}

/* The column widens instead, and the table box scrolls sideways when needed. */
.expense-table .chip {
    max-width: none;
    white-space: nowrap;
}

.expense-table .num,
.expense-table .tabular {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.cell-note {
    display: block;
    color: var(--ink-muted);
}

.list-note {
    color: var(--ink-muted);
}

/* Fact list: a term above its value; two columns of pairs from 640px, three from 1280px; Notes spans them. */
.fact-list {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
    width: 100%;
    margin: 0;
}

.fact-list dt {
    color: var(--ink-muted);
    font-size: 13px;
    line-height: 18px;
    font-weight: 700;
}

.fact-list dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.fact-wide {
    grid-column: 1 / -1;
}

.fact-notes {
    white-space: pre-line;
}

.plain-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: 0;
    list-style: none;
}

/* History list: newest first, items divided by --line-subtle. */
.history-list,
.history-changes {
    width: 100%;
    padding: 0;
    list-style: none;
}

.history-list > li {
    padding: var(--space-3) 0;
    border-top: 1px solid var(--line-subtle);
}

.history-list > li:first-child {
    padding-top: 0;
    border-top: 0;
}

.history-time {
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 20px;
}

.history-changes li {
    overflow-wrap: anywhere;
}

/*
 * Manage page blocks (Types, payment methods; docs/design.md §6). List and
 * Archived rows are at least 52px tall: the name, its details in body-sm
 * --ink-muted, then the buttons at the right. Below 640px the buttons move
 * under the name and details; from 640px the row is one line.
 */
.manage-list {
    width: 100%;
    padding: 0;
    list-style: none;
}

.manage-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    min-height: 52px;
    padding: var(--space-2) 0;
    border-top: 1px solid var(--line-subtle);
}

.manage-row:first-child {
    border-top: 0;
}

.manage-name {
    min-width: 0;
    overflow-wrap: anywhere;
}

.manage-details {
    min-width: 0;
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 20px;
    overflow-wrap: anywhere;
}

.manage-actions {
    display: flex;
    gap: var(--space-2);
    margin-left: auto;
}

.manage-row .manage-actions {
    flex-basis: 100%;
    margin-left: 0;
}

/* Receipts card (docs/design.md §6): rows at least 52px tall, divided by --line-subtle. */
.receipt-list {
    width: 100%;
    padding: 0;
    list-style: none;
}

.receipt-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    min-height: 52px;
    padding: var(--space-2) 0;
    border-top: 1px solid var(--line-subtle);
}

.receipt-row:first-child {
    border-top: 0;
}

.receipt-name {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* A link that opens a new tab: its 16px new-tab icon follows the text. */
.new-tab .icon {
    margin-left: var(--space-1);
    vertical-align: -2px;
}

.receipt-meta {
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 20px;
}

/* Receipt count on list cards: a paperclip and the count, 13px --ink-muted. */
.receipt-count {
    display: inline-flex;
    align-items: center;
    color: var(--ink-muted);
    font-size: 13px;
    line-height: 18px;
    font-variant-numeric: tabular-nums;
}

/*
 * The receipt picker (docs/design.md §6): matches, search and upload under
 * label-style headings. Rows are receipt rows with a 24px checkbox first.
 * The upload fields use the long form's columns: one, two from 640px, three
 * from 1280px.
 */
.receipt-picker {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
    width: 100%;
    min-width: 0;
}

.receipt-picker > *,
.picker-part {
    width: 100%;
}

.picker-part {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* Below 640px "Also on <n> expenses" sits under the name, lined up with it (24px box + 12px gap). */
.picker-row .receipt-name {
    flex: 1 1 0;
}

.picker-also {
    flex-basis: 100%;
    padding-left: calc(var(--space-5) + var(--space-3));
}

.picker-empty {
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 20px;
}

.picker-search {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
}

.picker-search .field {
    width: 100%;
    max-width: 560px;
}

.picker-fields {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-5);
}

.picker-form {
    width: 100%;
}

/* Text for screen readers only. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Form fields beyond the plain text box (docs/design.md §6). */
.input-file {
    height: auto;
    min-height: 50px;
    padding: var(--space-2) var(--space-3);
}

.input-affix {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.affix {
    flex: none;
    font-weight: 600;
}

.input-affix .input {
    flex: 1 1 auto;
    min-width: 0;
}

.select-wrap {
    position: relative;
    display: block;
}

.select {
    padding-right: 44px;
    appearance: none;
}

.select-wrap .icon {
    position: absolute;
    top: 50%;
    right: var(--space-3);
    transform: translateY(-50%);
    color: var(--ink);
    pointer-events: none;
}

.textarea {
    height: auto;
    min-height: 120px;
    padding: var(--space-3);
    resize: vertical;
}

.choice-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

/* A fieldset's legend is not a flex item, so the 8px below it is its own margin (docs/design.md §6). */
.choice-group legend {
    margin-bottom: var(--space-2);
    padding: 0;
}

.choice-options {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-5);
}

/* A checkbox with its hints below its label, lined up with the label's text (24px box + 12px gap). */
.check-item > .hint {
    padding-left: calc(var(--space-5) + var(--space-3));
}

/* Role choice (docs/design.md §7): one role per row, two from 640px. */
.role-options {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2) var(--space-5);
}

/* Admin pages: a user card's name with its Disabled chip beside it. */
.user-card-name {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

/*
 * Permissions tree (docs/design.md §6): nested lists, each level indented 24px,
 * rows at least 44px tall divided by --line-subtle. A row is the chevron (or
 * its empty place on a leaf), then the label with its marker after an em dash
 * and the description below, in one column, so wrapped text always lines up
 * with the label; on read-only trees "Held" or "Not held" at the right.
 *
 * A branch is a <details> whose <summary> is the row; its entries follow it as
 * a list hidden while it is closed. The chevron points right when closed and
 * down when open; "<n> of <m> below" shows only while closed.
 */
.perm-tree,
.perm-tree ul {
    width: 100%;
    margin: 0;
    padding: 0;
    list-style: none;
}

.perm-tree ul {
    padding-left: var(--space-5);
}

.perm-tree li {
    border-top: 1px solid var(--line-subtle);
}

.perm-tree > li:first-child {
    border-top: 0;
}

.perm-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0 var(--space-3);
    min-height: 44px;
    padding: var(--space-2) 0;
}

summary.perm-row {
    list-style: none;
    cursor: pointer;
}

summary.perm-row::-webkit-details-marker {
    display: none;
}

.perm-chevron {
    flex: none;
    display: flex;
    align-items: center;
    width: var(--space-5);
    height: 20px;
    color: var(--ink);
}

.perm-branch[open] > summary .perm-chevron .icon {
    transform: rotate(90deg);
}

.perm-branch:not([open]) ~ ul {
    display: none;
}

.perm-branch[open] .perm-count {
    display: none;
}

.perm-main {
    flex: 1 1 0;
    min-width: 0;
}

.perm-text,
.perm-desc {
    display: block;
    line-height: 20px;
    overflow-wrap: anywhere;
}

.perm-text .label {
    color: var(--ink);
}

.perm-marker {
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 20px;
    font-weight: 400;
}

.perm-end,
.perm-count {
    flex: none;
    font-size: 13px;
    line-height: 20px;
    font-weight: 700;
}

/* Below 640px the count has a line of its own under the description, lined up with the label. */
.perm-count {
    flex-basis: 100%;
    padding-left: calc(var(--space-5) + var(--space-3));
}

.perm-count-sep {
    display: none;
}

.perm-heading {
    margin-top: var(--space-2);
}

/*
 * Editable trees: each item is a grid, the checkbox in the first column beside
 * the row (outside the summary), the row in the second. The checkbox's <label>
 * is its 44px touch target, centered on the label's line. Below 640px a row's
 * "Back to role" (a form button that looks like a link, because it posts) or
 * Clear sits under the row, lined up with the label; from 640px at the right.
 */
.perm-tree-edit li {
    display: grid;
    grid-template-columns: calc(var(--space-5) + var(--space-3)) minmax(0, 1fr);
    align-items: start;
}

.perm-box {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    align-items: center;
    height: 44px;
    /* Centered on the label's 20px line, which starts below the row's 8px padding. */
    margin-top: calc(var(--space-2) + (20px - 44px) / 2);
    cursor: pointer;
}

.perm-box input {
    flex: none;
    width: var(--space-5);
    height: var(--space-5);
    margin: 0;
    accent-color: var(--accent);
}

.perm-tree-edit li > .perm-row,
.perm-tree-edit li > .perm-branch {
    grid-column: 2;
    grid-row: 1;
    min-width: 0;
}

.perm-tree-edit li > .link-button,
.perm-tree-edit li > .button {
    grid-column: 2;
    grid-row: 2;
    justify-self: start;
    margin: 0 0 var(--space-2) calc(var(--space-5) + var(--space-3));
}

.perm-tree-edit li > ul {
    grid-column: 1 / -1;
    grid-row: 3;
}

.link-button {
    flex: none;
    min-height: 44px;
    padding: 0;
    background: none;
    border: 0;
    color: var(--accent);
    font-family: var(--font);
    font-size: 16px;
    line-height: 26px;
    text-decoration: underline;
    cursor: pointer;
}

.link-button:hover {
    color: var(--accent-hover);
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.notice a {
    color: inherit;
}

.refund-line,
.form-intro,
.perm-added {
    color: var(--ink-secondary);
}

/* ----- From 640px ----- */

@media (min-width: 640px) {
    .display {
        font-size: 56px;
        line-height: 60px;
    }

    .container {
        padding-left: var(--space-5);
        padding-right: var(--space-5);
    }

    .section,
    .section-pad {
        padding-top: var(--space-8);
        padding-bottom: var(--space-8);
    }

    .hero {
        grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    }

    .hero-art {
        display: block;
        justify-self: end;
    }

    .about {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: var(--space-6);
    }

    .contact-band {
        padding: var(--space-7);
    }

    .app-column {
        padding-left: var(--space-5);
        padding-right: var(--space-5);
    }

    .app-main {
        padding-top: var(--space-5);
        padding-bottom: var(--space-5);
    }

    .card.form-grid,
    .picker-fields {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .picker-row {
        flex-wrap: nowrap;
    }

    .picker-also {
        flex: none;
        padding-left: 0;
    }

    /* Search beside its field from 640px, as tall as the box; the field's label is visually hidden. */
    .picker-search {
        flex-direction: row;
    }

    .picker-search .field {
        flex: 0 1 560px;
    }

    .picker-search .button {
        flex: none;
        min-height: 50px;
    }

    .pill-filter {
        display: inline-flex;
    }

    .pill {
        flex: none;
    }

    .expense-cards {
        display: none;
    }

    .table-box {
        display: block;
    }

    .fact-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .manage-row {
        flex-wrap: nowrap;
    }

    .manage-row .manage-actions {
        flex: none;
        margin-left: auto;
    }

    .role-options {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .perm-row {
        flex-wrap: nowrap;
    }

    .perm-count {
        flex-basis: auto;
        padding-left: 0;
    }

    /* After "Held" or "Not held", the separator's own spaces stand in for the gap. */
    .perm-end + .perm-count {
        margin-left: calc(-1 * var(--space-3));
    }

    .perm-count-sep {
        display: inline;
    }

    .perm-tree-edit li {
        grid-template-columns: calc(var(--space-5) + var(--space-3)) minmax(0, 1fr) auto;
    }

    .perm-tree-edit li > .link-button,
    .perm-tree-edit li > .button {
        grid-column: 3;
        grid-row: 1;
        align-self: center;
        margin: 0 0 0 var(--space-3);
    }
}

/* ----- From 960px ----- */

@media (min-width: 960px) {
    .app-column {
        padding-left: var(--space-6);
        padding-right: var(--space-6);
    }

    .top-bar-inner {
        gap: var(--space-5);
    }

    .top-bar .wordmark {
        position: static;
        width: auto;
        height: auto;
        overflow: visible;
        clip-path: none;
    }

    .top-bar-title,
    .button-menu,
    .app-menu {
        display: none;
    }

    .top-nav {
        display: block;
    }

    .top-bar-user {
        display: flex;
        align-items: center;
        gap: var(--space-3);
        margin-left: auto;
    }

    .app-main {
        padding-top: var(--space-6);
        padding-bottom: var(--space-6);
    }

    .content-grid > * {
        flex-basis: calc((100% - var(--space-5)) / 2);
    }

    /*
     * The Add block from 960px: the fields and Add in one row. Labels and
     * legends are one 20px line with 8px below, so the controls (50px) share a
     * top edge; Add is pushed down by the same 28px and is 50px tall, so it
     * lines up with their bottom edge. Hints and errors sit under each field.
     */
    .short-form.manage-form {
        flex-direction: row;
        align-items: flex-start;
        max-width: none;
    }

    .manage-form > .field,
    .manage-form > .choice-group {
        flex: 0 1 auto;
        min-width: 0;
    }

    .manage-form > .field:has(> #f-name) {
        flex: 0 1 320px;
    }

    .manage-form #f-last4 {
        width: 120px;
    }

    /* The legend's own 8px margin sits above the buttons, as below 960px. */
    .manage-form .choice-options {
        align-items: center;
        min-height: 50px;
    }

    .manage-form .form-actions {
        flex: none;
        margin-top: calc(20px + var(--space-2));
    }

    .manage-form .form-actions .button {
        min-height: 50px;
    }

    .product-cards {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* ----- From 1280px ----- */

@media (min-width: 1280px) {
    .content-grid > * {
        flex-basis: calc((100% - 2 * var(--space-5)) / 3);
    }

    .card.form-grid,
    .picker-fields,
    .fact-list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
