:root {
  --bg: #f4f5f7;
  --card: #ffffff;
  --subcard: #f9fafb;
  --field: #ffffff;
  --th-bg: #f9fafb;
  --border: #e2e5ea;
  --text: #1a1f2b;
  --muted: #6b7280;
  --primary: #2563eb;
  --primary-hover: #1d4ed8;
  --danger: #dc2626;
  --success: #16a34a;
  --warn: #d97706;
  --tag-bg: #f3f4f6;
  --tag-fg: #6b7280;
  --tag-active-bg: #dcfce7;
  --tag-active-fg: #15803d;
  --tag-inactive-bg: #fee2e2;
  --tag-inactive-fg: #991b1b;
  --tag-inv-bg: #dbeafe;
  --tag-inv-fg: #1e40af;
  --tag-exp-bg: #fef3c7;
  --tag-exp-fg: #92400e;
  --err-bg: #fee2e2;
  --err-fg: #991b1b;
  --ok-bg: #dcfce7;
  --ok-fg: #166534;
  --topbar-bg: #ffffff;
  --tabs-bg: #ffffff;
  --btn-secondary-bg: #ffffff;
  --btn-secondary-hover: #f3f4f6;
  --overlay: rgba(0, 0, 0, 0.5);
  --shadow-sm: 0 1px 2px rgba(15, 20, 25, 0.03), 0 1px 3px rgba(15, 20, 25, 0.05);
  --shadow-md: 0 4px 12px rgba(15, 20, 25, 0.06), 0 2px 6px rgba(15, 20, 25, 0.04);
  --shadow-lg: 0 12px 32px rgba(15, 20, 25, 0.12);
  --focus-ring: rgba(37, 99, 235, 0.15);
  --seg-track: #eef0f3;
  --seg-active: #ffffff;
  --row-inv-stripe: #93c5fd;
  --row-exp-stripe: #fcd34d;
  --inv-glow: rgba(59, 130, 246, 0.32);
  --exp-glow: rgba(217, 119, 6, 0.28);
  --inv-ring: rgba(59, 130, 246, 0.55);
  --exp-ring: rgba(217, 119, 6, 0.55);
  --inv-bar: #3b82f6;
  --exp-bar: #d97706;
  --cost-zero: #cbd0d8;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #0f1419;
  --card: #1a1f2b;
  --subcard: #232a39;
  --field: #232a39;
  --th-bg: #232a39;
  --border: #2a3346;
  --text: #e4e7eb;
  --muted: #8b96a8;
  --primary: #3b82f6;
  --primary-hover: #60a5fa;
  --danger: #ef4444;
  --success: #22c55e;
  --warn: #f59e0b;
  --tag-bg: #232a39;
  --tag-fg: #8b96a8;
  --tag-active-bg: #14532d;
  --tag-active-fg: #86efac;
  --tag-inactive-bg: #7f1d1d;
  --tag-inactive-fg: #fca5a5;
  --tag-inv-bg: #1e3a8a;
  --tag-inv-fg: #93c5fd;
  --tag-exp-bg: #78350f;
  --tag-exp-fg: #fcd34d;
  --err-bg: #4a1414;
  --err-fg: #fca5a5;
  --ok-bg: #0f3a1f;
  --ok-fg: #86efac;
  --topbar-bg: #1a1f2b;
  --tabs-bg: #1a1f2b;
  --btn-secondary-bg: #232a39;
  --btn-secondary-hover: #2d3548;
  --overlay: rgba(0, 0, 0, 0.7);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2), 0 1px 3px rgba(0, 0, 0, 0.15);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.2);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.4);
  --focus-ring: rgba(59, 130, 246, 0.22);
  --seg-track: #0f1419;
  --seg-active: #2d3548;
  --row-inv-stripe: #60a5fa;
  --row-exp-stripe: #d97706;
  --inv-glow: rgba(96, 165, 250, 0.4);
  --exp-glow: rgba(245, 158, 11, 0.36);
  --inv-ring: rgba(96, 165, 250, 0.65);
  --exp-ring: rgba(245, 158, 11, 0.6);
  --inv-bar: #60a5fa;
  --exp-bar: #f59e0b;
  --cost-zero: #2a3346;
  color-scheme: dark;
}

* { box-sizing: border-box; }

:root {
  --topbar-h: 58px;
  --tabs-h: 44px;
}

html, body {
  height: 100%;
  margin: 0;
}
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.4;
  transition: background-color 0.2s ease, color 0.2s ease;
  /* Body itself does NOT scroll — see .app-scroll. Removing body scroll is
     the single most effective fix for iOS Safari "fixed elements unstick
     during momentum scroll" because fixed elements no longer race against
     a body-level scroll context. */
  overflow: hidden;
}

