/* Shared styling for the hosted pages. Mirrors the app's lavender identity so a
   link out of the app doesn't feel like it left it. */
:root {
  --bg: #faf9fc;
  --surface: #ffffff;
  --border: #e4dff0;
  --ink: #1e1a2b;
  --muted: #675f7d;
  --accent: #645a94;
  --accent-2: #c3b7e8;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #15121d;
    --surface: #1d1929;
    --border: #322b45;
    --ink: #ece8f6;
    --muted: #a79ec0;
    --accent: #a99ad8;
  }
}

* { box-sizing: border-box; }

/* The UA rule for [hidden] is display:none at zero specificity, so any class
   below that sets display (.stack, .chips) silently defeats it and the element
   shows anyway. The group page hides its states with the attribute, so this
   has to win. */
[hidden] { display: none !important; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

header.site, footer.site {
  max-width: 760px;
  margin: 0 auto;
  padding: 20px 22px;
}
footer.site {
  border-top: 1px solid var(--border);
  margin-top: 48px;
  color: var(--muted);
  font-size: 14px;
}
footer.site a { color: var(--muted); }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--ink);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.01em;
}

main.doc, main.invite {
  max-width: 760px;
  margin: 0 auto;
  padding: 8px 22px 40px;
}
main.doc h1 {
  font-size: 34px;
  letter-spacing: -0.025em;
  line-height: 1.15;
  margin: 8px 0 20px;
}
main.doc h2 {
  font-size: 20px;
  letter-spacing: -0.015em;
  margin: 34px 0 8px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
main.doc h3 { font-size: 16px; margin: 22px 0 6px; }
main.doc p, main.doc li { font-size: 15.5px; }
main.doc ul { padding-left: 22px; }
main.doc li { margin-bottom: 6px; }
main.doc code {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 0.88em;
}
blockquote {
  margin: 20px 0;
  padding: 14px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  color: var(--muted);
  font-size: 14.5px;
}
a { color: var(--accent); }

/* Invite pages */
main.invite { text-align: center; padding-top: 40px; }
main.invite h1 {
  font-size: 30px;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0 0 10px;
  text-wrap: balance;
}
main.invite p.sub { color: var(--muted); margin: 0 0 28px; font-size: 16.5px; }
.actions { display: flex; flex-direction: column; gap: 10px; align-items: center; }
.btn {
  display: inline-block;
  min-width: 240px;
  padding: 13px 22px;
  border-radius: 12px;
  text-decoration: none;
  font-weight: 650;
  font-size: 15.5px;
}
.btn.primary { background: var(--accent); color: #fff; }
.btn.secondary {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
}
.code-pill {
  display: inline-block;
  margin: 4px 0 24px;
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 17px;
  letter-spacing: 0.08em;
}
.note { color: var(--muted); font-size: 13.5px; margin-top: 26px; }

/* ── Group page (/w) ─────────────────────────────────────────────────────── */
main.group {
  max-width: 620px;
  margin: 0 auto;
  padding: 8px 22px 40px;
}
main.group h1 {
  font-size: 26px;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0 0 2px;
}
main.group h2 {
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 32px 0 10px;
}
.muted { color: var(--muted); }
.err { color: #c0392b; font-size: 14px; margin: 4px 0 0; }
@media (prefers-color-scheme: dark) { .err { color: #ff8a7a; } }

.group-head { display: flex; align-items: center; gap: 14px; margin-top: 12px; }
.group-head img {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  object-fit: cover;
  flex: none;
}
.group-head p { margin: 0; font-size: 14.5px; }

.head-row { display: flex; align-items: center; justify-content: space-between; }
.head-row h2 { margin-bottom: 10px; }
.balances-head { margin-top: 20px; }
.balances-head h2 { margin-top: 12px; }

.desc { margin: 10px 0 2px; font-size: 15px; }
.meta { margin: 0; color: var(--muted); font-size: 13px; }
.meta .btn.tiny { margin-left: 6px; vertical-align: baseline; }
.optional {
  font-weight: 500;
  font-size: 12px;
  color: var(--muted);
  opacity: 0.8;
}
.meta.warn { color: var(--accent); margin-top: 2px; }

/* Same shape as the app's inline notices: a quiet filled strip, not an alert. */
.banner {
  margin: 12px 0 0;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

/* ── Insight carousel ─────────────────────────────────────────────────────
   Scroll-snap rather than a JS pager: it gets native momentum and swipe on a
   phone, keyboard and trackpad on a desktop, for none of the code. */
.carousel-wrap { margin: 16px 0 4px; }
.carousel-viewport { position: relative; }
.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  gap: 0;
}
.carousel::-webkit-scrollbar { display: none; }
.carousel:focus { outline: none; }
.carousel:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Overlaid on the chart rather than beside it: the page is narrow on a phone,
   and stealing width for controls a touch user never needs would squeeze the
   chart itself. */
.carousel-nav {
  position: absolute;
  top: 55%;
  transform: translateY(-50%);
  z-index: 2;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.carousel-nav.prev { left: -6px; }
.carousel-nav.next { right: -6px; }
.carousel-nav:disabled { opacity: 0; pointer-events: none; }
.carousel-nav:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }

/* Touch devices have the swipe, and the arrows would sit on top of the chart
   for no gain. Anything with a real pointer keeps them — that is the case
   where swiping is not available at all. */
@media (hover: none) {
  .carousel-nav { display: none; }
}
.carousel .page {
  flex: 0 0 100%;
  scroll-snap-align: start;
  min-width: 0;
}
.carousel h3 {
  font-size: 16px;
  font-weight: 650;
  margin: 0;
  letter-spacing: -0.01em;
}
.carousel .page-head h3 .meta { font-weight: 500; font-size: 13px; }
.settled-note {
  height: 230px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  margin: 0;
}
.dots { display: flex; gap: 4px; justify-content: center; margin-top: 6px; }
/* The visible dot is 6px, but the button is padded out to a comfortable tap
   target — a 6px hit area would be unusable on a phone and fiddly with a
   mouse. */
.dot {
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.dot::after {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
}
.dot.on::after { background: var(--accent); }
.dot:focus { outline: none; }
.dot:focus-visible { outline: 2px solid var(--accent); border-radius: 50%; }

.donut, .sankey { display: block; width: 100%; height: 230px; margin-top: 8px; }
.slice { cursor: pointer; }
.slice:focus { outline: none; }
.slice:focus-visible { outline: 2px solid var(--accent); }
.donut-amount {
  fill: var(--ink);
  font-size: 19px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.donut-label { fill: var(--muted); font-size: 12px; }
.donut-badge { fill: #fff; font-size: 11px; font-weight: 700; }
.sankey-name { fill: var(--ink); font-size: 13px; font-weight: 600; }
.sankey-amount {
  fill: var(--muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* ── Action row ───────────────────────────────────────────────────────────
   Two equal halves, labels stacked under their icon — the app's layout, minus
   "Add member", which is member management and not something a link holder
   does. */
.actions-row { display: flex; gap: 8px; margin: 16px 0 0; }
.btn.action {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 12px 8px;
  border-radius: 12px;
  font-size: 13.5px;
  line-height: 1.25;
  text-align: center;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
}
.btn.action.primary { background: var(--accent); color: #fff; border-color: transparent; }
.btn.action:disabled { opacity: 0.45; cursor: not-allowed; }
.action-icon { font-size: 19px; line-height: 1; }

.btn.link {
  background: none;
  border: none;
  padding: 4px 0;
  color: var(--accent);
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
}

/* ── Ad placeholders ──────────────────────────────────────────────────────────
   Reserved space, not content. Both slots are sized to a standard unit so that
   dropping a real ad in later changes nothing about the layout — the usual way
   this goes wrong is a banner appearing after first paint and shoving the page
   down under someone's thumb. */
.ad-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px dashed var(--border);
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.ad-bottom {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 50px;
  border-width: 1px 0 0;
  border-style: solid;
  z-index: 5;
}
/* So the last row of a list is never sitting underneath the banner. */
body { padding-bottom: 50px; }

.ad-side { display: none; }

@media (min-width: 900px) {
  .ad-bottom { display: none; }
  body { padding-bottom: 0; }
  .ad-side {
    display: flex;
    width: 300px;
    height: 250px;
    margin: 28px auto 0;
    border-radius: 12px;
  }
}

/* ── Desktop layout ───────────────────────────────────────────────────────────
   Not the phone layout stretched. Three things change: the insight charts sit
   side by side instead of behind a swipe, the page splits into two columns so
   the balances are visible while reading the expenses, and more of each list is
   shown inline. Clicking through a page with a mouse is more work than tapping
   through one with a thumb, so the desktop errs towards showing rather than
   hiding. */
@media (min-width: 900px) {
  main.group { max-width: 1120px; }

  /* The carousel stops being one: same nodes, laid out as a row. */
  .carousel {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 28px;
    overflow: visible;
    scroll-snap-type: none;
  }
  .carousel .page { flex: none; scroll-snap-align: none; }
  .carousel-nav, .dots { display: none; }
  .donut, .sankey { height: 200px; }

  .group-body {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(300px, 1fr);
    gap: 40px;
    align-items: start;
    margin-top: 8px;
  }
  /* The side column holds balances, members and the ad. It is the reference
     while the wide column is being read, so it stays put on a long list. */
  .col-side {
    position: sticky;
    top: 16px;
  }
  .col-side h2:first-child, .balances-head h2 { margin-top: 0; }

  .actions-row { max-width: 260px; }
  .btn.action { flex-direction: row; gap: 8px; padding: 11px 18px; }

  main.group h1 { font-size: 30px; }
}

/* Tall enough to scroll independently on a short window, rather than pinning a
   column taller than the viewport and hiding its lower half. */
@media (min-width: 900px) and (max-height: 780px) {
  .col-side { position: static; }
}

/* ── Creating a group (/new) ──────────────────────────────────────────────── */
.people { gap: 8px; }
.person-row { display: flex; gap: 8px; align-items: center; }
.person-row input { margin-top: 0; }
.btn.icon {
  flex: none;
  min-width: 0;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.btn.icon:hover { border-color: var(--accent); color: var(--accent); }

/* The one notice on the site that has to be read rather than skimmed: losing
   this link loses the group outright. */
.banner.warn-strong {
  border-left-width: 3px;
  border-left-color: var(--accent);
  color: var(--ink);
  font-size: 14.5px;
}
.link-box {
  margin: 14px 0;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
}
.link-box code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  word-break: break-all;
  color: var(--ink);
}

/* ── Expense details dialog ───────────────────────────────────────────────── */
.detail {
  width: min(440px, calc(100vw - 32px));
  max-height: min(80vh, 700px);
  overflow-y: auto;
  padding: 18px 20px 14px;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
}
.detail::backdrop { background: rgba(20, 16, 32, 0.5); }
.detail-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 12px;
}
.detail-head h3 {
  flex: 1;
  margin: 0;
  font-size: 19px;
  letter-spacing: -0.01em;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.detail-line {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14.5px;
}
.detail-line > span:first-child { color: var(--muted); flex: none; }
.detail-line > span:last-child { text-align: right; overflow-wrap: anywhere; }
.detail h4 {
  margin: 18px 0 2px;
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.detail-note {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}
.detail-actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 16px;
}
.detail-actions .btn.tiny { padding: 7px 14px; font-size: 13.5px; }

/* ── Editing an open group ────────────────────────────────────────────────── */
/* A row that opens its details. Only a pointer affordance: the row already
   reads as a list item, and a hover tint on every row would make a page of
   numbers flicker as the mouse crosses it. */
.row.is-tappable { cursor: pointer; }
.row.is-tappable:hover { background: var(--surface); }
.row.is-tappable:focus { outline: none; }
.row.is-tappable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 8px;
}

.row-actions { display: flex; gap: 2px; flex: none; }
.btn.tiny {
  min-width: 0;
  padding: 4px 8px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: none;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.btn.tiny:hover { border-color: var(--border); color: var(--ink); }
.btn.tiny.danger:hover { border-color: var(--border); color: #c0392b; }
@media (prefers-color-scheme: dark) { .btn.tiny.danger:hover { color: #ff8a7a; } }

.title-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.title-row h1 { min-width: 0; }

.rows.plain .row { gap: 8px; }
.row.tight { padding: 7px 0; font-size: 15px; }
.row .amount.date { font-weight: 500; font-size: 13px; color: var(--muted); }

/* Rows carry their own separators rather than a wrapper border, so a list that
   renders empty leaves no stray line behind. */
.rows { list-style: none; margin: 0; padding: 0; }
.row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}
.row:last-child { border-bottom: none; }
.row.dim { opacity: 0.62; }
.row .grow { flex: 1; min-width: 0; }
.row strong { display: inline; font-weight: 650; font-size: 15px; }
.row .sub {
  display: block;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.4;
}
.row .amount { font-variant-numeric: tabular-nums; font-weight: 650; flex: none; }
.row .amount.pos { color: #1e8449; }
.row .amount.neg { color: #c0392b; }
.row .amount.flat { color: var(--muted); }
@media (prefers-color-scheme: dark) {
  .row .amount.pos { color: #6ed49a; }
  .row .amount.neg { color: #ff8a7a; }
}

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
}
.avatar.fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-2, var(--surface));
  color: #2b2440;
  font-weight: 700;
  font-size: 14px;
}

.chip {
  display: inline-block;
  margin-left: 7px;
  padding: 1px 7px;
  border-radius: 6px;
  background: var(--accent-2, var(--surface));
  color: #2b2440;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: 1px;
}

/* Confirmation after a write. Deliberately its own element rather than reusing
   the balances note — they say different things and would otherwise overwrite
   each other. */
.flash {
  margin: 0 0 4px;
  padding: 10px 14px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  color: var(--muted);
  font-size: 14px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px;
  margin-bottom: 18px;
}
.stack { display: flex; flex-direction: column; gap: 12px; }
.stack label { font-size: 13.5px; color: var(--muted); font-weight: 600; }
.pair { display: flex; gap: 12px; }
.pair > * { flex: 1; min-width: 0; }

input, select {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
}
input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

fieldset {
  border: none;
  padding: 0;
  margin: 0;
}
fieldset legend {
  padding: 0;
  font-size: 13.5px;
  color: var(--muted);
  font-weight: 600;
}
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.chip-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}
.chip-check input { width: auto; margin: 0; }

button.btn { border: none; cursor: pointer; font: inherit; font-weight: 650; }
.btn.small {
  min-width: 0;
  padding: 7px 14px;
  font-size: 14px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 10px;
}
form .btn { min-width: 0; }

main.group .state h1 { margin-top: 24px; }
