@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

/* ============================================================
   SLR Family Receipts — receipts.slr.family

   The design system from documents.slr.family (SLR Family OS),
   carried over token for token so the two sites read as one
   product: dark left rail, light workspace, dense list views.

   One deliberate omission: the vault's `.pill` filter control.
   Filtering here is done with plain selects, so no filter state
   is ever carried by a block of colour.
   ============================================================ */

:root {
  /* Brand — the vault's violet */
  --accent:          #5b4fe9;
  --accent-hover:    #4a3ed6;
  --accent-soft:     #eeecfd;
  --accent-ring:     rgba(91, 79, 233, .16);

  /* Rail */
  --rail:            #1b2a3a;
  --rail-hover:      #253a4f;
  --rail-active:     #0f1b26;
  --rail-text:       #b9c6d3;
  --rail-faint:      #6f8298;

  /* Surfaces */
  --bg:              #f4f5f7;
  --surface:         #ffffff;
  --border:          #e2e5ea;
  --border-strong:   #cbd2db;

  /* Text */
  --text:            #1a2733;
  --text-muted:      #5c6b7a;
  --text-faint:      #8a97a4;

  /* State */
  --danger:          #d0342c;
  --danger-soft:     #fdeceb;
  --warn:            #c2610a;
  --warn-soft:       #fdf1e4;
  --info:            #1f6fd0;
  --info-soft:       #e9f1fb;
  --ok:              #217a44;
  --ok-soft:         #e8f6ee;

  --radius:          8px;
  --radius-sm:       6px;
  --shadow:          0 1px 2px rgba(20, 35, 50, .08);
  --shadow-lg:       0 8px 24px -8px rgba(20, 35, 50, .25);
  --shadow-modal:    0 24px 60px -12px rgba(20, 35, 50, .35);

  --rail-w:          232px;
  --topbar-h:        56px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
input, select, textarea { font: inherit; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
::selection { background: var(--accent-soft); color: var(--text); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  background: #c8d0d9; border-radius: 99px;
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: #adb8c4; background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }

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

[hidden] { display: none !important; }

/* ============================================================
   Layout
   ============================================================ */

.shell { display: flex; min-height: 100vh; }

.rail {
  width: var(--rail-w);
  flex: none;
  background: var(--rail);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

.rail-brand {
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 16px;
  color: #fff;
  font-weight: 700;
  font-size: 14.5px;
  letter-spacing: .01em;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  white-space: nowrap;
  overflow: hidden;
  flex: none;
}

.rail-mark {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .03em;
}

.rail-nav { padding: 10px 8px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; }

.rail-section {
  padding: 14px 12px 6px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--rail-faint);
  white-space: nowrap;
}

.rail-link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--rail-text);
  white-space: nowrap;
  overflow: hidden;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}

.rail-link:hover { background: var(--rail-hover); color: #fff; }

.rail-link.is-active {
  background: var(--rail-active);
  color: #fff;
  box-shadow: inset 3px 0 0 var(--accent);
}

.rail-link .ico { width: 17px; height: 17px; flex: none; display: grid; place-items: center; }

.rail-foot {
  padding: 12px;
  border-top: 1px solid rgba(255, 255, 255, .08);
  font-size: 11px;
  color: var(--rail-faint);
  white-space: nowrap;
  overflow: hidden;
  flex: none;
}

.rail-scrim { display: none; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* ---- Top bar ---- */

.topbar {
  height: var(--topbar-h);
  flex: none;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
  position: sticky;
  top: 0;
  z-index: 40;
}

.topbar-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  padding: 4px;
}

.topbar-search { position: relative; flex: 1; max-width: 520px; }

.topbar-search input {
  width: 100%;
  height: 34px;
  padding: 0 12px 0 34px;
  font-size: 13.5px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}

.topbar-search input:focus {
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.topbar-search .ico {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-faint);
  pointer-events: none;
  display: grid;
  place-items: center;
}

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }

.topbar-user { display: flex; align-items: center; gap: 9px; }

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  overflow: hidden;
  flex: none;
}