/* The actual scroll container that takes the role body normally would.
   Fixed elements (.topbar, .tabs in portrait) live OUTSIDE of this and
   anchor to the viewport directly, so they stay rock-solid throughout
   any scroll on iOS. */
.app-scroll {
  position: fixed;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  padding-top: var(--topbar-h);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
@media (orientation: portrait) {
  .app-scroll {
    padding-top: calc(var(--topbar-h) + var(--tabs-h));
  }
}

a { color: var(--primary); text-decoration: none; }
button { font-family: inherit; font-size: inherit; cursor: pointer; }

.topbar {
  background: var(--topbar-bg);
  padding: 10px 16px;
  /* iOS standalone PWA with status-bar-style=black-translucent extends the
     web view under the status bar — add the system inset so content sits
     below it. The max() on horizontal sides handles landscape iPhone notch. */
  padding-top: calc(10px + env(safe-area-inset-top, 0px));
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  /* position:fixed instead of sticky — iOS Safari occasionally fails to paint
     sticky topbars above heavy box-shadow content (the kind-investment glow),
     letting the scrolled content show through. fixed avoids that bug entirely.
     The body padding-top reserves the equivalent space. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  /* Force a GPU compositor layer so iOS Safari keeps the fixed element
     properly anchored during momentum scrolls (without this, iOS sometimes
     "detaches" fixed elements until the scroll finishes). */
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.topbar h1 { margin: 0; font-size: 18px; }
.topbar .spacer { flex: 1; }
.topbar .user { color: var(--muted); font-size: 14px; }

.tabs {
  background: var(--tabs-bg);
  border-bottom: 1px solid var(--border);
}
/* The actual scroll container — kept SEPARATE from the fixed positioning on
   .tabs so iOS Safari doesn't lose the fixed anchor during long scrolls
   (mixing position:fixed + overflow:auto on one element is a known WebKit
   bug). */
.tabs-inner {
  display: flex;
  gap: 4px;
  padding: 0 16px;
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
  overflow-x: auto;
}
/* Tabs (area B) are fixed in portrait so the user can switch sections
   without scrolling back up. In landscape they scroll away — vertical
   space is precious on a phone/tablet held sideways.
   Why fixed (not sticky) on iOS specifically: Safari "unsticks" sticky
   elements after a few seconds of momentum scrolling — a long-standing
   WebKit bug. Fixed avoids the bug entirely. The body padding-top is
   topped up to include the tabs height so content doesn't slide under. */
@media (orientation: portrait) {
  .tabs {
    position: fixed;
    /* Position at viewport top:0 then push down with translate3d — iOS Safari
       handles GPU-accelerated transform offsets more reliably than non-zero
       top values during momentum scroll. Setting top != 0 was causing the
       tabs to "scroll away" after a few seconds of fast flicks. */
    top: 0;
    left: 0;
    right: 0;
    -webkit-transform: translate3d(0, var(--topbar-h), 0);
    transform: translate3d(0, var(--topbar-h), 0);
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    z-index: 9;
  }
}
.tabs button {
  background: none;
  border: none;
  padding: 12px 14px;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
@media (hover: hover) {
  .tabs button:hover { color: var(--text); }
}
.tabs button.active { color: var(--primary); border-color: var(--primary); }

.container { padding: 16px; max-width: 1100px; margin: 0 auto; }

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 16px;
  box-shadow: var(--shadow-sm);
}
.card h2 { margin: 0 0 12px 0; font-size: 16px; }
.card.subcard { background: var(--subcard); box-shadow: none; }
.card.kind-investment {
  border-color: var(--inv-ring);
  box-shadow:
    inset 0 4px 0 var(--inv-bar),
    0 0 0 1px var(--inv-ring),
    0 10px 28px var(--inv-glow),
    var(--shadow-sm);
  padding-top: 20px;
}
.card.kind-expense {
  border-color: var(--exp-ring);
  box-shadow:
    inset 0 4px 0 var(--exp-bar),
    0 0 0 1px var(--exp-ring),
    0 10px 28px var(--exp-glow),
    var(--shadow-sm);
  padding-top: 20px;
}

.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row > * { flex: 1 1 160px; min-width: 0; }

.date-pair {
  display: flex;
  gap: 8px;
  flex: 1 1 260px;
}
.date-pair > div { flex: 1 1 0; min-width: 0; }

.segmented {
  display: flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 3px;
  background: var(--seg-track);
  gap: 2px;
  width: 100%;
}
.segmented button {
  flex: 1 1 0;
  padding: 8px 10px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 500;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
  min-height: 38px;
  font-family: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.segmented button.active {
  background: var(--primary);
  color: #ffffff;
  font-weight: 600;
  box-shadow: 0 2px 6px var(--focus-ring);
}
@media (hover: hover) {
  .segmented button:not(.active):hover { color: var(--text); }
}
.segmented.kind-tinted button.active[data-val="investment"],
.segmented.tint-investment button.active {
  background: var(--inv-bar);
  color: #ffffff;
  box-shadow: 0 2px 6px var(--inv-glow);
}
.segmented.kind-tinted button.active[data-val="expense"],
.segmented.tint-expense button.active {
  background: var(--exp-bar);
  color: #ffffff;
  box-shadow: 0 2px 6px var(--exp-glow);
}

label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
/* Password input with eye-toggle button on the right. */
.pwd-field {
  position: relative;
}
.pwd-field input {
  padding-right: 44px;
}
.pwd-field .pwd-toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  background: transparent;
  border: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  padding: 0;
}
.pwd-field .pwd-toggle:hover { color: var(--text); }
.pwd-field .pwd-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Chip-style label used in admin panel checkbox lists (assigned objects).
   Overrides the default block display so checkbox and text sit on one line. */
label.chip-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--field);
  color: var(--text);
  font-size: 14px;
  margin-bottom: 0;
  cursor: pointer;
}
input, select, textarea {
  width: 100%;
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--field);
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
/* macOS Safari renders native <select> noticeably shorter than <input>
   despite identical padding — explicit min-height aligns them. Date inputs
   also get this for consistency with the @supports rule below. */
