/*
  The web interface wears the app's clothes.
  Tokens are lifted from ui/theme/Color.kt and Type.kt, not eyeballed from a
  screenshot — a second client that is nearly the same colour is worse than one
  that is obviously different.

  The design's logic: ink on paper, everything in a hard-bordered box with a
  solid offset shadow and no blur. At night the paper becomes deep ink-violet,
  the ink becomes cream, and the shadow goes darker than the page rather than
  lighter. The accent survives unchanged, because it is the brand.

  Mobile first. Most people opening this have a phone in one hand and a bill in
  the other; the desktop case is the easy one to widen into.

  The Content-Security-Policy says style-src 'self', which also refuses style=""
  attributes. Every rule lives here; a template that needs a one-off gets a class.
*/

/* ---------------------------------------------------------------- faces */
/*
  Subset to latin plus the punctuation the interface actually draws, and served
  from this origin — the CSP forbids third-party anything, and a font request to
  Google would tell them who is reading a page about somebody's money.
*/
@font-face {
  font-family: "Archivo Black";
  src: url("/assets/fonts/archivo-black.woff2?v=N3LMmjeFc140") format("woff2");
  font-weight: 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/space-grotesk-400.woff2?v=N3LMmjeFc140") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/space-grotesk-700.woff2?v=N3LMmjeFc140") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
/*
  The category glyphs, addressed by codepoint. Pinned to one weight and optical
  size and subset to the eleven the seeded categories use — 10.6 MB of variable
  font down to 1.5 KB. `block` rather than `swap`: there is no fallback that
  resembles an icon, and a private-use codepoint rendered in a text face is a
  tofu box, so a moment of nothing is better than a moment of wrong.
*/
@font-face {
  font-family: "Material Symbols";
  src: url("/assets/fonts/material-symbols.woff2?v=N3LMmjeFc140") format("woff2");
  font-weight: 600; font-style: normal; font-display: block;
}
@font-face {
  font-family: "Space Mono";
  src: url("/assets/fonts/space-mono-700.woff2?v=N3LMmjeFc140") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ---------------------------------------------------------------- palette */

:root {
  --paper: #FFF6E8;
  --card: #FFFDF9;
  --ink: #1B1830;
  --ink-muted: #6B6685;
  --ink-faint: #8B85A0;
  --on-accent-muted: #5A5570;
  --hairline: #E7E1D3;
  --disabled: #F2ECDE;
  --disabled-border: #A9A3B8;
  --shadow: #1B1830;
  --accent: #FFD65C;
  --on-accent: #1B1830;

  /*
    The accent never inverts — it is the brand — so anything sitting on it needs
    an ink that never inverts either. --solid is the filled-button and hero-chip
    surface, and it stays dark in both moods for the same reason: in the dark
    theme --ink is cream, and a cream button with yellow text is unreadable.
    Straight off the app's ADD EXPENSE, which stays dark violet at night with a
    cream border and yellow letters.
  */
  --solid: #1B1830;
  --on-solid: #FFD65C;
  --tag-up-bg: #E4F7EC;
  --tag-up-fg: #14603A;
  --tag-down-bg: #FFE7ED;
  --tag-down-fg: #8E1740;

  --owed: #1E7A4A;
  --owed-surface: #E4F7EC;
  --owed-ink: #14603A;
  --owing: #B41E4E;
  --owing-surface: #FFE7ED;
  --owing-ink: #8E1740;

  --sans: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --display: "Archivo Black", "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  --mono: "Space Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --border: 3px;
  --lift: 5px;
  --radius: 18px;
  --pill: 999px;

  /* How wide a page's column is. Pages that want more say so on <body>. */
  --measure: 46rem;
  /* Quick out, soft landing: a sticker pressed down, not a spring. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #141220;
    --card: #1F1B2E;
    --ink: #F6F1E6;
    --ink-muted: #AEA6C4;
    --ink-faint: #837C9B;
    --hairline: #322C46;
    --disabled: #262137;
    --disabled-border: #534B6E;
    --shadow: #070610;
    --owed: #5BD79B;
    --owed-surface: #143A2A;
    --owed-ink: #9BEFC4;
    --owing: #FF7E9E;
    --owing-surface: #3E1526;
    --owing-ink: #FFB3C6;
    /* A shade above the card, so the filled button reads as raised rather than
       as a hole, and its cream border is what draws the shape. */
    --solid: #241F38;
    /* Tags stay bright with dark glyphs at night, which is what the app does —
       a deep pill with pale text disappears into the card behind it. */
    --tag-up-bg: #5BD79B;
    --tag-up-fg: #0E2A1C;
    --tag-down-bg: #FF7E9E;
    --tag-down-fg: #40101F;
  }
}

