/* ==========================================================================
   Sun City Birria — Finances
   assets/css/app.css

   TWO LAYOUTS, ONE STYLESHEET

   The phone is the real one. It is what gets used, standing at a till, one
   handed, installed to the home screen — so the phone layout is what the
   plain rules describe, and the desktop layout is the media query. Written
   the other way round, every phone rule ends up undoing a desktop rule and
   the small screen inherits whatever nobody remembered to override.

   The breakpoint is 900px. Below it: a bottom tab bar, one column, full-width
   controls. Above it: the same nav moved to a rail down the left, two columns
   where there is something worth putting beside something else.

   The colours are the inventory app's, deliberately — same family, same
   restaurant, and a token copied is a token that cannot drift.
   ========================================================================== */

:root {
    /* Brand */
    --navy:          #153143;
    --navy-700:      #1d4257;
    --navy-300:      #4a6c81;
    --teal:          #54AEA6;
    --teal-600:      #418983;
    --teal-700:      #31635f;
    --orange:        #E86F0D;
    --orange-700:    #C4600D;

    /* Neutrals */
    --white:         #ffffff;
    --gray-50:       #f7f8f9;
    --gray-100:      #eef0f2;
    --gray-200:      #e3e5e8;
    --gray-300:      #cdd2d7;
    --gray-400:      #a6aeb6;
    --gray-500:      #6b7680;
    --gray-600:      #4d565e;

    /* Semantic */
    --bg:            var(--gray-50);
    --surface:       var(--white);
    --border:        var(--gray-200);
    --border-strong: var(--gray-300);
    --text:          var(--navy);
    --text-muted:    var(--gray-500);
    --primary:       var(--teal-600);
    --primary-hover: var(--teal-700);
    --danger:        #c0392b;
    --danger-bg:     #fdecea;
    --success:       #1e7d5a;
    --success-bg:    #e6f4ee;
    --warning:       var(--orange);
    --warning-bg:    #fdf0e4;

    /* Money has a direction, and it should be readable without reading.
       Deliberately NOT plain red and green: eight per cent of men cannot tell
       those apart, and this is an app about numbers that must not be
       misread. The out colour is the brand orange, the in colour the brand
       teal — different in hue AND in lightness, so they survive both colour
       blindness and a phone in sunlight. */
    --out:           #b3540d;
    --out-bg:        #fdf2e7;
    --in:            #1e7d5a;
    --in-bg:         #e6f4ee;

    /* Spacing — 4px scale */
    --s1: 0.25rem;
    --s2: 0.5rem;
    --s3: 0.75rem;
    --s4: 1rem;
    --s5: 1.5rem;
    --s6: 2rem;
    --s7: 3rem;

    --radius:    10px;
    --radius-sm: 6px;
    --radius-lg: 16px;

    --shadow-sm: 0 1px 2px rgba(21, 49, 67, 0.06);
    --shadow:    0 2px 8px rgba(21, 49, 67, 0.08);
    --shadow-lg: 0 12px 32px rgba(21, 49, 67, 0.16);

    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
            "Helvetica Neue", Arial, sans-serif;
    /* Amounts are set in a tabular font so a column of them lines up on the
       decimal point. A proportional font makes $1,204.00 and $94.50 ragged,
       and a ragged column of money is one nobody scans. */
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

    /* The height the bottom bar occupies, so everything else can stay clear
       of it in one place rather than at nine. */
    --navbar-height: 3.75rem;

    /* Set per book by the tab that is showing, so the accent on the home page
       follows whichever book is open. */
    --book-accent: var(--teal-600);
}

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

html {
    /* Kills the double-tap zoom on iOS, which otherwise fires when somebody
       taps two buttons quickly — and on a screen of buttons, that is often. */
    touch-action: manipulation;
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: var(--font);
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    /* Room for the bottom bar plus the home indicator on a notched iPhone. */
    padding-bottom: calc(var(--navbar-height) + env(safe-area-inset-bottom, 0px));
    /* Stops the whole page rubber-banding under the fixed bar when a list is
       shorter than the screen. */
    overscroll-behavior-y: contain;
}

h1, h2, h3, h4 { margin: 0; font-weight: 650; line-height: 1.25; }
h1 { font-size: 1.375rem; }
h2 { font-size: 1.125rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 var(--s3); }
p:last-child { margin-bottom: 0; }

button, input, select, textarea { font: inherit; color: inherit; }
img, svg { max-width: 100%; }
svg { display: block; }

[hidden] { display: none !important; }

.muted   { color: var(--text-muted); }
.small   { font-size: 0.875rem; }
.tiny    { font-size: 0.8125rem; }
.grow    { flex: 1 1 auto; min-width: 0; }
.center  { text-align: center; }
.right   { text-align: right; }
.nowrap  { white-space: nowrap; }
.mb-2 { margin-bottom: var(--s2); }
.mb-3 { margin-bottom: var(--s3); }
.mb-4 { margin-bottom: var(--s4); }
.mt-3 { margin-top: var(--s3); }
.mt-4 { margin-top: var(--s4); }