input, select {
  min-height: 40px;
}
input[type="date"] {
  -webkit-appearance: none;
  appearance: none;
  -webkit-min-logical-width: 0;
  max-width: 100%;
  min-height: 38px;
  line-height: 1.2;
  text-align: left;
  display: block;
  background-clip: padding-box;
}
input[type="date"]::-webkit-date-and-time-value {
  text-align: left;
  min-height: 1em;
}

/* iOS Safari: prevent input zoom on focus (triggered when font-size < 16px) */
@supports (-webkit-touch-callout: none) {
  input, select, textarea { font-size: 16px; }
}
textarea { resize: vertical; min-height: 60px; }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.btn {
  background: var(--primary);
  color: #fff;
  border: none;
  padding: 10px 16px;
  border-radius: 6px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background-color 0.15s ease, transform 0.08s ease, box-shadow 0.15s ease;
}
.btn:hover { background: var(--primary-hover); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn.secondary { background: var(--btn-secondary-bg); color: var(--text); border: 1px solid var(--border); }
.btn.secondary:hover { background: var(--btn-secondary-hover); }
.btn.secondary.active { border-color: var(--primary); color: var(--primary); }
.btn.danger { background: var(--danger); color: #fff; }
.btn.danger:hover { filter: brightness(1.05); }
.btn.kind-investment { background: var(--inv-bar); color: #fff; }
.btn.kind-investment:hover { background: var(--inv-bar); filter: brightness(0.93); }
.btn.kind-expense { background: var(--exp-bar); color: #fff; }
.btn.kind-expense:hover { background: var(--exp-bar); filter: brightness(0.93); }
.btn.small { padding: 6px 10px; font-size: 13px; gap: 4px; }

table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--border); }
th { background: var(--th-bg); font-weight: 600; color: var(--muted); font-size: 13px; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.num.cost-investment { color: var(--inv-bar); font-weight: 600; }
td.num.cost-expense { color: var(--exp-bar); font-weight: 600; }
td.num.cost-zero { color: var(--cost-zero); }

/* Records table: cap free-text columns (Object, Note) so a single long
   word like "longstringwithoutspaces" can't blow out the row width.
   Inner div uses webkit line-clamp for max 2 lines; word-break:break-word
   handles the unbroken-string case. */
table.records-table { table-layout: auto; width: 100%; }
table.records-table td.cell-clip { max-width: 220px; overflow: hidden; }
table.records-table td.cell-clip > .clip-inner {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
  word-break: break-word;
}
@media (max-width: 600px) {
  table.records-table td.cell-clip { max-width: 140px; }
}
@media (orientation: landscape) and (max-width: 900px) {
  table.records-table td.cell-clip { max-width: 200px; }
}
tr:last-child td { border-bottom: none; }
tbody tr { transition: background-color 0.15s ease; }
@media (hover: hover) {
  tbody tr:hover { background: var(--th-bg); }
}
tbody tr.row-investment > td:first-child { box-shadow: inset 2px 0 0 var(--row-inv-stripe); }
tbody tr.row-expense > td:first-child { box-shadow: inset 2px 0 0 var(--row-exp-stripe); }

.balance-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
/* Cap at 3 columns on wider viewports so 6 tiles always wrap as 3+3 instead
   of 5+1 / 4+2 depending on width. */
@media (min-width: 600px) {
  .balance-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Category breakdown shown under the value on expense tiles. */
.balance-tile .cat-breakdown {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}
.balance-tile .cat-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}
.balance-tile .cat-label { color: var(--muted); }
.balance-tile .cat-amount { font-variant-numeric: tabular-nums; }
.balance-tile {
  background: var(--subcard);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
@media (hover: hover) {
  .balance-tile:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
}
.balance-tile .label {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  display: flex;
  align-items: center;
  gap: 6px;
}
.balance-tile .value {
  font-size: 28px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  margin-top: 6px;
  line-height: 1.1;
}
.pos { color: var(--success); }
.neg { color: var(--danger); }

.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 12px;
  background: var(--tag-bg);
  color: var(--tag-fg);
}
.tag.active { background: var(--tag-active-bg); color: var(--tag-active-fg); }
.tag.inactive { background: var(--tag-inactive-bg); color: var(--tag-inactive-fg); }
.tag.inv { background: var(--tag-inv-bg); color: var(--tag-inv-fg); }
.tag.exp { background: var(--tag-exp-bg); color: var(--tag-exp-fg); }

.err { background: var(--err-bg); color: var(--err-fg); padding: 10px; border-radius: 6px; margin-bottom: 12px; }
.ok { background: var(--ok-bg); color: var(--ok-fg); padding: 10px; border-radius: 6px; margin-bottom: 12px; }

.login-wrap {
  /* With body overflow:hidden, login needs to be its own scroll container
     so virtual keyboards / small viewports can still scroll content. */
  position: fixed;
  inset: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
  padding-bottom: max(20px, env(safe-area-inset-bottom, 0px));
  gap: 14px;
}
.login-wrap .card { width: 100%; max-width: 360px; margin: 0; }

.flex-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.muted { color: var(--muted); font-size: 13px; }

.mobile-scroll { overflow-x: auto; }

.settings-bar { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

.pager {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; flex-wrap: wrap; margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--border);
}
.pager-ctrls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pager-size { width: auto; padding: 6px 8px; }
button[disabled] { opacity: 0.5; cursor: not-allowed; }

.warn-text { color: var(--danger); font-weight: bold; }

.modal-bg {
  position: fixed; inset: 0;
  background: var(--overlay);
  display: flex; align-items: center; justify-content: center;
  z-index: 100; padding: 16px;
  animation: fade-in 0.15s ease-out;
}
.modal-bg > .card {
  box-shadow: var(--shadow-lg);
  animation: card-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes card-in {
  from { transform: translateY(-8px) scale(0.98); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}

.skeleton {
  height: 14px;
  margin: 10px 0;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--border) 25%, var(--subcard) 50%, var(--border) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s infinite;
}
.skeleton.short { width: 60%; }
.skeleton.medium { width: 80%; }
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.toast-host {
  position: fixed;
  bottom: 16px;
  right: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 200;
  pointer-events: none;
  max-width: calc(100% - 32px);
}
.toast {
  background: var(--card);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 8px;
  padding: 10px 14px;
  box-shadow: var(--shadow-md);
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: auto;
  animation: toast-in 0.25s ease-out;
  color: var(--text);
}
.toast.ok { border-left-color: var(--success); }
.toast.ok > svg { color: var(--success); }
.toast.err { border-left-color: var(--danger); }
.toast.err > svg { color: var(--danger); }
.toast.leaving { animation: toast-out 0.2s ease-in forwards; }
@keyframes toast-in {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
@keyframes toast-out {
  to { transform: translateY(10px); opacity: 0; }
}
@media (max-width: 600px) {
  .toast-host { left: 16px; right: 16px; bottom: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

.btn.icon-only { padding: 6px 8px; }

@media (max-width: 600px) {
  /* topbar stays sticky on phones too (user requirement: area A always pinned) */
  .topbar h1 { font-size: 16px; }
  th, td { padding: 6px 8px; }
  .balance-tile { padding: 12px; }
  .balance-tile .value { font-size: 22px; }
  .card { padding: 14px; }
  .tabs button { padding: 10px 12px; gap: 4px; }
}