/*
  Two fixed contexts that ignore the theme. The yellow one is the brand and stays
  yellow at night, so everything drawn on it takes the light theme's tokens. The
  ink one is the reverse: a dark band in both moods.
*/
.sun, .is-land .chrome {
  --ink: #1B1830;
  --ink-muted: #4A4560;
  --ink-faint: #6B6685;
  --card: #FFFDF9;
  --shadow: #1B1830;
  --hairline: #E7E1D3;
  --solid: #1B1830;
  --on-solid: #FFD65C;
  --owed: #1E7A4A;
  --owing: #B41E4E;
  --tag-up-bg: #E4F7EC;
  --tag-up-fg: #14603A;
  --tag-down-bg: #FFE7ED;
  --tag-down-fg: #8E1740;
  background: var(--accent);
  color: var(--ink);
}
.inkband {
  --ink: #FFF6E8;
  --ink-muted: #C9C3DA;
  --ink-faint: #9A93B2;
  --card: #26213A;
  --shadow: #070610;
  --hairline: #3A3352;
  --solid: #26213A;
  --on-solid: #FFD65C;
  background: #1B1830;
  color: var(--ink);
}

/* ---------------------------------------------------------------- base */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0 0 40px;
  background: var(--paper);
  color: var(--ink);
  font: 400 16px/1.5 var(--sans);
}
.topbar, main, footer.site {
  width: min(100% - 2rem, var(--measure));
  margin-inline: auto;
}
.is-wide { --measure: 64rem; }
.is-narrow main { --measure: 30rem; }
a { color: inherit; text-underline-offset: 3px; }
img { max-width: 100%; }

.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 10;
  background: var(--solid); color: var(--on-solid);
  font: 900 0.86rem/1 var(--display); text-transform: uppercase;
  padding: 12px 16px; border-radius: var(--pill); text-decoration: none;
}
.skip:focus { top: 12px; }

/*
  The display face is uppercase everywhere in the app — headings, buttons, chips,
  section labels. It is the loudest thing about the design and the fastest way to
  read as the same product.
*/
h1 {
  font: 900 clamp(1.7rem, 6vw, 2.3rem)/1.05 var(--display);
  text-transform: uppercase;
  letter-spacing: -0.01em;
  margin: 18px 0 6px;
  text-wrap: balance;
}
h2 {
  font: 900 1.05rem/1.2 var(--display);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin: 30px 0 12px;
}
.sub { color: var(--ink-muted); margin: 0 0 18px; }
.muted { color: var(--ink-muted); }
.fine { color: var(--ink-muted); font-size: 0.88rem; line-height: 1.45; }
.after { margin-top: 22px; }

/* The tiny tracked label above every group of controls. */
.label {
  display: block;
  font: 700 0.66rem/1.4 var(--sans);
  text-transform: uppercase;
  letter-spacing: 0.11em;
  color: var(--ink-muted);
  margin: 0 0 4px;
}
.label.gap { margin-top: 20px; }

/* Money is always the mono face with tabular figures, so a column of cents lines
   up and a changing amount does not shift the layout. */
.amount, .money {
  font: 700 1rem/1.3 var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.owed { color: var(--owed); }
.owing { color: var(--owing); }

/* Line icons, drawn in the same stroke as the app's empty-state drawings. */
.ico {
  flex: none; width: 1.15em; height: 1.15em;
  fill: none; stroke: currentColor; stroke-width: 2.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ---------------------------------------------------------------- chrome */

.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 0 6px;
}
.topbar .spacer { flex: 1; }
.logo {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: 13px;
  background: var(--accent); color: var(--on-accent);
  border: var(--border) solid var(--ink); box-shadow: 3px 3px 0 var(--shadow);
  font: 900 22px/1 var(--display); text-decoration: none;
  transition: transform 200ms var(--ease-out);
}
@media (hover: hover) { .logo:hover { transform: rotate(-8deg); } }
.wordmark {
  font: 900 1.15rem/1 var(--display);
  text-transform: uppercase; letter-spacing: -0.01em; text-decoration: none;
}
.nav { display: flex; gap: 4px; }
.nav a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 8px;
  font: 900 0.82rem/1 var(--display); text-transform: uppercase; letter-spacing: 0.02em;
  text-decoration: none; color: var(--ink-muted);
  border-bottom: var(--border) solid transparent;
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--ink); }
.who { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; }
.who-name { display: none; }
@media (min-width: 40rem) { .who-name { display: inline; } }
.inline-form { margin: 0; }
.textbtn {
  background: none; border: 0; cursor: pointer;
  min-height: 44px; padding: 0 4px;
  font: 700 0.88rem/1 var(--sans); color: var(--ink-muted);
  text-decoration: underline; text-underline-offset: 3px;
}
.textbtn:hover { color: var(--ink); }

footer.site {
  margin-top: 48px; padding: 18px 0 0;
  border-top: 2px solid var(--hairline);
  color: var(--ink-muted); font-size: 0.88rem;
  display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center;
}
footer.site .spacer { flex: 1; }
footer.site a { color: inherit; }

.back {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; margin-top: 4px;
  font: 700 0.92rem/1 var(--sans); color: var(--ink-muted); text-decoration: none;
}
.back:hover { color: var(--ink); text-decoration: underline; }
.back + h1, .back + .pagehead h1 { margin-top: 2px; }

.pagehead {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 12px 20px; margin-bottom: 18px;
}
.pagehead .sub { margin: 0; }