/* Visible only to a screen reader. Used for the labels a sighted person reads
   from position and colour, which a screen reader cannot. */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */
.app-header {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: calc(var(--s3) + env(safe-area-inset-top, 0px)) var(--s4) var(--s3);
    background: var(--navy);
    color: var(--white);
    position: sticky;
    top: 0;
    z-index: 30;
}

.app-header__title {
    font-size: 1.0625rem;
    font-weight: 650;
    letter-spacing: 0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-header__logo { height: 1.75rem; width: auto; }

.app-header__actions { display: flex; align-items: center; gap: var(--s1); margin-left: auto; }

.icon-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    cursor: pointer;
}
.icon-btn svg { width: 1.375rem; height: 1.375rem; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.icon-btn:hover { background: rgba(255, 255, 255, 0.12); }
.icon-btn:active { background: rgba(255, 255, 255, 0.2); }

.icon-btn__badge {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    min-width: 1.125rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    background: var(--orange);
    color: var(--white);
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.125rem;
    text-align: center;
}

/* --------------------------------------------------------------------------
   Page shell
   -------------------------------------------------------------------------- */
.app-main {
    max-width: 42rem;
    margin: 0 auto;
    padding: var(--s4);
}

.page { display: none; }
.page.is-active { display: block; }

.page-head {
    display: flex;
    align-items: baseline;
    gap: var(--s3);
    margin-bottom: var(--s4);
}

/* --------------------------------------------------------------------------
   Bottom navigation — Home, Transactions, Settings
   -------------------------------------------------------------------------- */
.navbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    display: flex;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    /* Above the safe area on a notched phone, so the labels never sit under
       the home indicator. */
}

.navbar__item {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    min-height: var(--navbar-height);
    padding: var(--s2) var(--s1);
    border: 0;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
    /* No tap highlight rectangle on iOS — it makes a full-width tab flash as
       a grey block, which reads as a rendering fault. */
    -webkit-tap-highlight-color: transparent;
}

.navbar__item svg {
    width: 1.5rem;
    height: 1.5rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.navbar__item.is-active { color: var(--primary); }
.navbar__item.is-active svg { stroke-width: 2; }

.navbar__badge {
    position: absolute;
    top: 0.375rem;
    left: 50%;
    margin-left: 0.375rem;
    min-width: 1.125rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    background: var(--orange);
    color: var(--white);
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.125rem;
    text-align: center;
}

/* --------------------------------------------------------------------------
   Folder tabs — Personal on the left, Business on the right
   ...............................................................
   Drawn as actual folder tabs: rounded at the top only, and the active one
   sits ONE PIXEL over the panel below it so the two read as a single piece of
   card rather than a button above a box. That one pixel is the whole illusion
   — without it they are just buttons.
   -------------------------------------------------------------------------- */
.folders {
    display: flex;
    gap: var(--s1);
    padding: 0 var(--s2);
    margin-bottom: -1px;
    position: relative;
    z-index: 1;
}

.folder {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.125rem;
    padding: var(--s3) var(--s2) calc(var(--s3) + 1px);
    border: 1px solid var(--border);
    border-bottom: 1px solid transparent;
    border-radius: var(--radius) var(--radius) 0 0;
    background: var(--gray-100);
    color: var(--text-muted);
    font-weight: 650;
    font-size: 0.9375rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    /* Sits behind the active tab so the active one's edge overlaps it. */
    position: relative;
    top: 3px;
    transition: background 0.12s ease, top 0.12s ease;
}

.folder:hover { background: var(--gray-50); }

.folder.is-active {
    top: 0;
    background: var(--surface);
    color: var(--text);
    border-bottom-color: var(--surface);
    /* The book's own colour, as the strip along the top of its folder. */
    box-shadow: inset 0 3px 0 var(--book-accent);
}

.folder__amount {
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.folder-body {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 0 0 var(--radius) var(--radius);
    padding: var(--s4);
}

/* --------------------------------------------------------------------------
   Cards and panels
   -------------------------------------------------------------------------- */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

.card + .card { margin-top: var(--s4); }

.card__header {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border-bottom: 1px solid var(--border);
    background: var(--gray-50);
}

.card__body { padding: var(--s4); }

.stack > * + * { margin-top: var(--s4); }

.section-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    margin: var(--s5) 0 var(--s3);
    font-size: 0.8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   The three numbers at the top of a book
   -------------------------------------------------------------------------- */
.totals {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s2);
    margin-bottom: var(--s4);
}

.total {
    /* minmax(0, 1fr) above and this together are what stop the row running off
       the side of a 375px screen. Without both, each tile is sized by its
       CONTENT — a grid track's default minimum is auto, not zero — so
       "$1,289.40" in a monospace font forces the track wider than its third of
       the row and the last tile is pushed off the edge, where nothing on the
       page reveals it. */
    min-width: 0;
    /* Narrow side padding, because the width is needed by the number. Three
       tiles across a 375px screen leave about 93px of content each, and
       "$1,289.40" has to fit in that without being cut. */
    padding: var(--s3) var(--s1);
    border-radius: var(--radius);
    background: var(--gray-50);
    border: 1px solid var(--border);
    text-align: center;
}

.total__label {
    font-size: 0.625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    /* One line, always. A two-word label wrapping makes its tile taller than
       the two beside it and the row stops reading as a row. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.total__value {
    font-family: var(--font-mono);
    /* Shrinks with the viewport rather than wrapping. A wrapped amount is both
       taller and harder to read than a smaller one, and these three have to
       stay the same height to be compared at a glance.
       NO ELLIPSIS HERE, deliberately: a truncated label is a small annoyance,
       a truncated AMOUNT is a wrong number on screen. "$1,289.…" reads as a
       real figure and is not one. If a total ever outgrows its tile the text
       overflows visibly instead, which is ugly and obvious — which is the
       right way round for money. */
    font-size: clamp(0.75rem, 3.7vw, 1.25rem);
    font-weight: 700;
    letter-spacing: -0.04em;
    white-space: nowrap;
}

.total--out .total__value { color: var(--out); }
.total--in  .total__value { color: var(--in); }
.total--net.is-negative .total__value { color: var(--out); }
.total--net.is-positive .total__value { color: var(--in); }

/* --------------------------------------------------------------------------
   Where it went — a bar per category
   -------------------------------------------------------------------------- */
.bars { display: flex; flex-direction: column; gap: var(--s3); }

.bar__top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    margin-bottom: var(--s1);
}