.avatar img { width: 100%; height: 100%; object-fit: cover; }

.topbar-user-meta { line-height: 1.25; min-width: 0; }
.topbar-user-meta strong { display: block; font-size: 13px; font-weight: 600; }
.topbar-user-meta span { display: block; font-size: 11.5px; color: var(--text-faint); }

/* ---- Content ---- */

.content { flex: 1; padding: 24px; max-width: 1280px; width: 100%; }

.page-head { margin-bottom: 20px; display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.page-head-text { flex: 1; min-width: 220px; }
.page-head h1 { font-size: 22px; font-weight: 700; letter-spacing: -.01em; }
.page-head p { color: var(--text-muted); margin-top: 3px; font-size: 13.5px; }
.page-head-actions { display: flex; align-items: center; gap: 8px; }

.grid { display: grid; gap: 16px; }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ============================================================
   Buttons
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 36px;
  padding: 0 16px;
  font-size: 13.5px;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, opacity .14s ease;
  white-space: nowrap;
}

.btn:hover { background: #f3f5f7; }
.btn:disabled { opacity: .55; cursor: not-allowed; }

.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn-ghost { background: none; border-color: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: #eef1f4; color: var(--text); }

.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover:not(:disabled) { background: #b82c25; border-color: #b82c25; }

.btn-sm { height: 30px; padding: 0 11px; font-size: 12.5px; }
.btn-block { width: 100%; }

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  border: none;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
  flex: none;
}
.icon-btn:hover { background: #eef1f4; color: var(--text); }
.icon-btn.is-danger:hover { background: var(--danger-soft); color: var(--danger); }
.icon-btn:disabled { opacity: .5; cursor: not-allowed; }

/* ============================================================
   Cards, lists, tables
   ============================================================ */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.list-head {
  display: grid;
  gap: 12px;
  padding: 9px 18px;
  background: #fafbfc;
  border-bottom: 1px solid var(--border);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.list-row {
  display: grid;
  gap: 12px;
  align-items: center;
  padding: 11px 18px;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
  transition: background .12s ease;
}

.list-row:last-child { border-bottom: none; }
.list-row:hover { background: #fafbfc; }
.list-row.is-clickable { cursor: pointer; }

.list-primary { font-weight: 600; color: var(--text); }
.list-sub { font-size: 12px; color: var(--text-faint); margin-top: 1px; }
.list-cell-muted { color: var(--text-muted); }
.list-actions { display: flex; align-items: center; justify-content: flex-end; gap: 2px; }

.amount { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A receipt's own thumbnail, or the file-type square when it is a PDF. */
.thumb {
  width: 38px;
  height: 42px;
  flex: none;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg);
  display: grid;
  place-items: center;
  overflow: hidden;
  color: var(--text-faint);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: .04em;
}
.thumb img { width: 100%; height: 100%; object-fit: cover; }

/* ---- Stats ---- */

.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 14px 16px;
}

.stat-label { font-size: 11px; font-weight: 650; letter-spacing: .07em; text-transform: uppercase; color: var(--text-faint); }
.stat-value { font-size: 26px; font-weight: 700; margin-top: 4px; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.stat-hint { font-size: 12px; color: var(--text-faint); margin-top: 2px; }

/* ---- Meta text ----
   Where the vault would reach for a coloured badge, a receipt's channel,
   type and place are plain text separated by a hairline dot. Nothing here
   ranks or warns, so nothing here needs colour to say so. */

.meta { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; font-size: 12px; color: var(--text-muted); }
.meta-sep { color: var(--border-strong); }
.meta-key { color: var(--text-faint); }

/* ---- Segmented control ---- */

.seg { display: inline-flex; background: #eef1f4; border-radius: var(--radius-sm); padding: 3px; gap: 2px; }
.seg button {
  height: 26px; padding: 0 11px; border: none; background: none;
  border-radius: 4px; font-size: 12.5px; font-weight: 600;
  color: var(--text-muted); cursor: pointer; transition: background .14s ease, color .14s ease;
  display: inline-flex; align-items: center; gap: 6px;
}
.seg button:hover { color: var(--text); }
.seg button.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow); }

/* ============================================================
   Filter bar

   Four selects on one row — location, city, channel, purchase
   type — plus a reset. Selects rather than pills: the list of
   places a family shops grows without limit, and a select does
   not have to be scrolled sideways to be read.
   ============================================================ */

.filters {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
  gap: 12px;
  align-items: end;
  margin-bottom: 16px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.filters .field { margin-bottom: 0; min-width: 0; }
.filters-reset { align-self: end; }

.filter-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  font-size: 12.5px;
  color: var(--text-muted);
}
.filter-summary strong { color: var(--text); font-weight: 650; font-variant-numeric: tabular-nums; }

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.toolbar-end { margin-left: auto; }

/* ============================================================
   Forms
   ============================================================ */

.field { margin-bottom: 14px; }

.label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 6px;
}

.label .optional { text-transform: none; letter-spacing: 0; font-weight: 500; color: var(--border-strong); }

.input, .select, .textarea {
  width: 100%;
  height: 36px;
  padding: 0 11px;
  font-size: 13.5px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.textarea { height: auto; padding: 9px 11px; resize: vertical; line-height: 1.5; }

.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.input::placeholder, .textarea::placeholder { color: var(--text-faint); }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* Online / In-person. A two-way choice, so the segmented control the vault
   already uses for view style — not a coloured pill. */
.choice { display: flex; gap: 8px; }
.choice button {
  flex: 1;
  height: 36px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.choice button:hover { background: #f3f5f7; color: var(--text); }
.choice button.is-active {
  border-color: var(--accent);
  color: var(--text);
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* ============================================================
   Notices, empty states, feedback
   ============================================================ */

.notice {
  display: flex;
  gap: 10px;
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.5;
}
.notice .ico { flex: none; margin-top: 1px; color: var(--text-faint); }
.notice.is-info   { background: var(--info-soft);   border-color: #cfe0f5; color: #14508f; }
.notice.is-info .ico   { color: var(--info); }
.notice.is-warn   { background: var(--warn-soft);   border-color: #f3ddc0; color: #8a4507; }
.notice.is-warn .ico   { color: var(--warn); }
.notice.is-danger { background: var(--danger-soft); border-color: #f5cdca; color: #9c2620; }
.notice.is-danger .ico { color: var(--danger); }

.empty { padding: 56px 24px; text-align: center; }
.empty .ico { color: var(--border-strong); margin-bottom: 12px; display: inline-grid; }
.empty h3 { font-size: 15px; font-weight: 650; margin-bottom: 4px; }
.empty p { font-size: 13px; color: var(--text-muted); max-width: 42ch; margin: 0 auto; }
.empty .empty-action { margin-top: 18px; }

.loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 56px 24px; color: var(--text-faint); font-size: 13.5px; }

.spinner {
  width: 16px; height: 16px; flex: none;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
.spinner.on-accent { border-color: rgba(255,255,255,.35); border-top-color: #fff; }
@keyframes spin { to { transform: rotate(360deg); } }

.progress { height: 5px; background: #eef1f4; border-radius: 99px; overflow: hidden; }
.progress span { display: block; height: 100%; background: var(--accent); border-radius: 99px; transition: width .2s ease; }

/* ============================================================
   Overlays
   ============================================================ */

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(15, 27, 38, .45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
  animation: fade .16s ease both;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.modal {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-modal);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: pop .18s cubic-bezier(.2,.7,.4,1) both;
}
@keyframes pop { from { opacity: 0; transform: translateY(8px) scale(.99); } to { opacity: 1; transform: none; } }

.modal-head {
  padding: 15px 18px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
}
.modal-head h2 { font-size: 15.5px; font-weight: 650; }
.modal-head p { font-size: 12.5px; color: var(--text-faint); margin-top: 1px; }
.modal-head .icon-btn { margin-left: auto; }

.modal-body { padding: 18px; overflow-y: auto; flex: 1; }

.modal-foot {
  padding: 13px 18px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  flex: none;
}
.modal-foot .modal-foot-start { margin-right: auto; }

.menu {
  position: fixed;
  z-index: 200;
  min-width: 178px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 4px;
  animation: pop .14s ease both;
}

.menu button, .menu a {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 10px;
  border: none;
  background: none;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  transition: background .12s ease;
}
.menu button:hover, .menu a:hover { background: #f3f5f7; }
.menu .is-danger { color: var(--danger); }
.menu .is-danger:hover { background: var(--danger-soft); }
.menu-sep { height: 1px; background: var(--border); margin: 4px 6px; }

.dropzone {
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  background: #fafbfc;
  padding: 28px 24px;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.dropzone:hover { border-color: var(--accent); background: var(--accent-soft); }
.dropzone.is-dragging { border-color: var(--accent); background: var(--accent-soft); }
.dropzone .ico { color: var(--text-faint); margin-bottom: 10px; display: inline-grid; }
.dropzone.is-dragging .ico, .dropzone:hover .ico { color: var(--accent); }
.dropzone h3 { font-size: 14.5px; font-weight: 650; margin-bottom: 3px; }
.dropzone p { font-size: 12.5px; color: var(--text-muted); }

/* Files staged in the form, and files already on a saved receipt. */
.filelist { display: grid; gap: 6px; margin-top: 10px; }
.fileitem {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 12.5px;
  min-width: 0;
}
.fileitem .thumb { width: 30px; height: 34px; }
.fileitem-name { min-width: 0; flex: 1; }
.fileitem-size { color: var(--text-faint); flex: none; font-variant-numeric: tabular-nums; }

/* ============================================================
   Gallery

   The receipts as receipts — the paper itself, not a row about
   it. A photographed till slip is recognisable at a glance in a
   way "Kroger · $41.02" never is, so this is the default view.
   ============================================================ */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 12px;
}

.shot {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  transition: border-color .14s ease, box-shadow .14s ease, transform .1s ease;
  -webkit-tap-highlight-color: transparent;
}

.shot:hover  { border-color: var(--border-strong); box-shadow: var(--shadow-lg); }
.shot:active { transform: scale(.995); }

/* Taller than wide: a till slip is a long strip, and a square crop throws
   away the half with the total on it. */
.shot-img {
  position: relative;
  aspect-ratio: 3 / 4;
  background: var(--bg);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.shot-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}

/* No photo, or a PDF: say which rather than showing a broken frame. */
.shot-none {
  display: grid;
  place-items: center;
  gap: 6px;
  color: var(--text-faint);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.shot-count {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 2px 7px;
  border-radius: 99px;
  background: rgba(15, 27, 38, .72);
  color: #fff;
  font-size: 11px;
  font-weight: 650;
}

.shot-body {
  padding: 10px 12px 11px;
  border-top: 1px solid var(--border);
}

.shot-top { display: flex; align-items: baseline; gap: 8px; }
.shot-name { font-size: 13px; font-weight: 650; min-width: 0; }
.shot-amount { margin-left: auto; flex: none; font-size: 13px; font-weight: 650; font-variant-numeric: tabular-nums; }
.shot-sub { font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }

@media (max-width: 720px) {
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .shot-body { padding: 9px 10px 10px; }
  .shot-name, .shot-amount { font-size: 12.5px; }
}

/* ---- Viewer: the receipt image itself, full size ---- */
.viewer {
  max-width: 860px;
}
.viewer-body { background: #0f1b26; display: grid; place-items: center; padding: 0; }
.viewer-body img { max-width: 100%; max-height: 70vh; display: block; }
.viewer-body iframe { width: 100%; height: 70vh; border: none; background: #fff; }

.viewer-nav { display: flex; align-items: center; gap: 4px; }
.viewer-nav span {
  font-size: 12px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  min-width: 40px;
  text-align: center;
}

@media (max-width: 720px) {
  .viewer-body img { max-height: 58vh; }
  .viewer-body iframe { height: 58vh; }
  /* Four controls will not sit on one phone-width row. */
  .viewer .modal-foot { flex-wrap: wrap; }
  .viewer .modal-foot .btn { flex: 1; }
}

/* ============================================================
   Auth screen
   ============================================================ */

.auth {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(900px 460px at 50% -12%, #24374b 0%, transparent 70%),
    var(--rail);
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border-radius: 10px;
  box-shadow: var(--shadow-modal);
  padding: 28px;
  animation: pop .22s cubic-bezier(.2,.7,.4,1) both;
}

.auth-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; }
.auth-brand .rail-mark { width: 30px; height: 30px; font-size: 10.5px; }
.auth-brand strong { font-size: 16px; font-weight: 700; letter-spacing: -.01em; display: block; }
.auth-brand span { font-size: 12px; color: var(--text-faint); }

.auth-card h1 { font-size: 19px; font-weight: 700; letter-spacing: -.015em; margin-bottom: 5px; }
.auth-card > p { font-size: 13px; color: var(--text-muted); margin-bottom: 20px; line-height: 1.55; }

.auth-foot {
  margin-top: 18px;
  padding-top: 15px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--text-faint);
}

.auth-note { text-align: center; font-size: 12.5px; color: #8fa1b3; margin-top: 16px; }
.auth-note a { color: #cfd9e3; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.auth-note a:hover { color: #fff; }

/* ============================================================
   Card view — the same rows in a stacked shape
   ============================================================ */

.entity-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
}

.entity-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 15px;
  transition: border-color .14s ease, box-shadow .14s ease, transform .1s ease;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
  width: 100%;
  cursor: pointer;
}

.entity-card:hover  { border-color: var(--border-strong); box-shadow: var(--shadow-lg); }
.entity-card:active { transform: scale(0.995); }

.entity-card-top { display: flex; align-items: flex-start; gap: 11px; }
.entity-card-title { font-size: 14px; font-weight: 650; letter-spacing: -.005em; }
.entity-card-sub { font-size: 12.5px; color: var(--text-faint); margin-top: 1px; }

.entity-card-facts { display: grid; gap: 5px; }
.entity-card-fact {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 12.5px;
}
.entity-card-fact dt { color: var(--text-faint); flex: none; }
.entity-card-fact dd { color: var(--text); text-align: right; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================================================
   Charts

   Hand-drawn SVG, one hue. A month that cost more is a taller
   bar; it is not a worse month, so nothing here changes colour
   to imply that it is. Everything scales to its container, and
   the month chart scrolls sideways inside its own box rather
   than squeezing twelve labels into a phone's width.
   ============================================================ */

.chart-card { padding: 16px 18px 14px; }
.chart-card-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.chart-card-head h2 { font-size: 14px; font-weight: 650; letter-spacing: -.005em; }
.chart-card-head p { font-size: 12px; color: var(--text-faint); margin-left: auto; }
.chart-card-head .btn { margin-left: 10px; align-self: center; }

/* ---- Map ----
   Off by default, so nothing is requested from the tile server until it is
   asked for. Leaflet needs a height in CSS; it cannot infer one. */

.map {
  height: 380px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  z-index: 0; /* keeps Leaflet's panes under the modals and the tab bar */
}

.map .leaflet-container { font: inherit; }
.map .leaflet-popup-content { font-size: 12.5px; line-height: 1.55; }
.map .leaflet-popup-content a { color: var(--accent); font-weight: 600; }

/* Months. A scroll container so the bars keep a legible minimum width. */
.chart-scroll { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
.chart-scroll::-webkit-scrollbar { height: 6px; }

.bars {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  height: 168px;
  min-width: 100%;
  padding-top: 18px;
}

.bar-col {
  flex: 1 0 34px;
  min-width: 34px;
  height: 100%;
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 6px;
  justify-items: center;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.bar-track { width: 100%; height: 100%; display: flex; align-items: flex-end; position: relative; }

.bar-fill {
  width: 100%;
  border-radius: 4px 4px 0 0;
  background: var(--accent);
  opacity: .82;
  min-height: 2px;
  transition: opacity .14s ease;
}
.bar-col:hover .bar-fill { opacity: 1; }
.bar-col.is-empty .bar-fill { background: var(--border-strong); opacity: .5; }

.bar-value {
  position: absolute;
  left: 0; right: 0;
  bottom: 100%;
  margin-bottom: 5px;
  text-align: center;
  font-size: 10.5px;
  font-weight: 650;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.bar-label { font-size: 10.5px; font-weight: 600; color: var(--text-faint); white-space: nowrap; }
.bar-col.is-current .bar-label { color: var(--text); }

/* Breakdown by type / by place — a horizontal bar behind each label. */
.rank { display: grid; gap: 9px; }

.rank-row { display: grid; gap: 4px; }
.rank-top { display: flex; align-items: baseline; gap: 10px; font-size: 12.5px; }
.rank-name { min-width: 0; font-weight: 600; }
.rank-amount { margin-left: auto; flex: none; font-variant-numeric: tabular-nums; color: var(--text-muted); }

.rank-track { height: 7px; border-radius: 99px; background: #eef1f4; overflow: hidden; }
.rank-fill  { height: 100%; border-radius: 99px; background: var(--accent); opacity: .78; }

/* Two charts side by side on a wide screen, stacked on a phone. */
.chart-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }

/* ============================================================
   Mobile navigation

   Below 720px the rail is replaced by a bottom tab bar. Three
   destinations, thumb-height targets, and no drawer to open
   before you can move — this app is used standing in a shop
   doorway with a paper receipt in the other hand.
   ============================================================ */

.tabbar { display: none; }

@media (max-width: 1000px) {
  .filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .filters-reset { grid-column: 1 / -1; }
}

@media (max-width: 900px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .chart-pair { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  .rail { display: none; }

  .topbar { padding: 0 14px; gap: 10px; }
  .topbar-user-meta { display: none; }

  /* Room for the tab bar, plus the home indicator on an iPhone. */
  .content {
    padding: 16px 14px calc(84px + env(safe-area-inset-bottom));
  }

  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .stat { padding: 12px 13px; }
  .stat-value { font-size: 21px; }

  .filters { grid-template-columns: minmax(0, 1fr); padding: 13px 14px; }
  .filters-reset { grid-column: auto; }

  .page-head h1 { font-size: 19px; }
  .page-head { margin-bottom: 16px; }

  .modal { max-width: none; border-radius: 12px 12px 0 0; align-self: flex-end; max-height: 92vh; }
  .scrim { padding: 0; align-items: flex-end; }
  .modal-body { padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); }

  .entity-grid { grid-template-columns: minmax(0, 1fr); }
  .toolbar-end { margin-left: 0; }

  .list-head { display: none; }
  .list-row { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 4px; padding: 12px 14px; }
  .hide-sm { display: none !important; }

  .chart-card { padding: 14px 14px 12px; }
  .bars { height: 148px; }
  .map { height: 300px; }
  .chart-card-head { flex-wrap: wrap; }
  .chart-card-head .btn { margin-left: auto; }

  /* Touch targets: 16px inputs also stop iOS zooming the page on focus. */
  .input, .select, .textarea, .choice button { height: 42px; font-size: 16px; }
  .textarea { height: auto; }
  .btn { height: 42px; }
  .btn-sm { height: 34px; }
  .icon-btn { width: 36px; height: 36px; }

  .tabbar {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 90;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
  }

  .tabbar a {
    display: grid;
    justify-items: center;
    gap: 3px;
    padding: 9px 4px 8px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-faint);
    -webkit-tap-highlight-color: transparent;
  }
  .tabbar a.is-active { color: var(--accent); }
  .tabbar a .ico { display: grid; place-items: center; height: 22px; }
}

@media (max-width: 380px) {
  .grid-4 { grid-template-columns: minmax(0, 1fr); }
}