/* ---------------------------------------------------------------- surfaces */

.card {
  background: var(--card);
  border: var(--border) solid var(--ink);
  border-radius: var(--radius);
  box-shadow: var(--lift) var(--lift) 0 var(--shadow);
  padding: 16px 18px;
  margin: 16px 0;
}
.card.flush { padding: 4px 18px; margin-top: 0; }

/*
  The balance hero: the one filled-accent surface on a page, carrying the number
  that the whole screen exists to show. A fixed light context: yellow in both
  moods, so its text is the dark ink in both moods rather than the theme's.
*/
.hero {
  display: block;
  background: var(--accent); color: var(--on-accent);
  border: var(--border) solid var(--ink);
  border-radius: 22px;
  box-shadow: var(--lift) var(--lift) 0 var(--shadow);
  padding: 16px 20px 18px;
  margin: 0 0 18px;
}
.hero .label { color: var(--on-accent-muted); }
.hero .chip, .hero .badge { border-color: var(--on-accent); }
.hero .badge { background: var(--solid); color: #FFF6E8; }
.hero .chip.on { background: var(--solid); color: var(--accent); }
.hero .field, .hero input { color: var(--on-accent); }
.hero input::placeholder { color: var(--on-accent-muted); }
.hero:focus-within { outline: 3px solid var(--ink); outline-offset: 3px; }
.hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.hero .figure {
  font: 900 clamp(2.4rem, 12vw, 3.4rem)/1 var(--display);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.035em;
  margin: 2px 0 14px;
}
.hero .row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* The big number you type into, on the expense form and the landing demo. */
.amount-input {
  flex: 1; min-width: 0; width: 100%;
  background: transparent; border: 0; padding: 0; color: inherit;
  font: 900 clamp(2.2rem, 10vw, 3rem)/1.1 var(--display);
  letter-spacing: -0.035em; font-variant-numeric: tabular-nums;
}
.amount-input:focus { outline: none; }

/* ---------------------------------------------------------------- pills */

/*
  Chips and buttons are the same object at different weights: a pill with a hard
  border. White means "available", ink-filled means "chosen" or "the one action
  on this screen". Hovering lifts the sticker off the page; pressing pushes it
  into its shadow.
*/
.chip, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: 900 0.86rem/1 var(--display);
  text-transform: uppercase; letter-spacing: 0.02em;
  text-decoration: none; cursor: pointer;
  border: var(--border) solid var(--ink); border-radius: var(--pill);
  background: var(--card); color: var(--ink);
  padding: 11px 16px; min-height: 44px;
  transition: transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out);
}
.chip.on, .btn.primary {
  background: var(--solid); color: var(--on-solid);
}
.btn {
  width: 100%; padding: 15px 20px; font-size: 0.95rem; min-height: 52px;
  box-shadow: var(--lift) var(--lift) 0 var(--shadow);
  margin: 16px 0 0;
}
/* An ink button's shadow is the accent, not more ink — otherwise it disappears
   into its own outline. Straight from the app's SAVE button. */
.btn.primary { box-shadow: var(--lift) var(--lift) 0 var(--accent); }
.btn.accent { background: var(--accent); color: var(--on-accent); }
.btn.danger { background: var(--owing); color: #FFF6E8; border-color: var(--ink); }
.btn.inline {
  width: auto; margin: 0; padding: 10px 16px; min-height: 44px; font-size: 0.8rem;
  box-shadow: 3px 3px 0 var(--shadow);
}
.btn.primary.inline { box-shadow: 3px 3px 0 var(--accent); }
.btn.big { padding: 18px 26px; font-size: 1rem; }

@media (hover: hover) {
  .btn:not(:disabled):hover {
    transform: translate(-2px, -2px);
    box-shadow: calc(var(--lift) + 2px) calc(var(--lift) + 2px) 0 var(--shadow);
  }
  .btn.primary:not(:disabled):hover { box-shadow: calc(var(--lift) + 2px) calc(var(--lift) + 2px) 0 var(--accent); }
  .btn.inline:not(:disabled):hover { box-shadow: 5px 5px 0 var(--shadow); }
  .btn.primary.inline:not(:disabled):hover { box-shadow: 5px 5px 0 var(--accent); }
  .chip:not(.static):hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 var(--shadow); }
}
.btn:not(:disabled):active, .chip:not(.static):active {
  transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--shadow);
}
.btn.primary:not(:disabled):active { box-shadow: 2px 2px 0 var(--accent); }
.btn[disabled], .btn:disabled {
  background: var(--disabled); color: var(--ink-faint);
  border-color: var(--disabled-border); box-shadow: none; cursor: not-allowed;
}
.chip.static { cursor: default; }

.chiprow { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 4px; }
.actions { display: flex; gap: 10px; flex-wrap: wrap; }
/*
  A basis wide enough that two of them do not fit on a phone, so they stack
  instead of squeezing a two-word label onto two lines.
*/
.actions > * { flex: 1 1 15rem; }

:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
@media (prefers-color-scheme: dark) { :focus-visible { outline-color: var(--accent); } }
.sun :focus-visible, .is-land .chrome :focus-visible { outline-color: #1B1830; }
.inkband :focus-visible { outline-color: var(--accent); }

/* ---------------------------------------------------------------- rows */

.rows { list-style: none; margin: 0; padding: 0; }
.rows li {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 2px solid var(--hairline);
}
.rows li:last-child { border-bottom: 0; }
.grow { flex: 1; min-width: 0; text-decoration: none; }
.grow strong { display: block; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grow .meta, .meta {
  display: block;
  font: 700 0.7rem/1.4 var(--sans);
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-muted);
}

/*
  A card per row, with the shadow tinted by which way the money went. The app
  does this on the expense list and it is the fastest read on the screen.

  A row with a link in it is one big target: the link's ::after covers the whole
  card, so the tap does not have to land on the words.
*/
.cards { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 12px; }
.cards > li {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  background: var(--card);
  border: var(--border) solid var(--ink); border-radius: 15px;
  box-shadow: 4px 4px 0 var(--shadow);
  padding: 13px 15px;
  transition: transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out);
}
.cards > li.up { box-shadow: 4px 4px 0 var(--owed); }
.cards > li.down { box-shadow: 4px 4px 0 var(--owing); }
.cards a.grow::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.cards a.grow:focus-visible { outline: none; }
.cards > li:has(> a.grow:focus-visible) { outline: 3px solid var(--ink); outline-offset: 3px; }
@media (prefers-color-scheme: dark) {
  .cards > li:has(> a.grow:focus-visible) { outline-color: var(--accent); }
}
@media (hover: hover) {
  .cards > li:has(> a.grow):hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--shadow); }
  .cards > li.up:has(> a.grow):hover { box-shadow: 6px 6px 0 var(--owed); }
  .cards > li.down:has(> a.grow):hover { box-shadow: 6px 6px 0 var(--owing); }
}
.cards > li.more { justify-content: center; background: none; border: 0; box-shadow: none; }
@media (min-width: 44rem) { .cards.tiles { grid-template-columns: 1fr 1fr; gap: 16px; } }

.tag {
  font: 700 0.8rem/1 var(--mono);
  font-variant-numeric: tabular-nums;
  border-radius: var(--pill); padding: 6px 10px; white-space: nowrap;
}
.tag.up { background: var(--tag-up-bg); color: var(--tag-up-fg); }
.tag.down { background: var(--tag-down-bg); color: var(--tag-down-fg); }
.stack { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }

.face {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 12px;
  background: var(--accent); color: var(--on-accent);
  border: var(--border) solid var(--ink);
  font: 900 17px/1 var(--display);
}
.face.round { border-radius: 50%; }
.face.sm { width: 32px; height: 32px; font-size: 14px; border-width: 2.5px; }

/* Who pays whom: two faces and an arrow, then the sentence. */
.duo { display: inline-flex; align-items: center; gap: 3px; flex: none; }
.duo .ico { width: 16px; height: 16px; color: var(--ink-muted); }
.transfers > li.on { background: var(--accent); color: var(--on-accent); }
.transfers > li.on .duo .ico, .transfers > li.on .amount { color: var(--on-accent); }
.transfers > li.on .face { border-color: var(--on-accent); }

.empty { text-align: center; color: var(--ink-muted); padding: 22px 12px; margin: 0; }

/* An empty screen gets a drawing, the way the app's do, and the one thing to do. */
.emptystate { text-align: center; padding: 24px 16px 8px; }
.emptystate .art { display: block; width: 132px; height: 132px; margin: 0 auto 6px; }
.emptystate p { color: var(--ink-muted); max-width: 26rem; margin: 0 auto; }
.emptystate .btn { width: auto; }