.bar__name { font-weight: 600; font-size: 0.9375rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar__value { font-family: var(--font-mono); font-size: 0.875rem; font-weight: 600; white-space: nowrap; }

.bar__track {
    height: 0.5rem;
    border-radius: 999px;
    background: var(--gray-100);
    overflow: hidden;
}

.bar__fill {
    height: 100%;
    border-radius: 999px;
    background: var(--book-accent);
    /* A category with a rounding-error share still shows a sliver rather than
       nothing, so the row does not read as an empty track. */
    min-width: 3px;
}

.bar__fill--over { background: var(--danger); }
.bar__fill--warn { background: var(--warning); }

/* --------------------------------------------------------------------------
   Entry rows
   -------------------------------------------------------------------------- */
.entries { display: flex; flex-direction: column; }

.entry {
    display: flex;
    align-items: center;
    gap: var(--s3);
    width: 100%;
    padding: var(--s3) var(--s2);
    border: 0;
    border-bottom: 1px solid var(--border);
    background: transparent;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.entry:last-child { border-bottom: 0; }
.entry:hover { background: var(--gray-50); }

.entry__mark {
    flex: 0 0 auto;
    width: 0.25rem;
    align-self: stretch;
    min-height: 2.25rem;
    border-radius: 999px;
    background: var(--book-accent);
}

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

/* These are <span>s in the markup, and a span is inline — so without an
   explicit display they lay themselves out on ONE line, the payee and the
   meta text and the amount all running through each other, and
   text-overflow does nothing because an inline box has no width to overflow.
   Block is what makes the row two lines of text with an amount beside it. */
.entry__payee,
.entry__meta {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.entry__payee { font-weight: 600; }

.entry__meta {
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.entry__amount {
    display: block;
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-weight: 700;
    letter-spacing: -0.02em;
    white-space: nowrap;
    text-align: right;
}
.entry__amount--out { color: var(--out); }
.entry__amount--in  { color: var(--in); }

/* A split entry shows what it is worth in THIS book, with the whole receipt
   underneath in small type — so a $60 line never gets mistaken for a $100
   receipt or the other way round. */
.entry__whole { display: block; font-size: 0.75rem; font-weight: 500; color: var(--text-muted); text-align: right; }

.entry__flags { display: flex; gap: var(--s1); align-items: center; }

.pill {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.0625rem 0.4375rem;
    border-radius: 999px;
    background: var(--gray-100);
    color: var(--gray-600);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    white-space: nowrap;
}
.pill--warn  { background: var(--warning-bg); color: var(--orange-700); }
.pill--auto  { background: var(--gray-100); color: var(--gray-600); }
.pill--book  { background: var(--book-accent); color: var(--white); }
.pill svg { width: 0.75rem; height: 0.75rem; fill: none; stroke: currentColor; stroke-width: 2.2; }

/* --------------------------------------------------------------------------
   The swipe deck
   ...............................................................
   One card at a time, dragged left for Personal or right for Business. The
   two targets are painted UNDER the card and revealed as it moves, so the
   gesture explains itself the first time somebody's thumb wanders: the label
   appearing behind the card is what it is about to do.
   -------------------------------------------------------------------------- */
.deck {
    position: relative;
    /* Tall enough for the card plus the two below it in the stack. */
    min-height: 19rem;
    margin-bottom: var(--s4);
    /* The browser must not claim horizontal drags for its own back-gesture or
       for scrolling — pan-y leaves vertical scrolling alone and gives us the
       horizontal axis, which is the whole interaction. */
    touch-action: pan-y;
}

.deck__targets {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--s4);
    border-radius: var(--radius-lg);
    background: var(--gray-100);
    border: 2px dashed var(--border-strong);
}

.deck__target {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s1);
    font-weight: 700;
    font-size: 0.9375rem;
    color: var(--text-muted);
    opacity: 0.55;
    transition: opacity 0.1s ease, transform 0.1s ease;
}
.deck__target svg { width: 1.75rem; height: 1.75rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.deck__target.is-armed { opacity: 1; transform: scale(1.12); color: var(--primary); }

.deck__card {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    padding: var(--s5) var(--s4) var(--s4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    /* The card is dragged with a transform, so it never triggers layout while
       a finger is on it — on a phone that is the difference between a card
       that tracks the thumb and one that stutters behind it. */
    will-change: transform;
    user-select: none;
    -webkit-user-select: none;
    cursor: grab;
}
.deck__card.is-dragging { cursor: grabbing; transition: none; }
.deck__card.is-settling { transition: transform 0.22s cubic-bezier(0.2, 0, 0.2, 1), opacity 0.22s ease; }

/* The next two cards, peeking out below, so the pile has visible depth and
   "how many left" is felt rather than read. */
.deck__card--behind { box-shadow: var(--shadow); pointer-events: none; }

.deck__amount {
    font-family: var(--font-mono);
    font-size: 2.25rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin-bottom: var(--s1);
}
.deck__amount--out { color: var(--out); }
.deck__amount--in  { color: var(--in); }

.deck__payee { font-size: 1.25rem; font-weight: 650; margin-bottom: var(--s1); }
.deck__when  { color: var(--text-muted); font-size: 0.9375rem; margin-bottom: var(--s4); }

/* Why the app thinks what it thinks. The single most important thing on this
   card after the amount: a guess whose reasoning is invisible is one people
   stop trusting the first time it is wrong. */
.deck__reason {
    margin-top: auto;
    padding: var(--s3);
    border-radius: var(--radius);
    background: var(--gray-50);
    border: 1px solid var(--border);
    font-size: 0.875rem;
    line-height: 1.45;
}
.deck__reason--unsure { background: var(--warning-bg); border-color: #f3d9bd; }

.deck__guess {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-weight: 700;
    margin-bottom: 0.125rem;
}
.deck__dot { width: 0.625rem; height: 0.625rem; border-radius: 999px; background: var(--book-accent); flex: 0 0 auto; }

/* The stamp that slides in over the card as it is dragged past the point of
   no return — the same idea as the targets underneath, at the moment of
   commitment. */
.deck__stamp {
    position: absolute;
    top: var(--s5);
    padding: var(--s1) var(--s3);
    border: 3px solid currentColor;
    border-radius: var(--radius);
    font-size: 1.125rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0;
    pointer-events: none;
}
.deck__stamp--left  { left: var(--s4);  transform: rotate(-12deg); color: var(--teal-700); }
.deck__stamp--right { right: var(--s4); transform: rotate(12deg);  color: var(--navy-700); }

.deck__progress {
    text-align: center;
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-bottom: var(--s3);
}

/* --------------------------------------------------------------------------
   Segmented control — "To review" / "All"
   -------------------------------------------------------------------------- */
.segmented {
    display: flex;
    padding: 0.1875rem;
    border-radius: var(--radius);
    background: var(--gray-100);
    border: 1px solid var(--border);
    margin-bottom: var(--s4);
}

.segmented__option {
    flex: 1 1 0;
    padding: var(--s2) var(--s3);
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.875rem;
    font-weight: 650;
    cursor: pointer;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
}
.segmented__option.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s2);
    /* 44px minimum: the smallest thing a thumb hits reliably. */
    min-height: 2.75rem;
    padding: var(--s2) var(--s4);
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: var(--primary);
    color: var(--white);
    font-size: 0.9375rem;
    font-weight: 650;
    cursor: pointer;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}
.btn:hover { background: var(--primary-hover); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn svg { width: 1.125rem; height: 1.125rem; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

.btn--block { display: flex; width: 100%; }
.btn--secondary { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.btn--secondary:hover { background: var(--gray-50); }
.btn--ghost { background: transparent; color: var(--text-muted); }
.btn--ghost:hover { background: var(--gray-100); }
.btn--danger { background: var(--danger); }
.btn--danger:hover { background: #a5342a; }
.btn--link { background: none; border: 0; color: var(--primary); text-decoration: underline; min-height: auto; padding: var(--s1); }
.btn--lg { min-height: 3.25rem; font-size: 1rem; }
.btn--personal { background: var(--teal-600); }
.btn--business { background: var(--navy-700); }

.btn-row { display: flex; gap: var(--s3); flex-wrap: wrap; }
.btn-row--split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }

/* The two big buttons the app is used through.
   minmax(0, 1fr) for the same reason as the totals row: a track's default
   minimum is its content, so a long label makes the button wider than half
   the row and pushes the other one off the screen. */
.quick-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s3);
    margin-bottom: var(--s4);
}

/* A label too long for the button it is in shrinks rather than escaping it.
   The real labels are two words, but the Spanish ones are longer and a
   renamed one could be longer still. */
.quick-actions .btn,
.deck__actions .btn {
    min-width: 0;
    padding-left: var(--s2);
    padding-right: var(--s2);
    overflow: hidden;
}
.quick-actions .btn > span,
.deck__actions .btn { text-overflow: ellipsis; white-space: nowrap; }

.deck__actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */
.field { margin-bottom: var(--s4); }

.field__label {
    display: block;
    margin-bottom: var(--s1);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.field__hint { margin-top: var(--s1); font-size: 0.8125rem; color: var(--text-muted); }

.input, .select, .textarea {
    display: block;
    width: 100%;
    min-height: 2.75rem;
    padding: var(--s2) var(--s3);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    /* 16px exactly. Anything smaller and iOS Safari zooms the page in when
       the field is focused, and it does not zoom back out. */
    font-size: 1rem;
}
.input:focus, .select:focus, .textarea:focus {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: var(--primary);
}
.textarea { min-height: 5rem; resize: vertical; }

.select {
    appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7680' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--s3) center;
    background-size: 1.125rem;
    padding-right: var(--s6);
}

/* The amount field. Big, monospaced, and with the currency symbol drawn
   inside it — this is the field the app exists for and it should be the
   thing a thumb lands on without aiming. */
.amount-field { position: relative; }
.amount-field__symbol {
    position: absolute;
    left: var(--s3);
    top: 50%;
    transform: translateY(-50%);
    font-family: var(--font-mono);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-muted);
    pointer-events: none;
}
.amount-field .input {
    min-height: 3.5rem;
    padding-left: 2.25rem;
    font-family: var(--font-mono);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.checkbox {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    padding: var(--s2) 0;
    cursor: pointer;
}
.checkbox input { width: 1.25rem; height: 1.25rem; margin: 0.125rem 0 0; flex: 0 0 auto; accent-color: var(--primary); }

.switch-row {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s3) 0;
    border-bottom: 1px solid var(--border);
}
.switch-row:last-child { border-bottom: 0; }

/* --------------------------------------------------------------------------
   Split editor
   -------------------------------------------------------------------------- */
.split { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s3); margin-bottom: var(--s3); background: var(--gray-50); }
.split__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s2); }
.split__index { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }

.split-balance {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s3);
    border-radius: var(--radius);
    font-size: 0.875rem;
    font-weight: 650;
    margin-bottom: var(--s4);
}
.split-balance--ok    { background: var(--in-bg);     color: var(--in); }
.split-balance--short { background: var(--warning-bg); color: var(--orange-700); }
.split-balance--over  { background: var(--danger-bg);  color: var(--danger); }

/* --------------------------------------------------------------------------
   Counting cash

   Six rows, each a denomination with a minus, a number and a plus. The two
   buttons are the whole interaction, so they are the biggest things in the
   row — 3rem square, which is comfortably past the 44px a thumb needs, and
   far enough apart that hitting minus when you meant plus takes effort.
   -------------------------------------------------------------------------- */
.bill-row {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s2) 0;
    border-bottom: 1px solid var(--border);
}
.bill-row:last-of-type { border-bottom: 0; }

.bill-row__label {
    flex: 0 0 3.5rem;
    font-family: var(--font-mono);
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

/* What this row comes to. Sits between the denomination and the stepper and
   stays quiet until the count is above zero — six lines of "$0.00" is noise
   that makes the one row you have counted harder to find. */
.bill-row__subtotal {
    flex: 1 1 auto;
    min-width: 0;
    font-family: var(--font-mono);
    font-size: 0.875rem;
    color: var(--text-muted);
    text-align: right;
    white-space: nowrap;
}
.bill-row__subtotal.is-zero { opacity: 0; }

.stepper { display: flex; align-items: center; gap: var(--s1); flex: 0 0 auto; }

.stepper__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    /* Held down to add ten at a time — so a drawer with forty ones is not
       forty taps. Without this, text selection starts on a long press and the
       repeat looks like a stuck button. */
    user-select: none;
    -webkit-user-select: none;
}
.stepper__btn:active { background: var(--gray-100); }
.stepper__btn:disabled { opacity: 0.35; cursor: not-allowed; }
.stepper__btn--plus { border-color: var(--primary); color: var(--primary); }