.art .a-accent { fill: var(--accent); }
.art .a-card { fill: var(--card); }
.art .a-ink { fill: var(--ink); }
.art .a-muted { fill: var(--hairline); }
.art .a-edge { fill: none; stroke: var(--ink); stroke-width: 2.6; }
.art .a-edge-muted { fill: none; stroke: var(--hairline); stroke-width: 2.6; }
.art .a-line { fill: none; stroke: var(--ink); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.art .a-line.thick { stroke-width: 3.4; }

/* ---------------------------------------------------------------- a group */

/*
  One column on a phone: the number, what to do about it, then the history. On a
  wide screen the history takes the main column and who-owes-whom sits beside it,
  where it stays in view while the list scrolls.
*/
.groupgrid { display: grid; grid-template-areas: "hero" "side" "list"; column-gap: 32px; }
.g-hero { grid-area: hero; }
.g-side { grid-area: side; }
.g-list { grid-area: list; }
.g-hero .btn { margin: 0 0 8px; }
@media (min-width: 60rem) {
  .groupgrid {
    grid-template-columns: minmax(0, 1fr) 21rem;
    grid-template-areas: "hero side" "list side";
    align-items: start;
  }
  .g-side { position: sticky; top: 16px; }
  .g-side h2:first-child { margin-top: 0; }
}

.danger-zone { margin-top: 36px; padding-top: 8px; border-top: 2px dashed var(--hairline); }
.danger-zone .btn { width: auto; }

/* ---------------------------------------------------------------- forms */

/*
  A field is a bordered card with its label inside it, the way the app draws
  them: the label is part of the box rather than floating above it.
*/
.field {
  display: block;
  background: var(--card);
  border: var(--border) solid var(--ink); border-radius: 15px;
  box-shadow: 4px 4px 0 var(--shadow);
  padding: 9px 15px 11px;
  margin: 14px 0;
}
.field:focus-within { outline: 3px solid var(--ink); outline-offset: 3px; }
@media (prefers-color-scheme: dark) { .field:focus-within { outline-color: var(--accent); } }
.field input, .field select, .field textarea {
  width: 100%; font: 400 1.02rem/1.4 var(--sans); color: var(--ink);
  background: transparent; border: 0; padding: 0; margin: 0;
  min-height: 28px;
}
.field input:focus, .field select:focus, .field textarea:focus { outline: none; }
.field input::placeholder { color: var(--ink-faint); }
.field.money-field input { font: 700 1.5rem/1.2 var(--mono); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.field select {
  appearance: none; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  /* The left half of the chevron first, then the right: the other way round
     the two triangles point apart and draw a bow tie instead of a "v". */
  background-position: right 8px top 60%, right 2px top 60%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 22px;
}
.field select option { color: #1B1830; }
.pair { display: flex; flex-wrap: wrap; column-gap: 12px; }
.pair > * { flex: 1 1 10rem; min-width: 0; }

/* The currency badge that sits inside the amount hero. */
.badge {
  flex: none;
  font: 900 0.8rem/1 var(--display); text-transform: uppercase;
  background: var(--card); color: var(--ink);
  border: var(--border) solid var(--ink); border-radius: var(--pill);
  padding: 8px 13px;
}

/* A radio or checkbox drawn as the app draws it: a hard-bordered box that fills
   with ink and shows an accent tick. */
.pick { position: absolute; opacity: 0; width: 0; height: 0; }
.pick + .box {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 10px;
  border: var(--border) solid var(--ink); background: var(--card);
  color: transparent; font: 900 15px/1 var(--display); cursor: pointer;
}
/* Filled with --solid, not --ink: at night --ink is cream, and a yellow tick on
   cream is a tick nobody can see. */
.pick:checked + .box { background: var(--solid); color: var(--accent); }
/* The chosen split mode, read off the radio rather than set by script. */
.chip:has(.pick:checked) { background: var(--solid); color: var(--on-solid); }

/*
  Which input a split row shows follows the checked mode. Plain CSS, so it holds
  with scripts off, and nothing has to be told twice.
*/
.split-row .m-exact, .split-row .m-shares, .split-row .m-percent, .split-row .m-equal { display: none; }
.split:has([name="split_type"][value="exact"]:checked) .m-exact,
.split:has([name="split_type"][value="shares"]:checked) .m-shares,
.split:has([name="split_type"][value="percent"]:checked) .m-percent,
.split:has([name="split_type"][value="equal"]:checked) .m-equal { display: inline-block; }
.pick:focus-visible + .box, .chip:has(.pick:focus-visible) { outline: 3px solid var(--ink); outline-offset: 3px; }
@media (prefers-color-scheme: dark) {
  .pick:focus-visible + .box, .chip:has(.pick:focus-visible) { outline-color: var(--accent); }
}

/* ---------------------------------------------------------------- notices */

.problem, .notice {
  display: flex; gap: 10px; align-items: flex-start;
  border: var(--border) solid var(--owing); border-radius: 14px;
  background: var(--owing-surface); color: var(--owing-ink);
  padding: 12px 15px; margin: 16px 0; font-weight: 700;
}
.notice { border-color: var(--owed); background: var(--owed-surface); color: var(--owed-ink); }

/* ---------------------------------------------------------------- split */

.split-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 2px solid var(--hairline);
  min-height: 56px;
}
.split-row:last-of-type { border-bottom: 0; }
.split-row .name { flex: 1; min-width: 0; font-weight: 700; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.split-row input[type="text"], .split-row input[type="number"] {
  width: 7.5rem; text-align: right;
  font: 700 1rem/1 var(--mono); font-variant-numeric: tabular-nums;
  color: var(--ink); background: var(--paper);
  border: 2px solid var(--ink); border-radius: 10px; padding: 9px 11px;
}
.split-total {
  display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap;
  gap: 4px 12px; padding-top: 14px; margin-top: 2px;
  border-top: 2px solid var(--hairline);
  font: 700 0.7rem/1.4 var(--sans); text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--ink-muted);
}
.split-total .money { font-size: 1.05rem; color: var(--ink); letter-spacing: -0.02em; }
.split-total.off .money { color: var(--owing); }

/* ---------------------------------------------------------------- htmx */

/*
  Fading the element htmx is waiting on is enough feedback for a request that
  usually takes tens of milliseconds. A spinner appearing and vanishing that fast
  reads as a flicker.
*/
.htmx-request.pending, .htmx-request .pending { opacity: 0.45; }
.pending { transition: opacity 0.12s ease-in; }

/*
  The category mark. The swatches are the app's (ui/theme/Color.kt): bright with a
  dark glyph in the light theme, deeper at night so the same dark glyph still
  reads on them.
*/
.mark {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 11px;
  border: var(--border) solid var(--ink);
  color: #1B1830;
  font-family: "Material Symbols"; font-size: 21px; font-weight: 600;
  /* The glyphs are drawn on their own baseline; without this they sit low in
     the square and the ligature-suppression keeps a stray codepoint from being
     recombined by the text engine. */
  line-height: 1; font-variant-ligatures: none; -webkit-font-feature-settings: "liga" 0;
          font-feature-settings: "liga" 0;
  -webkit-font-smoothing: antialiased;
}
.mark.s0 { background: #FFD65C; }
.mark.s1 { background: #7FD1FF; }
.mark.s2 { background: #FFA36B; }
.mark.s3 { background: #C9B8FF; }
.mark.s4 { background: #B6F06B; }
@media (prefers-color-scheme: dark) {
  .mark.s0 { background: #E0B23C; }
  .mark.s1 { background: #54A9DC; }
  .mark.s2 { background: #D97F47; }
  .mark.s3 { background: #9C8AD8; }
  .mark.s4 { background: #8CC64B; }
}
.sun .mark.s2 { background: #FFA36B; }

/* ================================================================ landing */

/*
  The one page that sells rather than serves. It gets the whole width, a yellow
  slab for a first impression that is the brand in both moods, and stickers —
  the app's own components, cut out and slapped on the page.
*/
.is-land { --measure: 72rem; }
.is-land main { width: 100%; }
.is-land .chrome .topbar { padding-bottom: 0; }

.wrap { width: min(100% - 2rem, 72rem); margin-inline: auto; }
.band { padding-block: clamp(3.5rem, 9vw, 6.5rem); }
.band.sun { padding-block: clamp(1.75rem, 5vw, 3.5rem) clamp(3rem, 8vw, 5.5rem); border-bottom: var(--border) solid #1B1830; }
.inkband { border-block: var(--border) solid #1B1830; }
@media (prefers-color-scheme: dark) { .inkband { border-color: #FFF6E8; } }

.display-2 {
  font: 900 clamp(1.9rem, 5vw, 3.2rem)/1 var(--display);
  text-transform: uppercase; letter-spacing: -0.015em;
  margin: 0 0 16px; text-wrap: balance;
}
.lede {
  font-size: clamp(1.05rem, 1.5vw, 1.22rem); line-height: 1.55;
  color: var(--ink-muted); max-width: 34rem; margin: 0;
}

/* ---- hero */

.hero-grid { display: grid; gap: clamp(2.5rem, 6vw, 3rem); align-items: center; }
@media (min-width: 56rem) {
  .hero-grid { grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr); }
}
.kicker {
  display: inline-block; margin: 0;
  font: 700 0.8rem/1.3 var(--sans); text-transform: uppercase; letter-spacing: 0.08em;
  background: var(--card); border: 2.5px solid var(--ink); border-radius: 12px;
  padding: 7px 13px; box-shadow: 3px 3px 0 var(--shadow);
}
/* Sized so "WITHOUT THE" holds one line in the hero's column at every desktop
   width; any bigger and a lone "THE" ends up on a line of its own. */
.display {
  font: 900 clamp(2.6rem, 5.6vw, 4.4rem)/0.95 var(--display);
  text-transform: uppercase; letter-spacing: -0.025em;
  margin: 22px 0 20px; text-wrap: balance;
}
/*
  The phrase the whole product is about, set as a sticker of its own: ink with
  yellow letters, stuck on at an angle. Emphasis by object, not by colour trick.
*/
.stickerword {
  --tilt: -2.5deg;
  display: inline-block;
  background: #1B1830; color: #FFD65C;
  padding: 0.04em 0.16em 0.08em; border-radius: 0.14em;
  transform: rotate(var(--tilt));
  box-shadow: 0.07em 0.07em 0 #FFFDF9;
}
.cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 30px; }
.cta .btn { margin: 0; flex: 1 1 15rem; }
@media (min-width: 56rem) { .cta .btn { flex: 0 1 auto; width: auto; } }
.sun .btn.primary { box-shadow: var(--lift) var(--lift) 0 #FFFDF9; }
@media (hover: hover) {
  .sun .btn.primary:hover { box-shadow: calc(var(--lift) + 2px) calc(var(--lift) + 2px) 0 #FFFDF9; }
}
.sun .btn.primary:active { box-shadow: 2px 2px 0 #FFFDF9; }
.fineprint { margin: 18px 0 0; font-size: 0.92rem; color: var(--ink-muted); }
.fineprint a { color: var(--ink); font-weight: 700; }

/*
  The pile: a real screenshot with three stickers on top. Positioned in
  percentages of a box whose shape is fixed up front, so it is the same
  composition at every width and nothing moves when the image arrives.
*/
.pile {
  position: relative; width: min(100%, 27rem); margin-inline: auto;
  aspect-ratio: 4 / 5;
}
.pile-phone {
  --tilt: 3deg;
  position: absolute; left: 25%; top: 1%; width: 53%; height: auto;
  border: var(--border) solid #1B1830; border-radius: 22px;
  box-shadow: 8px 8px 0 #1B1830; background: #FFFDF9;
  transform: rotate(var(--tilt));
}
.receipt {
  --tilt: -6deg;
  position: absolute; left: 0; top: 16%; width: 47%;
  isolation: isolate; color: #1B1830;
  padding: 14px 14px 30px;
  display: grid; gap: 4px; justify-items: start;
  transform: rotate(var(--tilt));
}
.receipt .shape {
  position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%;
  overflow: visible; filter: drop-shadow(5px 5px 0 #1B1830);
}
.receipt .shape path { fill: #FFFDF9; stroke: #1B1830; stroke-width: 3; stroke-linejoin: round; }
.receipt .mark { width: 32px; height: 32px; font-size: 18px; border-color: #1B1830; }
.stk-title { font: 700 0.72rem/1.3 var(--sans); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 4px; }
.stk-amount { font: 700 clamp(1.3rem, 5vw, 1.7rem)/1 var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -0.03em; }
.stk-meta { font: 700 0.68rem/1.3 var(--sans); text-transform: uppercase; letter-spacing: 0.08em; color: #5A5570; }
.owes-stk {
  --tilt: 5deg;
  position: absolute; right: 0; top: 52%;
  display: grid; gap: 6px; justify-items: start;
  background: #FFFDF9; color: #1B1830;
  border: var(--border) solid #1B1830; border-radius: 16px;
  box-shadow: 5px 5px 0 #1B1830; padding: 12px 14px;
  transform: rotate(var(--tilt));
}
.owes-stk .tag { font-size: clamp(0.95rem, 3.4vw, 1.15rem); padding: 7px 12px; background: #E4F7EC; color: #14603A; }

/* A rubber stamp: double rule, drawn in the colour of money that is settled. */
.stamp {
  --tilt: -12deg;
  display: inline-block;
  font: 900 clamp(1rem, 3.4vw, 1.4rem)/1 var(--display);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: #1E7A4A; background: #FFFDF9;
  border: var(--border) solid currentColor; border-radius: 12px;
  outline: 2px solid currentColor; outline-offset: -8px;
  padding: 13px 16px;
  transform: rotate(var(--tilt));
}
.pile .stamp { position: absolute; left: 9%; bottom: 3%; }

@media (prefers-reduced-motion: no-preference) {
  .slap { animation: slap 620ms var(--ease-out) both; }
  .slap.d1 { animation-delay: 240ms; }
  .slap.d2 { animation-delay: 380ms; }
  .slap.d3 { animation-delay: 540ms; }
  .stickerword { animation: slap 560ms var(--ease-out) 120ms both; }
}
@keyframes slap {
  from { opacity: 0; transform: translateY(-16px) rotate(calc(var(--tilt, 0deg) - 9deg)) scale(1.1); }
  to { opacity: 1; transform: rotate(var(--tilt, 0deg)); }
}

/* ---- the split demo */

.demo-grid { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 56rem) { .demo-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 27rem); gap: 4rem; } }
.demo-note { margin: 18px 0 0; font-weight: 700; }
.demo { padding: 20px; margin: 0; }
.demo .hero { margin-bottom: 8px; box-shadow: 4px 4px 0 var(--shadow); }
.demo-try { margin: 0 0 14px; }
.demo-rows { list-style: none; margin: 0; padding: 0; }
.demo-rows li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border-bottom: 2px solid var(--hairline);
}
.pickbtn {
  display: inline-flex; align-items: center; gap: 12px; min-height: 52px;
  background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
  font: 700 1.02rem/1.2 var(--sans); color: var(--ink);
}
.pickbtn .face { transition: transform 160ms var(--ease-out); }
@media (hover: hover) { .pickbtn:hover .face { transform: rotate(-8deg); } }
.demo-rows li.out .face { background: var(--disabled); color: var(--ink-faint); border-color: var(--disabled-border); }
.demo-rows li.out .name { color: var(--ink-faint); text-decoration: line-through; text-decoration-thickness: 2px; }
.demo-rows li.out .amount { font: 700 0.78rem/1 var(--sans); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-faint); }
.demo .split-total { border-top: 0; }
.verdict { display: flex; align-items: center; gap: 8px; margin: 10px 0 0; font-weight: 700; color: var(--owed); }
.verdict.off { color: var(--ink-muted); }

/* ---- the fewest payments */

.few-grid { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 56rem) { .few-grid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 4rem; } }
.few-art { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.diagram {
  margin: 0; background: var(--card);
  border: var(--border) solid var(--ink); border-radius: 18px;
  padding: 8px 8px 12px;
}
.diagram.after { background: #FFD65C; border-color: #FFD65C; box-shadow: 6px 6px 0 #FFF6E8; }
.diagram svg { display: block; width: 100%; height: auto; }
.diagram figcaption {
  text-align: center; font: 700 0.72rem/1.3 var(--sans);
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted);
}
.diagram.after figcaption { color: #1B1830; }
.diagram .edge { fill: none; stroke: #8B85A0; stroke-width: 2.5; stroke-linecap: round; }
.diagram .tip { fill: #8B85A0; }
.diagram.after .edge { stroke: #1B1830; stroke-width: 3.5; }
.diagram.after .tip { fill: #1B1830; }
.diagram .who circle { fill: #FFD65C; stroke: #FFF6E8; stroke-width: 3; }
.diagram.after .who circle { fill: #FFFDF9; stroke: #1B1830; }
.diagram .who text { font: 900 15px var(--display); fill: #1B1830; text-anchor: middle; dominant-baseline: central; }

/* ---- the sticker sheet */

.sheet { list-style: none; margin: 2.2rem 0 0; padding: 0; display: grid; gap: 22px; }
@media (min-width: 48rem) {
  .sheet { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .sheet > li:nth-child(-n+3) { grid-column: span 2; }
  .sheet > li:nth-child(n+4) { grid-column: span 3; }
}
.sheet > li {
  --tilt: -0.8deg;
  background: var(--card); color: var(--ink);
  border: var(--border) solid var(--ink); border-radius: 20px;
  box-shadow: 6px 6px 0 var(--shadow);
  padding: 20px 22px 22px;
  transform: rotate(var(--tilt));
  transition: transform 220ms var(--ease-out), box-shadow 220ms var(--ease-out);
}
.sheet > li:nth-child(even) { --tilt: 0.9deg; }
@media (hover: hover) {
  .sheet > li:hover { transform: translate(-2px, -3px) rotate(0deg); box-shadow: 9px 9px 0 var(--shadow); }
}
.sheet h3 { font: 900 1.08rem/1.15 var(--display); text-transform: uppercase; letter-spacing: 0.005em; margin: 16px 0 6px; }
.sheet .body { margin: 0; color: var(--ink-muted); }
.sheet .is-accent { background: var(--accent); color: #1B1830; --ink-muted: #4A4560; }
.sheet .is-owed { background: var(--owed-surface); color: var(--owed-ink); --ink-muted: var(--owed-ink); }
.sheet .is-ink { background: var(--solid); color: #FFF6E8; --ink-muted: #C9C3DA; }
.sheet .badges { display: flex; flex-wrap: wrap; gap: 8px; }
.sheet .is-accent .badge:nth-child(odd) { background: #1B1830; color: #FFD65C; border-color: #1B1830; }
.sheet .is-accent .badge:nth-child(even) { background: #FFFDF9; color: #1B1830; border-color: #1B1830; }
.mini { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.mini li { display: flex; align-items: center; gap: 10px; font-weight: 700; }
.mini .amount { margin-left: auto; }
.mini .face { border-color: currentColor; }
.bubble {
  display: inline-block; margin: 0; max-width: 20rem;
  background: var(--accent); color: #1B1830;
  border: var(--border) solid var(--ink); border-radius: 18px 18px 18px 4px;
  padding: 11px 15px; font-weight: 700;
  box-shadow: 3px 3px 0 var(--shadow);
}
.sheet .is-ink .stamp { color: #FFD65C; background: transparent; --tilt: -6deg; }

/* ---- the screenshots */

.shots-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 8px 32px; }
.shots-head .display-2 { margin: 0; }
.shots {
  display: grid; grid-auto-flow: column; grid-auto-columns: clamp(12rem, 60vw, 15.5rem);
  gap: 26px; margin-top: 2rem; padding: 14px 6px 26px;
  overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: thin;
}
.shots figure { --tilt: -1.2deg; margin: 0; scroll-snap-align: start; transform: rotate(var(--tilt)); }
.shots figure:nth-child(even) { --tilt: 1.2deg; }
.shots img {
  display: block; width: 100%; height: auto;
  border: var(--border) solid var(--ink); border-radius: 20px;
  box-shadow: 6px 6px 0 var(--shadow); background: var(--card);
}
.shots figcaption {
  margin-top: 12px; text-align: center;
  font: 700 0.7rem/1.4 var(--sans); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--ink-muted);
}

/* ---- the last word */

.end-grid { display: grid; gap: 2rem; align-items: center; }
@media (min-width: 56rem) { .end-grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); } }
.end-grid .display-2 { margin: 0; color: #FFD65C; }
.end-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; }
.end-cta .or { color: var(--ink-muted); font-weight: 700; }
.end-cta .btn { width: auto; margin: 0; box-shadow: var(--lift) var(--lift) 0 #FFF6E8; border-color: #FFD65C; }
@media (hover: hover) { .end-cta .btn:hover { box-shadow: calc(var(--lift) + 2px) calc(var(--lift) + 2px) 0 #FFF6E8; } }

/*
  The Google Play badge is Google's artwork with its own proportions and its own
  brand rules: it is not a .btn, and it gets no border, no shadow and no recolour
  of ours.
*/
.play { display: inline-block; }
.play img { display: block; height: 58px; width: auto; }

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