.stepper__count {
    width: 2.75rem;
    padding: 0;
    border: 0;
    background: transparent;
    font-family: var(--font-mono);
    font-size: 1.25rem;
    font-weight: 700;
    text-align: center;
    /* Typed into directly when a count is large — tapping plus thirty times
       is not the only way in. */
    -moz-appearance: textfield;
}
.stepper__count::-webkit-outer-spin-button,
.stepper__count::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper__count:focus { outline: 2px solid var(--primary); border-radius: var(--radius-sm); }
.stepper__count.is-zero { color: var(--gray-400); font-weight: 500; }

/* The running total, pinned above the rows so it never scrolls out of sight
   while the drawer is being counted. */
.cash-total {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    margin: calc(var(--s4) * -1) calc(var(--s4) * -1) var(--s4);
    padding: var(--s4);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}

.cash-total__value {
    font-family: var(--font-mono);
    font-size: clamp(1.5rem, 8vw, 2.25rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    white-space: nowrap;
}
.cash-total--in  .cash-total__value { color: var(--in); }
.cash-total--out .cash-total__value { color: var(--out); }

.cash-total__bills { font-size: 0.875rem; color: var(--text-muted); white-space: nowrap; }

/* The card on the home page. */
.cash-card__figure {
    display: flex;
    align-items: baseline;
    gap: var(--s2);
    flex-wrap: wrap;
}
.cash-card__amount {
    font-family: var(--font-mono);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.03em;
}

/* One chip per denomination that is actually in the drawer. */
.cash-chips { display: flex; flex-wrap: wrap; gap: var(--s1); margin-top: var(--s2); }

.cash-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
    padding: 0.125rem var(--s2);
    border-radius: var(--radius-sm);
    background: var(--gray-100);
    font-family: var(--font-mono);
    font-size: 0.8125rem;
}
.cash-chip__count { font-weight: 700; }
.cash-chip--negative { background: var(--danger-bg); color: var(--danger); }

/* --------------------------------------------------------------------------
   Lists used in settings
   -------------------------------------------------------------------------- */
.list { display: flex; flex-direction: column; }

.list__item {
    display: flex;
    align-items: center;
    gap: var(--s3);
    width: 100%;
    padding: var(--s3) var(--s2);
    border: 0;
    border-bottom: 1px solid var(--border);
    background: transparent;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.list__item:last-child { border-bottom: 0; }
.list__item:hover { background: var(--gray-50); }
.list__item svg.chev { width: 1.125rem; height: 1.125rem; flex: 0 0 auto; fill: none; stroke: var(--gray-400); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.list__title { font-weight: 600; }
.list__sub { font-size: 0.8125rem; color: var(--text-muted); }

/* --------------------------------------------------------------------------
   What the app has learned
   -------------------------------------------------------------------------- */
.rule { padding: var(--s3) 0; border-bottom: 1px solid var(--border); }
.rule:last-child { border-bottom: 0; }
.rule__payee { font-weight: 650; margin-bottom: var(--s2); display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.rule__line { display: flex; align-items: baseline; gap: var(--s2); font-size: 0.875rem; padding: 0.125rem 0; }
.rule__book { display: inline-flex; align-items: center; gap: 0.375rem; font-weight: 650; }
.rule__range { color: var(--text-muted); font-family: var(--font-mono); font-size: 0.8125rem; }

/* --------------------------------------------------------------------------
   Alerts, empty states, toasts
   -------------------------------------------------------------------------- */
.alert {
    padding: var(--s3) var(--s4);
    border-radius: var(--radius);
    border: 1px solid transparent;
    font-size: 0.9375rem;
    margin-bottom: var(--s4);
}
.alert--error   { background: var(--danger-bg);  border-color: #f5c6c0; color: #8f2b20; }
.alert--warning { background: var(--warning-bg); border-color: #f3d9bd; color: #8a4708; }
.alert--success { background: var(--success-bg); border-color: #bfe0d2; color: #145840; }
.alert--info    { background: var(--gray-50);    border-color: var(--border); color: var(--gray-600); }

.empty { padding: var(--s6) var(--s4); text-align: center; color: var(--text-muted); }
.empty svg { width: 2.5rem; height: 2.5rem; margin: 0 auto var(--s3); fill: none; stroke: var(--gray-300); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.empty__title { font-weight: 650; color: var(--text); margin-bottom: var(--s1); }

.loading-block { display: flex; align-items: center; gap: var(--s2); padding: var(--s5); color: var(--text-muted); justify-content: center; }

.spinner {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.toast-stack {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(var(--navbar-height) + env(safe-area-inset-bottom, 0px) + var(--s3));
    z-index: 60;
    display: flex;
    flex-direction: column;
    gap: var(--s2);
    width: min(26rem, calc(100vw - 2rem));
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border-radius: var(--radius);
    background: var(--navy);
    color: var(--white);
    box-shadow: var(--shadow-lg);
    font-size: 0.9375rem;
    transition: opacity 0.2s ease;
    pointer-events: auto;
}
.toast--error { background: var(--danger); }
.toast--success { background: var(--success); }
.toast__action { margin-left: auto; background: none; border: 0; color: inherit; font-weight: 700; text-decoration: underline; cursor: pointer; padding: 0; }

/* --------------------------------------------------------------------------
   Modal — every editor renders into this one panel
   -------------------------------------------------------------------------- */
.modal {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: rgba(21, 49, 67, 0.45);
}

.modal__panel {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: 92vh;
    background: var(--surface);
    /* A sheet from the bottom on a phone: it is where the thumb is, and it is
       what every other app on the device does. */
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

.modal__header {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s4);
    border-bottom: 1px solid var(--border);
}

.modal__title { font-size: 1.0625rem; font-weight: 700; }
.modal__subtitle { font-size: 0.8125rem; color: var(--text-muted); margin: 0; }

.modal__back, .modal__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}
.modal__back svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.modal__back:hover, .modal__close:hover { background: var(--gray-100); color: var(--text); }

.modal__body {
    padding: var(--s4);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    flex: 1 1 auto;
}

.modal__footer {
    display: flex;
    gap: var(--s3);
    padding: var(--s4);
    padding-bottom: calc(var(--s4) + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
    background: var(--gray-50);
}
/* min-width: 0 is what actually makes these share the row. flex: 1 1 0 alone
   is not enough — a flex item's default minimum width is its CONTENT, so
   three buttons whose labels are wider than a third of a 375px screen refuse
   to shrink and the last one is pushed off the edge. That is how "Save"
   ended up half off the screen on the entry editor. */
.modal__footer > .btn {
    flex: 1 1 0;
    min-width: 0;
    padding-left: var(--s2);
    padding-right: var(--s2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The action the screen is FOR gets the room. A footer of three equal
   buttons makes Delete as prominent as Save, which is both wrong about
   importance and a hazard on a screen about money. */
.modal__footer > .btn:last-child { flex: 1.4 1 0; }
.modal__footer > .btn--ghost { flex: 0 1 auto; }

body.modal-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   Receipts
   -------------------------------------------------------------------------- */
.receipts { display: flex; gap: var(--s2); flex-wrap: wrap; }

.receipt-thumb {
    position: relative;
    width: 4.5rem;
    height: 4.5rem;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    overflow: hidden;
    background: var(--gray-100);
    cursor: pointer;
    padding: 0;
}
.receipt-thumb img { width: 100%; height: 100%; object-fit: cover; }
.receipt-thumb__pdf { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 0.6875rem; font-weight: 700; color: var(--gray-600); }

.receipt-add {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    width: 4.5rem;
    height: 4.5rem;
    border: 2px dashed var(--border-strong);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.6875rem;
    font-weight: 650;
    cursor: pointer;
}
.receipt-add svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.receipt-viewer { text-align: center; }
.receipt-viewer img { max-height: 70vh; border-radius: var(--radius); }

/* --------------------------------------------------------------------------
   Tables — reports on a wide screen
   -------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.table th, .table td { padding: var(--s2) var(--s3); text-align: left; border-bottom: 1px solid var(--border); }
.table th { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 700; white-space: nowrap; }
.table td.num, .table th.num { text-align: right; font-family: var(--font-mono); white-space: nowrap; }
.table tfoot td { font-weight: 700; border-bottom: 0; border-top: 2px solid var(--border-strong); }

/* --------------------------------------------------------------------------
   Sign in and setup
   -------------------------------------------------------------------------- */
.is-login body, body.is-login {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding-bottom: 0;
    background: var(--navy);
}

.login { width: 100%; padding: var(--s4); }

.login__card {
    width: min(24rem, 100%);
    margin: 0 auto;
    padding: var(--s6) var(--s5);
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    text-align: center;
}

.login__logo {
    width: 4.5rem;
    height: 4.5rem;
    display: block;
    margin: 0 auto var(--s5);
    border-radius: var(--radius-lg);
}
.login__title { font-weight: 650; margin-bottom: var(--s4); }
.login__notice { padding: var(--s3); border-radius: var(--radius); background: var(--warning-bg); color: #8a4708; font-size: 0.875rem; margin-bottom: var(--s4); }
.login__message { min-height: 1.5rem; margin-top: var(--s3); font-size: 0.875rem; color: var(--danger); }
.login__message--success { color: var(--success); }
.login__footer { margin-top: var(--s5); font-size: 0.8125rem; color: var(--text-muted); }

.pin-inputs { display: flex; gap: var(--s3); justify-content: center; margin-bottom: var(--s5); }

.pin-digit {
    width: 3rem;
    height: 3.5rem;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--gray-50);
    text-align: center;
    font-size: 1.5rem;
    font-weight: 700;
}
.pin-digit:focus { outline: 2px solid var(--primary); outline-offset: -1px; background: var(--surface); }
.pin-digit.is-filled { background: var(--surface); border-color: var(--primary); }

/* The two links under "Continue as…" are stacked, not side by side. They do
   different things — one falls back to the PIN pad and is free, the other
   destroys the token and cannot be undone from that screen — and a mis-tap
   between two adjacent links is exactly the mistake to design out. */
#device-panel .btn--link { display: block; width: 100%; margin-top: var(--s2); }

/* "Remember me on this device" */
.login__remember {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    margin-bottom: var(--s4);
    text-align: left;
    font-size: 0.9375rem;
    cursor: pointer;
}
.login__remember input { width: 1.25rem; height: 1.25rem; margin: 0.125rem 0 0; flex: 0 0 auto; accent-color: var(--primary); }
.login__remember-hint { display: block; font-size: 0.8125rem; color: var(--text-muted); }

/* The one-time confirmation. Over the card rather than beside it, because it
   is a question that has to be answered before the sign-in continues. */
.trust-dialog {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--s4);
    background: rgba(21, 49, 67, 0.55);
}
.trust-dialog__panel {
    width: min(22rem, 100%);
    padding: var(--s5);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    text-align: left;
}
.trust-dialog__title { font-size: 1.0625rem; margin-bottom: var(--s3); }
.trust-dialog__body { font-size: 0.9375rem; color: var(--gray-600); margin-bottom: var(--s4); }

.lang-switch { display: inline-flex; gap: var(--s1); padding: 0.1875rem; border-radius: var(--radius); background: var(--gray-100); margin-top: var(--s5); }
.lang-switch__option { padding: var(--s1) var(--s3); border-radius: var(--radius-sm); font-size: 0.875rem; font-weight: 600; color: var(--text-muted); text-decoration: none; }
.lang-switch__option.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

.setup-warning {
    padding: var(--s3);
    border-radius: var(--radius);
    background: var(--warning-bg);
    border: 1px solid #f3d9bd;
    color: #8a4708;
    font-size: 0.8125rem;
    text-align: left;
    margin-bottom: var(--s4);
}

/* ==========================================================================
   DESKTOP — 900px and up
   ==========================================================================
   The nav leaves the bottom of the screen and becomes a rail down the left.
   Same buttons, same order, same code — only the box they sit in changes,
   which is what keeps the two layouts from drifting into two designs.
   ========================================================================== */
@media (min-width: 900px) {
    body {
        padding-bottom: 0;
        padding-left: 15rem;
    }

    .app-header {
        padding-left: var(--s5);
        padding-right: var(--s5);
    }

    .navbar {
        top: 0;
        right: auto;
        width: 15rem;
        height: 100vh;
        flex-direction: column;
        justify-content: flex-start;
        gap: var(--s1);
        padding: var(--s4) var(--s3);
        border-top: 0;
        border-right: 1px solid var(--border);
        /* Above the header, because on a desktop the rail is the frame the
           page sits inside rather than a bar over the top of it. */
        z-index: 45;
    }

    .navbar__brand {
        display: flex;
        align-items: center;
        gap: var(--s2);
        padding: var(--s2) var(--s3) var(--s5);
        font-weight: 700;
    }

    .navbar__item {
        flex: 0 0 auto;
        flex-direction: row;
        justify-content: flex-start;
        gap: var(--s3);
        width: 100%;
        min-height: 2.75rem;
        padding: var(--s2) var(--s3);
        border-radius: var(--radius);
        font-size: 0.9375rem;
    }
    .navbar__item.is-active { background: var(--gray-100); }

    .navbar__badge { position: static; margin: 0 0 0 auto; }

    .app-main { max-width: 60rem; padding: var(--s5); }

    /* Two columns where there is genuinely something to put beside something
       else. Not everywhere: a form stretched to 60rem is harder to read than
       one that stays the width of a phone. */
    .cols {
        display: grid;
        grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
        gap: var(--s5);
        align-items: start;
    }

    .quick-actions { max-width: 30rem; }

    /* The sheet becomes a centred dialog. */
    .modal { align-items: center; }
    .modal__panel {
        width: min(40rem, calc(100vw - 4rem));
        max-height: 85vh;
        border-radius: var(--radius-lg);
    }
    .modal__footer { padding-bottom: var(--s4); }

    .toast-stack { bottom: var(--s5); left: auto; right: var(--s5); transform: none; }

    /* No swiping with a mouse. Dragging a card with a pointer is fiddly and
       nobody discovers it, so the desktop gets the two buttons — which are on
       the phone too — plus the left and right arrow keys. */
    .deck { min-height: 21rem; }
    .deck__card { cursor: default; }
}

/* A pointer that is not a finger: same rule as above, stated by capability
   rather than by width, so a small window on a laptop behaves like a laptop. */
@media (hover: hover) and (pointer: fine) {
    .deck__card { cursor: default; }
}

/* --------------------------------------------------------------------------
   Print — a report somebody takes to their accountant
   -------------------------------------------------------------------------- */
@media print {
    .navbar, .app-header, .toast-stack, .btn, .segmented, .quick-actions { display: none !important; }
    body { padding: 0; background: var(--white); }
    .app-main { max-width: none; padding: 0; }
    .card { border: 0; box-shadow: none; }
    .modal { position: static; background: none; }
    .modal__panel { max-height: none; box-shadow: none; }
}

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}
