/* ╔══════════════════════════════════════════════════════════════╗
   ║  Checko · Boutique SaaS theme · v2026-05-22h            ║
   ║  Tokens → Reset → Layout → Components → Views → Responsive   ║
   ╚══════════════════════════════════════════════════════════════╝ */

/* 启动 logo 过渡屏。放最前面 → 样式最早就绪,首帧就是成品,不闪。
   浅底固定不随主题:logo(checko-logo.png)是黑+橙,浅底才看得清;且与原生 splash
   一致(原生 splash 也是固定浅底 logo),两层无缝接。淡出由 app.js 控制(加 .hide)。 */
#bootSplash {
  position: fixed;
  inset: 0;
  z-index: 2147483646;   /* 盖住一切网页内容,仅次于键盘诊断条 */
  display: grid;
  place-items: center;
  background: #ffffff;
  padding: 12vh 12vw;
  transition: opacity 280ms ease;
}
#bootSplash img {
  width: min(62vw, 320px);
  height: auto;
  animation: bootSplashPulse 1.6s ease-in-out infinite;
}
#bootSplash.hide { opacity: 0; pointer-events: none; }
#bootSplash[hidden] { display: none; }
/* 「正在更新…」:只在 app.js 判定有更新(加 .updating)时露出,普通启动不显示。
   放在 logo 下方,浅灰小字,带缓慢呼吸暗示进行中。 */
/* ⚠️ 必须 absolute 脱离流。原来只写 opacity:0 —— 元素**照样占布局空间**,
   grid 把 [logo + 这行字] 一起居中,logo 就被顶到偏上(用户实拍「开屏 logo 没居中」)。
   脱离流之后 grid 里只剩 logo,才是真正的垂直居中;要显示时它绝对定位在 logo 下方。 */
#bootSplashMsg {
  position: absolute;
  left: 0; right: 0;
  top: calc(50% + 96px);      /* logo 中心下方,不参与居中计算 */
  margin: 0;
  /* ⚠️ 脱离流之后不再继承 grid 的 place-items:center —— 必须自己居中,
     否则文字贴到左边缘(用户实拍:「Memperbarui…」在最左侧)。 */
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  color: #8a94a6;
  letter-spacing: 0.02em;
  opacity: 0;                 /* 默认不显示 */
  transition: opacity 200ms ease;
}
#bootSplash.updating #bootSplashMsg { opacity: 1; animation: bootMsgPulse 1.4s ease-in-out infinite; }
@keyframes bootMsgPulse { 0%,100% { opacity: 0.5 } 50% { opacity: 1 } }
@media (prefers-reduced-motion: reduce) { #bootSplash.updating #bootSplashMsg { animation: none; opacity: 1; } }
/* 轻微呼吸,暗示「在加载」而不是卡住 */
@keyframes bootSplashPulse {
  0%, 100% { opacity: 0.72; transform: scale(0.99); }
  50%      { opacity: 1;    transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) { #bootSplash img { animation: none; } }

/* ── 1. Design tokens ───────────────────────────────────────────── */
:root {
  color-scheme: light;

  /* surfaces */
  --bg: #f6f7fb;
  --bg-tint: radial-gradient(140% 80% at 10% -10%, rgba(255, 87, 34, 0.08), transparent 60%),
             radial-gradient(120% 70% at 110% 10%, rgba(17, 17, 17, 0.06), transparent 55%),
             linear-gradient(180deg, #fafaf8 0%, #f0eeea 100%);
  --card: #ffffff;
  --card-elev: #ffffff;
  --soft: #f1f4fa;
  --hover: #eef2f9;

  /* text */
  --ink: #0f172a;
  --ink-strong: #050a1a;
  --muted: #64748b;
  --muted-strong: #475569;

  /* borders */
  --line: #e2e8f0;
  --line-strong: #cbd5e1;

  /* brand — Checko: rich black + orange accent */
  --brand: #111111;           /* rich black, primary */
  --brand-2: #ff5722;         /* orange accent */
  --brand-soft: rgba(255, 87, 34, 0.10);
  --brand-ring: rgba(255, 87, 34, 0.34);
  --brand-grad: var(--accent-grad); /* 按钮等强调元素=纯主题色(不再黑→色),与 Chat FAB 一致 */
  --brand-2-rgb: 255, 87, 34;
  /* 纯主题色渐变(浅→深):靠 color-mix 从 --brand-2 推导,自动跟随色板/明暗切换。
     与 --brand-grad(黑→色,顶栏药丸用)区分开。 */
  --accent-grad: linear-gradient(180deg, color-mix(in srgb, var(--brand-2), #fff 26%) 0%, var(--brand-2) 100%);

  /* hero (dark with warm glow toward orange) */
  --hero-bg: linear-gradient(140deg, #0b0b0e 0%, #16161c 50%, #1d1d26 100%);
  --hero-ink: #f8fafc;
  --hero-muted: rgba(248, 250, 252, 0.7);
  --hero-soft: rgba(255, 255, 255, 0.12);
  --hero-line: rgba(255, 255, 255, 0.18);

  /* semantic */
  --ok: #059669;
  --ok-2: #34d399;
  --ok-soft: rgba(16, 185, 129, 0.14);
  --ok-grad: linear-gradient(135deg, #059669, #34d399);
  --warn: #d97706;
  --warn-soft: rgba(245, 158, 11, 0.16);
  --warn-grad: linear-gradient(135deg, #d97706, #fbbf24);
  --danger: #dc2626;
  --danger-soft: rgba(239, 68, 68, 0.14);
  --danger-grad: linear-gradient(135deg, #dc2626, #f87171);
  --info: #0284c7;
  --info-soft: rgba(2, 132, 199, 0.14);

  /* category colors */
  --cat-food: #f97316;        /* orange */
  --cat-food-soft: rgba(249, 115, 22, 0.14);
  --cat-transport: #06b6d4;   /* cyan */
  --cat-transport-soft: rgba(6, 182, 212, 0.14);
  --cat-shopping: #ec4899;    /* pink */
  --cat-shopping-soft: rgba(236, 72, 153, 0.14);
  --cat-fun: #a855f7;         /* purple */
  --cat-fun-soft: rgba(168, 85, 247, 0.14);
  --cat-bills: #eab308;       /* amber */
  --cat-bills-soft: rgba(234, 179, 8, 0.14);
  --cat-saving: #10b981;      /* emerald */
  --cat-saving-soft: rgba(16, 185, 129, 0.14);
  --cat-debt: #ef4444;        /* red */
  --cat-debt-soft: rgba(239, 68, 68, 0.14);
  --cat-other: #64748b;       /* slate */
  --cat-other-soft: rgba(100, 116, 139, 0.14);
  --cat-reimbursement: #14b8a6; --cat-reimbursement-soft: rgba(20, 184, 166, 0.14);
  --cat-income: #22c55e;      /* green */
  --cat-income-soft: rgba(34, 197, 94, 0.14);
  --cat-travel: #0ea5e9;        --cat-travel-soft: rgba(14, 165, 233, 0.14);
  --cat-medical: #ef4444;       --cat-medical-soft: rgba(239, 68, 68, 0.14);
  --cat-education: #6366f1;     --cat-education-soft: rgba(99, 102, 241, 0.14);
  --cat-entertainment: #a855f7; --cat-entertainment-soft: rgba(168, 85, 247, 0.14);
  --cat-insurance: #3b82f6;     --cat-insurance-soft: rgba(59, 130, 246, 0.14);
  --cat-maintenance: #b45309;   --cat-maintenance-soft: rgba(180, 83, 9, 0.14);
  --cat-rent: #d97706;          --cat-rent-soft: rgba(217, 119, 6, 0.14);
  --cat-telecom: #14b8a6;       --cat-telecom-soft: rgba(20, 184, 166, 0.14);
  --cat-utilities: #eab308;     --cat-utilities-soft: rgba(234, 179, 8, 0.14);
  --cat-tax: #78716c;           --cat-tax-soft: rgba(120, 113, 108, 0.14);
  --cat-gift: #f43f5e;          --cat-gift-soft: rgba(244, 63, 94, 0.14);
  --cat-pet: #84cc16;           --cat-pet-soft: rgba(132, 204, 22, 0.14);
  --cat-fitness: #22d3ee;       --cat-fitness-soft: rgba(34, 211, 238, 0.14);

  /* legacy color aliases used by JS (group/chart colors) */
  --green: #10b981;
  --blue: #0ea5e9;
  --yellow: #eab308;
  --red: #ef4444;
  --purple: #a855f7;
  --orange: #f97316;
  --pink: #ec4899;

  /* effects */
  --radius-xs: 8px;
  --radius-sm: 12px;
  --radius: 16px;
  --radius-md: 18px;
  --radius-lg: 22px;
  --radius-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow: 0 6px 18px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-lg: 0 18px 50px rgba(15, 23, 42, 0.14), 0 4px 12px rgba(15, 23, 42, 0.06);
  --shadow-glow: 0 12px 30px rgba(255, 87, 34, 0.28);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 200ms;

  /* type */
  --font-display: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-sans: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-family: var(--font-sans);
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #070b16;
  --bg-tint: radial-gradient(140% 80% at 10% -10%, rgba(77, 124, 255, 0.18), transparent 60%),
             radial-gradient(120% 70% at 110% 10%, rgba(125, 163, 255, 0.10), transparent 55%),
             linear-gradient(180deg, #0a1024 0%, #050813 100%);
  --card: #111a2e;
  --card-elev: #1a2440;
  --soft: #182240;
  --hover: #1d2849;

  --ink: #e8edf7;
  --ink-strong: #ffffff;
  --muted: #93a0bd;
  --muted-strong: #b9c3da;

  --line: #1f2a48;
  --line-strong: #2a3865;

  --brand: #ff5722;
  /* 暗色 --brand-2 原为 #ff8a65(偏白桃橙),是所有橙色文字/图标/徽章/底部导航选中态
     发白的总根源。收到饱和橙 #ff6a3d(与 brand-grad 末端一致)→ 全站橙色一次性统一鲜艳。 */
  --brand-2: #ff6a3d;
  --brand-soft: rgba(255, 87, 34, 0.20);
  --brand-ring: rgba(255, 87, 34, 0.48);
  /* 暗色发白根因:渐变末端 #ff8a65 太浅,宽药丸(UANG/TAGIHAN·PROFIL/PENGATURAN 等)
     右半发白。两个渐变末端都收到饱和橙 #ff6a3d → 所有橙按钮/药丸统一鲜艳,不再发白。 */
  --brand-grad: linear-gradient(135deg, #ff5722 0%, #ff6a3d 100%);
  --accent-grad: linear-gradient(135deg, #ff5722 0%, #ff6a3d 100%);

  --ok: #34d399;
  --ok-soft: rgba(52, 211, 153, 0.18);
  --warn: #fbbf24;
  --warn-soft: rgba(251, 191, 36, 0.16);
  --danger: #f0342e;
  --danger-soft: rgba(240, 52, 46, 0.16);
  --danger-grad: linear-gradient(135deg, #e01c1c, #f0342e);
  --info: #60a5fa;
  --info-soft: rgba(96, 165, 250, 0.18);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow: 0 8px 20px rgba(0, 0, 0, 0.55), 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.7), 0 6px 14px rgba(0, 0, 0, 0.5);
  --shadow-glow: 0 14px 36px rgba(77, 124, 255, 0.45);
}

/* ── 2. Reset ────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html, body { min-height: 100%; margin: 0; }
body {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--bg);
  background-image: var(--bg-tint);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* iOS / Android — kill the tap blue flash + don't zoom on double-tap */
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  /* Stop body rubber-banding past phone-app on iOS */
  overscroll-behavior-y: contain;
}
/* Inputs ≥16px font-size to prevent iOS focus auto-zoom */
@media (max-width: 559px) {
  input[type="text"], input[type="tel"], input[type="number"],
  input[type="search"], input[type="email"], input[type="password"],
  input[type="date"], textarea, select {
    font-size: 16px;
  }
}
h1, h2, h3, h4 { margin: 0; line-height: 1.2; color: var(--ink-strong); letter-spacing: -0.02em; }
h1 { font-size: 17px; font-weight: 800; }
h2 { font-size: 22px; font-weight: 800; letter-spacing: -0.025em; }
h3 { font-size: 15px; font-weight: 700; }
h4 { font-size: 13px; font-weight: 700; }
p { margin: 0; color: var(--muted-strong); }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img { display: block; max-width: 100%; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
/* ── Accent palettes (orthogonal to light/dark). data-palette swaps brand vars,
   so every accent (buttons, active tabs, logo check, rings) re-tints at once. ── */
:root[data-palette="ocean"]  { --brand-2:#0ea5e9; --brand-soft:rgba(14,165,233,.10);  --brand-ring:rgba(14,165,233,.45); --brand-grad:var(--accent-grad); }
:root[data-palette="violet"] { --brand-2:#8b5cf6; --brand-soft:rgba(139,92,246,.10);  --brand-ring:rgba(139,92,246,.45); --brand-grad:var(--accent-grad); }
:root[data-palette="rose"]   { --brand-2:#ec4899; --brand-soft:rgba(236,72,153,.10);  --brand-ring:rgba(236,72,153,.45); --brand-grad:var(--accent-grad); }
:root[data-palette="ocean"][data-theme="dark"]  { --brand:#0ea5e9; --brand-2:#38bdf8; --brand-soft:rgba(14,165,233,.20);  --brand-ring:rgba(14,165,233,.48); --brand-grad:linear-gradient(135deg,#0ea5e9 0%,#38bdf8 100%); }
:root[data-palette="violet"][data-theme="dark"] { --brand:#8b5cf6; --brand-2:#a78bfa; --brand-soft:rgba(139,92,246,.20);  --brand-ring:rgba(139,92,246,.48); --brand-grad:linear-gradient(135deg,#8b5cf6 0%,#a78bfa 100%); }
:root[data-palette="rose"][data-theme="dark"]   { --brand:#ec4899; --brand-2:#f472b6; --brand-soft:rgba(236,72,153,.20);  --brand-ring:rgba(236,72,153,.48); --brand-grad:linear-gradient(135deg,#ec4899 0%,#f472b6 100%); }
/* RGB 三元组(给 rgba() 辉光用),与上面 --brand-2 同层叠 → 报表辉光跟随主题 */
:root { --brand-2-rgb: 255,87,34; }
:root[data-theme="dark"] { --brand-2-rgb: 255,138,101; }
:root[data-palette="ocean"]  { --brand-2-rgb: 14,165,233; }
:root[data-palette="violet"] { --brand-2-rgb: 139,92,246; }
:root[data-palette="rose"]   { --brand-2-rgb: 236,72,153; }
:root[data-palette="ocean"][data-theme="dark"]  { --brand-2-rgb: 56,189,248; }
:root[data-palette="violet"][data-theme="dark"] { --brand-2-rgb: 167,139,250; }
:root[data-palette="rose"][data-theme="dark"]   { --brand-2-rgb: 244,114,182; }

/* Palette picker swatches */
.palette-swatches { display: flex; gap: 10px; }
.palette-swatch {
  width: 26px; height: 26px; padding: 0;
  border-radius: 50%;
  border: 2px solid var(--line);
  background: var(--sw);
  cursor: pointer;
  transition: transform 0.12s var(--ease);
}
.palette-swatch:active { transform: scale(0.92); }
.palette-swatch.active { border-color: var(--card); box-shadow: 0 0 0 2px var(--sw); }
/* Logo check mark follows the palette accent (CSS beats the inline stroke attr) */
.brand-mark svg path:nth-child(2) { stroke: #ff5722; } /* logo 固定品牌橙,不随色板变 */

/* ── Hard login gate ─────────────────────────────────────────────────────── */
.auth-gate {
  position: fixed;
  inset: 0;
  z-index: 2147483600;
  display: flex;
  /* flex-start + 卡片 margin:auto:有空间时居中,内容超过视口高时顶对齐、可完整滚动
     (避免 align-items:center 把顶部标题裁出可视区且滚不到) */
  align-items: flex-start;
  justify-content: center;
  padding: 24px;
  background: var(--bg);
  overflow-y: auto;
}
.auth-gate-card { margin: auto; }
/* 桌面端:登录页背景做成有设计感的渐变(两栏卡片规则在基础规则之后,见下方) */
@media (min-width: 760px) {
  .auth-gate {
    padding: 48px;
    background:
      radial-gradient(60% 60% at 50% 0%, rgba(255, 87, 34, 0.16), transparent 60%),
      radial-gradient(50% 50% at 100% 100%, rgba(255, 87, 34, 0.08), transparent 60%),
      var(--bg);
  }
}
.auth-gate[hidden] { display: none; }
body.gate-open { overflow: hidden; }

/* 网页付费墙 */
.paywall-crown {
  width: 56px; height: 56px;
  margin: 0 auto 6px;
  display: grid; place-items: center;
  border-radius: 16px;
  color: #ffb300;
  background: rgba(255, 179, 0, 0.12);
}
.paywall-crown svg { width: 30px; height: 30px; }
.paywall-cycle { margin: 14px 0 12px; }
.paywall-plans { display: grid; gap: 10px; }
.paywall-plan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.paywall-plan:hover { border-color: var(--brand); transform: translateY(-1px); }
.paywall-plan .pp-name { font-size: 15px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.paywall-plan .pp-price { flex: none; display: inline-flex; align-items: baseline; gap: 4px; white-space: nowrap; font-size: 16px; font-weight: 800; color: var(--brand); }
.paywall-plan .pp-price small { font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.paywall-plan--gold { border-color: rgba(255, 179, 0, 0.5); }
.paywall-app-link {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin: 14px 0 4px;
  text-align: center;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--brand);
  text-decoration: none;
}
.paywall-app-link:hover { text-decoration: underline; }
.paywall-signout { width: 100%; min-height: 44px; margin-top: 6px; }

/* 汇率换算器 */
.fx-row { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: end; }
.fx-swap {
  width: 44px; height: 44px;
  align-self: end;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--brand-soft);
  color: var(--brand-2);
  cursor: pointer;
  display: grid; place-items: center;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.fx-swap svg { width: 18px; height: 18px; }
.fx-swap:hover { transform: rotate(180deg); }

/* Biometric privacy lock — sits above everything (incl. the auth gate) until
   Face ID / fingerprint clears it. */
.biometric-lock {
  position: fixed;
  inset: 0;
  z-index: 2147483646;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: var(--bg);
  background-image: var(--bg-tint);
}
.biometric-lock[hidden] { display: none; }
.biometric-lock-inner {
  display: grid;
  justify-items: center;
  gap: 12px;
  text-align: center;
  max-width: 320px;
  width: 100%;
}
.biometric-lock-icon {
  width: 72px; height: 72px;
  display: grid; place-items: center;
  border-radius: 24px;
  background: var(--brand-soft);
  color: var(--brand);
  margin-bottom: 4px;
}
.biometric-lock-icon svg { width: 38px; height: 38px; }
.biometric-lock-inner h2 { font-size: 22px; }
.biometric-lock-inner p { font-size: 14px; color: var(--muted); margin: 0 0 6px; }
#bioUnlockBtn {
  width: 100%; height: 50px;
  border: 0; border-radius: var(--radius-md);
  background: var(--brand-grad); color: #fff;
  font-size: 15px; font-weight: 800; cursor: pointer;
  box-shadow: 0 8px 20px -8px var(--brand);
}
#bioUnlockBtn:active { transform: scale(0.98); }
#bioSignOutBtn { width: 100%; }
body.bio-locked { overflow: hidden; }
.auth-gate-card {
  position: relative;
  width: 100%;
  max-width: 360px;
  display: grid;
  gap: 14px;
  padding: 28px 22px;
  border-radius: var(--radius);
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow: 0 18px 50px rgba(15, 23, 42, 0.16);
}
/* 登录卡两栏:手机端只显示表单列(aside 隐藏),桌面端左品牌右表单 */
.auth-gate-aside { display: none; }
.auth-gate-main { display: grid; gap: 14px; align-content: start; }
/* 桌面两栏:必须放在上面基础规则「之后」,否则 max-width:360 / aside:none 会反盖。
   只限定登录闸 #authGate;付费墙 #webPaywall 复用同 class 但要保持单栏(见下)。 */
@media (min-width: 760px) {
  #authGate .auth-gate-card {
    max-width: 880px;
    padding: 0;
    gap: 0;
    overflow: hidden;
    grid-template-columns: 1.02fr 1fr;
    align-items: stretch;
    box-shadow: 0 40px 110px rgba(0, 0, 0, 0.5);
  }
  /* 付费墙:单栏、舒适宽度(不吃登录页的两栏网格) */
  #webPaywall .auth-gate-card { max-width: 480px; }
  .auth-gate-aside {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 16px;
    padding: 44px 42px;
    color: #fff;
    background:
      radial-gradient(85% 70% at 8% 100%, rgba(255, 87, 34, 0.22), transparent 55%),
      radial-gradient(75% 55% at 0% 0%, rgba(255, 87, 34, 0.12), transparent 60%),
      linear-gradient(160deg, #141826, #0b0e17);
  }
  .auth-gate-aside-brand { display: flex; align-items: center; gap: 9px; }
  .auth-gate-aside-brand .brand-mark { width: 32px; height: 32px; color: #fff; }
  .auth-gate-aside-brand .brand-mark svg { width: 100%; height: 100%; }
  .auth-gate-aside-brand strong { font-size: 16px; letter-spacing: 0.14em; color: #fff; }
  .auth-gate-aside-title { font-size: 38px; font-weight: 800; line-height: 1.08; letter-spacing: -0.02em; color: #fff; margin: 6px 0 0; }
  .auth-gate-aside-title .hl { color: #ff5722; }
  .auth-gate-aside-sub { font-size: 13.5px; line-height: 1.5; color: rgba(255, 255, 255, 0.62); margin: 0; max-width: 330px; }
  .aga-bubbles { display: grid; gap: 9px; margin-top: 2px; }
  .aga-bubble { background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 14px; border-bottom-left-radius: 4px; padding: 11px 13px; display: grid; gap: 3px; }
  .aga-bubble b { font-size: 13.5px; font-weight: 700; color: #fff; }
  .aga-bubble span { font-size: 12px; line-height: 1.45; color: rgba(255, 255, 255, 0.58); }
  .aga-free { display: grid; grid-template-columns: auto 1fr; gap: 2px 14px; align-items: center; background: rgba(255, 87, 34, 0.1); border: 1px solid rgba(255, 87, 34, 0.25); border-radius: 16px; padding: 13px 16px; }
  .aga-free-num { grid-row: span 2; font-size: 42px; font-weight: 800; color: #ff5722; line-height: 0.9; }
  .aga-free-txt b { display: block; font-size: 15px; color: #fff; }
  .aga-free-txt small { font-size: 12px; color: rgba(255, 255, 255, 0.6); }
  .aga-free-note { grid-column: 1 / -1; margin: 8px 0 0; font-size: 11px; line-height: 1.45; color: rgba(255, 255, 255, 0.5); border-top: 1px solid rgba(255, 255, 255, 0.1); padding-top: 8px; }
  .aga-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 4px; }
  .aga-cols > div { display: grid; gap: 2px; padding-left: 11px; border-left: 1px solid rgba(255, 255, 255, 0.14); }
  .aga-cols b { font-size: 12.5px; color: #fff; }
  .aga-cols small { font-size: 10.5px; line-height: 1.4; color: rgba(255, 255, 255, 0.55); }
  /* 桌面:品牌 logo 只在左栏 → 右栏表单不再重复显示 */
  #authGate .auth-gate-main > .auth-gate-brand { display: none; }
  .auth-gate-main { padding: 44px 42px; align-content: center; }
  .auth-gate-card h2 { font-size: 26px; }
}
.auth-gate-foot { text-align: center; font-size: 11.5px; line-height: 1.55; color: var(--muted); margin: 4px 0 0; }
.auth-gate-foot .agf-copy { opacity: 0.7; }
/* 登录页右上角语言切换 */
.auth-lang { position: absolute; top: 14px; right: 14px; z-index: 2; display: flex; gap: 2px; background: var(--soft); border: 1px solid var(--line); border-radius: 999px; padding: 2px; }
.auth-lang button { min-width: 30px; height: 26px; border: 0; border-radius: 999px; background: transparent; color: var(--muted-strong); font-size: 12px; font-weight: 700; cursor: pointer; }
/* 选中态用品牌橙,和全 App 其他分段控件(.money-tabs 等)一致。
   原来是 var(--ink) —— 暗色主题下 --ink 是 #e8edf7(近白),于是登录页右上角
   杵着一颗白药丸,既不像本 App 的控件,在深色卡片上还刺眼。 */
.auth-lang button.active { background: var(--brand-grad); color: #fff; }
/* ⚠️ 药丸机制会给容器挂 .has-seg-pill,而那条规则是 position:relative,写在本文件
   更靠后的位置 —— 权重相同则后者胜,会把这里的 absolute 顶掉,语言切换器直接从
   右上角掉回文档流。所以必须在这里显式钉回 absolute。 */
.auth-lang.has-seg-pill { position: absolute; }
/* 登录页左上角:返回首页(原生壳无落地页 → 隐藏) */
.auth-gate-home { position: absolute; top: 16px; left: 16px; z-index: 2; display: inline-flex; align-items: center; gap: 6px; color: var(--brand-2); font-weight: 700; font-size: 13px; text-decoration: none; }
.auth-gate-home:hover { text-decoration: underline; }
body.native-app .auth-gate-home { display: none; }
/* 手机 web 端:返回键(absolute top:16)会贴住 CHECKO 品牌,把品牌下移留白 */
@media (max-width: 759px) {
  body:not(.native-app) #authGate .auth-gate-brand { margin-top: 20px; }
}
.auth-ref-hint { font-size: 12px; color: var(--brand); margin: -6px 0 0; text-align: center; font-weight: 600; }
/* 社交登录按钮 */
.social-login { display: grid; gap: 8px; }
.social-login[hidden] { display: none; }
.social-btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; height: 46px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--card); color: var(--ink); font-size: 14px; font-weight: 700; cursor: pointer; transition: background var(--dur) var(--ease); }
.social-btn:hover:not(:disabled) { background: var(--soft); }
.social-btn:active:not(:disabled) { transform: scale(0.99); }
.social-btn:disabled { opacity: .45; cursor: default; }
.social-btn svg { width: 20px; height: 20px; flex: none; }
/* 登录门:Face ID 快速登录按钮(品牌渐变 CTA,置于表单最上方) */
.bio-login-btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; height: 48px; margin-bottom: 14px; border: 0; border-radius: var(--radius-md); background: var(--brand-grad); color: #fff; font-size: 14.5px; font-weight: 800; cursor: pointer; box-shadow: 0 8px 22px -8px rgba(255, 87, 34, 0.55); transition: transform var(--dur) var(--ease); }
.bio-login-btn[hidden] { display: none; }
.bio-login-btn:active { transform: scale(0.99); }
.bio-login-btn svg { width: 22px; height: 22px; flex: none; }
.auth-or { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; font-weight: 600; }
.auth-or[hidden] { display: none; }
.auth-or::before, .auth-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
/* 兑换码:勾选才展开 + 视觉化奖励卡 */
.auth-ref-toggle { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; font-weight: 600; color: var(--ink); padding: 6px 0; user-select: none; }
.auth-ref-toggle input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.auth-ref-toggle .arr-chev { flex: none; width: 18px; height: 18px; color: var(--muted); transition: transform 0.2s var(--ease); }
.auth-ref-toggle .arr-chev svg { width: 100%; height: 100%; display: block; }
.auth-ref-toggle input:checked ~ .arr-chev { transform: rotate(90deg); }
.auth-ref-toggle-text { flex: 1; }
.auth-ref-gift { font-size: 12px; font-weight: 800; color: var(--brand-2); background: var(--brand-soft); padding: 4px 11px; border-radius: 999px; }
.auth-ref-box { display: grid; gap: 10px; }
.auth-ref-box[hidden] { display: none; }
.auth-ref-reward { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: var(--radius-md); background: color-mix(in srgb, var(--brand) 10%, transparent); border: 1px solid color-mix(in srgb, var(--brand) 28%, transparent); }
.auth-ref-reward .arr-ic { flex: none; width: 26px; height: 26px; color: var(--brand-2); }
.auth-ref-reward .arr-ic svg { width: 100%; height: 100%; display: block; }
.auth-ref-reward .arr-text b { display: block; font-size: 14px; font-weight: 800; color: var(--ink); }
.auth-ref-reward .arr-text small { display: block; font-size: 12px; color: var(--muted); margin-top: 1px; }
/* 提交按钮 loading 旋转(发码/登录时) */
.auth-gate-form button[type="submit"].is-loading { position: relative; color: transparent; pointer-events: none; }
.auth-gate-form button[type="submit"].is-loading::after { content: ""; position: absolute; left: 50%; top: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px; border: 2px solid rgba(255,255,255,.5); border-top-color: #fff; border-radius: 50%; animation: authspin .7s linear infinite; }
@keyframes authspin { to { transform: rotate(360deg); } }
.auth-gate-brand { display: flex; align-items: center; gap: 10px; }
.auth-gate-brand .brand-mark { width: 36px; height: 36px; color: var(--ink-strong); }
.auth-gate-brand .brand-mark svg { width: 100%; height: 100%; }
.auth-gate-brand strong { font-size: 18px; letter-spacing: 0.06em; }
/* 官方字标 lockup:C+橙勾标 + 小写 checko(o 橙)+ tagline,HTML 重建保证整齐 */
.ckb-lockup { display: flex; align-items: center; gap: 11px; }
.ckb-lockup .ckb-mark { flex: none; width: 40px; height: 40px; display: grid; place-items: center; color: var(--ink-strong); }
.ckb-lockup .ckb-mark svg { width: 100%; height: 100%; }
.ckb-lockup .ckb-word { display: flex; flex-direction: column; gap: 3px; line-height: 1; }
.ckb-lockup .ckb-name { font-size: 23px; font-weight: 800; letter-spacing: -0.01em; color: var(--ink); }
.ckb-lockup .ckb-o { color: #ff5722; }
.ckb-lockup .ckb-tag { font-size: 9.5px; font-weight: 600; letter-spacing: 0.02em; color: var(--muted); }
/* 深色左栏变体 */
.ckb-on-dark .ckb-mark { color: #fff; }
.ckb-on-dark .ckb-name { color: #fff; }
.ckb-on-dark .ckb-tag { color: rgba(255, 255, 255, 0.6); }
.auth-gate-card h2 { font-size: 22px; margin: 2px 0 0; }
.auth-gate-copy { font-size: 13px; color: var(--muted); margin: 0; }
/* 验证码已发送提示里的邮箱:橙色高亮,过长截断为 … */
.gate-code-email { color: var(--brand-2); font-weight: 700; display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.auth-gate-form { display: grid; gap: 12px; grid-template-columns: minmax(0, 1fr); }
.auth-gate-form input[type="email"],
.auth-gate-form input[type="password"],
.auth-gate-form input[type="text"],
.auth-gate-form input#gateCode {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink-strong);
  font-size: 15px;
}
/* 验证码 6 格子(深色 gate 上) */
.otp-boxes { display: flex; gap: 8px; justify-content: center; }
.otp-box {
  width: 100%; max-width: 48px; height: 54px; text-align: center;
  font-size: 22px; font-weight: 800;
  border: 1.5px solid var(--line); border-radius: 12px;
  background: var(--card); color: var(--ink-strong); caret-color: #ff6a3d;
}
.otp-box:focus { outline: none; border-color: #ff6a3d; background: var(--soft); box-shadow: 0 0 0 3px rgba(255,106,61,0.25); }
/* 邮箱/密码字段左侧图标(信封 / 锁) */
.auth-field { position: relative; }
.auth-field-ic { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; color: var(--muted); pointer-events: none; }
.auth-field-ic svg { width: 100%; height: 100%; }
.auth-field input { padding-left: 44px !important; }
/* Lanjut 按钮右侧箭头(标签外置,翻译不覆盖;loading 时随文字一起隐) */
.auth-gate-form button[type="submit"] { position: relative; }
#gateSubmitBtn .gate-arrow { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; }
.auth-gate-form button[type="submit"].is-loading .gate-arrow { visibility: hidden; }
/* 密码框 + 显示/隐藏眼睛 */
.auth-pass-wrap { position: relative; }
.auth-pass-wrap input { padding-right: 46px !important; }
.auth-pass-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border: 0; border-radius: 9px; background: transparent; color: var(--muted); cursor: pointer; padding: 0; transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.auth-pass-toggle svg { width: 20px; height: 20px; }
.auth-pass-toggle:hover { background: var(--soft); color: var(--ink); }
.auth-pass-toggle:active { transform: translateY(-50%) scale(0.9); }
/* 默认显示「眼睛」(点击=显示);开启后切到「眼睛划掉」并高亮橙色,一眼看出已点 */
.auth-pass-toggle .eye-hide { display: none; }
.auth-pass-toggle.on { color: var(--brand-2); background: var(--brand-soft); }
.auth-pass-toggle.on .eye-show { display: none; }
.auth-pass-toggle.on .eye-hide { display: block; }
/* 账号页「修改密码」三框:定位容器让眼睛按钮贴在框内右侧,输入右侧留位不压字 */
.pw-field { position: relative; }
.pw-field input { width: 100%; padding-right: 44px !important; }
.auth-gate-forgot { background: none; border: 0; color: var(--brand); font-size: 13px; font-weight: 700; cursor: pointer; padding: 4px; margin: -4px auto 0; display: block; }
/* 登录门:密码「用密码登录」展开链接 */
.auth-pass-link { background: none; border: 0; color: var(--muted-strong); font-size: 13px; font-weight: 700; cursor: pointer; padding: 4px; margin: 2px auto; display: block; }
/* 联系人弹窗:收款账号三字段(银行+账号一行,户名一行) */
.cf-bank-row { display: grid; grid-template-columns: 1fr 1.6fr; gap: 8px; margin-bottom: 8px; }
.cf-bank-in { width: 100%; box-sizing: border-box; height: 44px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--card); color: var(--ink); font-size: 14px; }
/* 注册后兑换码礼物卡 */
.redeem-gift-card { text-align: center; display: grid; gap: 10px; justify-items: center; max-width: 340px; }
.redeem-gift-ic { width: 54px; height: 54px; display: grid; place-items: center; border-radius: 50%; background: var(--brand-soft); color: var(--brand-2); }
.redeem-gift-ic svg { width: 28px; height: 28px; }
.redeem-gift-card h3 { margin: 0; font-size: 18px; font-weight: 800; }
.redeem-gift-copy { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.5; }
#redeemGiftInput { width: 100%; box-sizing: border-box; height: 46px; text-align: center; letter-spacing: 2px; text-transform: uppercase; font-size: 16px; font-weight: 700; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--card); color: var(--ink); }
.redeem-gift-msg { margin: 0; font-size: 12.5px; color: var(--danger, #dc2626); }
/* 竖排整行:主按钮(如「看广告·+1 AI」)不再挤成半宽换行;主在上、Nanti 在下 */
.redeem-gift-actions { display: flex; flex-direction: column-reverse; gap: 10px; width: 100%; margin-top: 4px; }
.redeem-gift-actions > button { flex: none; width: 100%; min-height: 50px; height: auto; padding: 13px 18px; border-radius: var(--radius-md); font-size: 15px; font-weight: 700; line-height: 1.2; cursor: pointer; }
.redeem-gift-go { border: 0; background: var(--accent-grad); color: #fff; } /* 与全局主按钮同款饱和橙 */
/* admin 测真实支付按钮 */
/* 订阅页:邀请免费拿会员提示 */
.sub-referral-prompt { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; margin-bottom: 14px; padding: 13px 15px; border-radius: var(--radius-md); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--brand-2) 34%, transparent); background: color-mix(in srgb, var(--brand-2) 10%, transparent); }
.sub-referral-prompt:active { transform: scale(0.995); }
.sub-referral-prompt .srp-ic { flex: none; width: 24px; height: 24px; color: var(--brand-2); }
.sub-referral-prompt .srp-ic svg { width: 100%; height: 100%; display: block; }
.sub-referral-prompt .srp-text { flex: 1; min-width: 0; }
.sub-referral-prompt .srp-text b { display: block; font-size: 14px; font-weight: 800; color: var(--ink); }
.sub-referral-prompt .srp-text small { display: block; font-size: 12px; color: var(--muted); margin-top: 1px; }
.sub-referral-prompt .srp-arrow { flex: none; color: var(--brand-2); font-size: 18px; font-weight: 800; }
/* 管理订阅:不自动续费说明 + 立即降级到免费 */
.sub-manage { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); display: grid; gap: 10px; }
.sub-manage[hidden] { display: none; }
.sub-manage-info { font-size: 12.5px; line-height: 1.5; color: var(--muted); margin: 0; }
/* Apple 自动续订法务声明:居中 muted、与 .sub-manage-info 同字号体系;声明与链接分两行更整齐,
   链接改用 ink 色 + 细下划线(不再浏览器默认蓝),nowrap 防止 "Privacy Policy" 断行落单。 */
.sub-legal { margin: 16px auto 0; max-width: 330px; text-align: center; font-size: 12px; line-height: 1.6; color: var(--muted); }
.sub-legal > span { display: block; margin-bottom: 5px; }
.sub-legal a { color: var(--ink); font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--line); white-space: nowrap; padding-bottom: 1px; }
.sub-legal a:active { color: var(--brand); border-color: var(--brand); }
.sub-cancel-btn { width: 100%; min-height: 44px; border: 1px solid var(--danger); border-radius: var(--radius-md); background: transparent; color: var(--danger); font-size: 14px; font-weight: 700; cursor: pointer; }
.sub-cancel-btn:active { transform: scale(0.99); }
.sub-cancel-btn:disabled { opacity: .5; cursor: default; }
.admin-testpay-btn { width: 100%; margin-top: 12px; min-height: 40px; border: 1px dashed var(--line); border-radius: var(--radius-md); background: transparent; color: var(--muted-strong); font-size: 13px; font-weight: 700; cursor: pointer; }
.admin-testpay-btn[hidden] { display: none; }
.admin-testpay-btn:active { transform: scale(0.99); }
.auth-gate-hint { font-size: 12px; color: var(--muted); margin: 2px 0 0; text-align: center; }
.auth-gate-form input#gateCode { letter-spacing: 0.28em; text-align: center; font-size: 21px; font-weight: 700; }
.auth-gate-form button[type="submit"] {
  padding: 13px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--brand-grad);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}
.auth-gate-form .secondary-button { padding: 11px; border-radius: var(--radius-sm); }
.auth-gate-resend {
  border: 0;
  background: none;
  color: var(--brand-2);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  padding: 4px;
}
.auth-gate-resend:disabled { color: var(--muted); cursor: default; }
.auth-gate .auth-consent { display: flex; gap: 8px; align-items: center; font-size: 11.5px; line-height: 1.35; color: var(--muted-strong); }
.auth-gate .auth-consent a { color: var(--brand-2); font-weight: 700; }
/* 勾选框:小巧但边框加深 + 未勾浅底,醒目又不挤,文案保持一行 */
.auth-gate .auth-consent input[type="checkbox"] { width: 18px; height: 18px; margin-top: 0; border-color: var(--muted); background: var(--soft); }
.auth-gate .auth-consent input[type="checkbox"]:checked { background: var(--brand-2); border-color: var(--brand-2); }
.auth-gate .auth-consent input[type="checkbox"]:checked::after { left: 5px; top: 1px; width: 5px; height: 9px; }
.auth-gate #gateStatus { font-size: 13px; text-align: center; margin: 0; }
/* Auth validation/error feedback: shake the card + turn the status line red so a
   blocked submit (e.g. consent unchecked) can't be mistaken for "nothing happened". */
@keyframes authShake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-8px); }
  40%, 60% { transform: translateX(8px); }
}
.auth-shake { animation: authShake 0.5s cubic-bezier(.36, .07, .19, .97); }
@media (prefers-reduced-motion: reduce) { .auth-shake { animation: none; } }
.auth-gate #gateStatus.is-error,
#authStatus.is-error { color: var(--danger); font-weight: 600; background: var(--danger-soft); }

::selection { background: var(--brand-soft); color: var(--ink-strong); }
[hidden] { display: none !important; }

/* "Rp" currency prefix — muted small label so the number is the focus.
   Wrapped by formatRpHtml(); see app.js. */
/* Atomic money block: prefix + digits never split across lines */
.rp-line {
  display: inline-block;
  white-space: nowrap;
}
.rp-prefix {
  font-size: 0.62em;
  font-weight: 600;
  opacity: 0.55;
  margin-right: 0.18em;
  letter-spacing: 0.02em;
  vertical-align: 0.1em;
  font-feature-settings: normal;
  white-space: nowrap;
  /* Force solid color even when the parent uses background-clip:text
     gradients (e.g. #todaySpendable's white→orange headline) — those
     set -webkit-text-fill-color:transparent which would inherit and
     make the Rp invisible. */
  -webkit-text-fill-color: currentColor;
  color: inherit;
}
/* On the dark hero specifically, ensure Rp reads as faded white */
.overview-hero .rp-prefix {
  color: rgba(255, 255, 255, 0.65);
  -webkit-text-fill-color: rgba(255, 255, 255, 0.65);
  opacity: 0.85;
}

/* mono utility — auto-apply to currency/number heavy elements */
.tx-meta, .paylater-meta,
#safeBalance, #safeReservedCost, #safeTotalBalance,
#overviewExpectedIncome, #overviewBudgetUsed, #balanceSummary,
#incomeSummary, #dailySafe, #todaySpendable, #todaySpendableRatio {
  font-feature-settings: "tnum", "lnum";
}

/* ── 3. App shell + phone frame ────────────────────────────────── */
.app-shell {
  display: grid;
  min-height: 100vh;
  min-height: 100dvh;
  place-items: stretch;
  padding: clamp(0px, 2vw, 24px);
}

/* When previewing as mobile on a wider window, frame the phone */
body[data-preview-device="mobile"] .app-shell {
  place-items: center;
  padding: clamp(0px, 3vw, 32px);
}

.phone-app {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  isolation: isolate;
}

/* Mobile preview frame: fixed phone width on desktop windows */
@media (min-width: 560px) {
  body[data-preview-device="mobile"] .phone-app {
    width: 414px;
    max-width: 100%;
    height: min(880px, calc(100vh - 48px));
    box-shadow: var(--shadow-lg);
  }
}

/* ── 4. Header ─────────────────────────────────────────────────── */
.app-header {
  /* ⚠️ 这里原有 backdrop-filter: blur(14px) —— 已删除。
     background 是 var(--card)=#ffffff / #111a2e,**完全不透明**,
     模糊层一个像素都渲染不出来,却让全 App 最常驻的元素每帧参与合成。
     删掉零视觉变化,纯赚。 */
  position: sticky;
  top: 0;
  z-index: 30;
  /* iOS Safari often reports inset-top = 0 even on notched phones (only PWA
     mode fills in the real value), so guarantee a minimum 18px gap so the
     brand row never kisses the status bar / Dynamic Island. */
  padding: calc(14px + max(env(safe-area-inset-top), 18px)) calc(16px + env(safe-area-inset-right)) 12px calc(16px + env(safe-area-inset-left));
  background: var(--card);
}
:root[data-theme="dark"] .app-header {
  background: var(--card);
}
.top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.brand {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  cursor: pointer;
}
.brand:active { transform: scale(0.99); }
/* 今日可签到的小红点(在 logo 左上角) */
.checkin-dot { position: absolute; top: -2px; left: -3px; width: 9px; height: 9px; border-radius: 50%; background: var(--brand-2, #ff5722); box-shadow: 0 0 0 2px var(--bg, #0f1424); animation: pulse 2.4s ease-in-out infinite; z-index: 2; }
.checkin-dot[hidden] { display: none; }
/* 新手高亮引导(聚光灯) */
#tourLayer { position: fixed; inset: 0; z-index: 9998; }
#tourLayer[hidden] { display: none; }
#tourSpot { position: fixed; border-radius: 14px; box-shadow: 0 0 0 9999px rgba(8,10,18,.74); transition: top .25s ease, left .25s ease, width .25s ease, height .25s ease; pointer-events: none; }
#tourCard { position: fixed; width: min(300px, 86vw); background: var(--card); color: var(--ink); border: 1px solid var(--line); border-radius: 16px; padding: 16px 18px; box-shadow: var(--shadow-lg); z-index: 9999; }
#tourCard #tourText { margin: 0 0 12px; font-size: 14px; line-height: 1.5; }
#tourCard .tour-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
#tourCard .tour-progress { font-size: 12px; font-weight: 700; color: var(--muted); }
#tourCard #tourSkip { border: 0; background: transparent; color: var(--muted); font-size: 13px; font-weight: 700; cursor: pointer; padding: 6px 4px; }
#tourCard #tourNext { border: 0; background: var(--brand-grad); color: #fff; font-size: 14px; font-weight: 800; padding: 9px 18px; border-radius: var(--radius-md); cursor: pointer; }
/* 「其他」快捷菜单 */
.more-actions-list { display: grid; gap: 8px; }
/* 去掉每行的灰色描边卡片,改成「无边行 + 行间内缩分隔线」—— 和 Alat 列表(.tool-row)
   同一套版式,视觉更整、也不再是一堆并排的方框。 */
.more-action-row { position: relative; display: flex; align-items: center; gap: 14px; width: 100%; padding: 14px 16px; border: 0; border-radius: var(--radius); background: transparent; cursor: pointer; text-align: left; }
/* 分隔线从图标右侧的标题处起(与 .tool-row 的 left:89px 同口径:16 padding + 52 图标 + 14 gap ≈ 82) */
.more-action-row:not(:last-of-type)::after { content: ""; position: absolute; left: 82px; right: 16px; bottom: 0; height: 1px; background: var(--line); }
.more-action-row:active { background: var(--soft); transform: scale(0.99); }
.more-action-row .ma-ic { flex: none; width: 52px; height: 52px; display: grid; place-items: center; border-radius: 15px; background: var(--brand-soft); color: var(--brand-2); }
.more-action-row .ma-ic svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.more-action-row .ma-ic-orange { background: rgba(255, 138, 61, .16); color: #ff6a2b; }
.more-action-row .ma-ic-purple { background: rgba(139, 92, 246, .14); color: #8b5cf6; }
.more-action-row .ma-text { flex: 1; min-width: 0; display: grid; gap: 2px; }
.more-action-row .ma-text b { font-size: 16px; font-weight: 800; letter-spacing: -.01em; color: var(--ink-strong); }
.more-action-row .ma-text small { font-size: 13px; color: var(--muted); }
.more-action-row .ma-chev { flex: none; width: 20px; height: 20px; color: var(--muted); }
/* ── 签到弹窗(精修版)──────────────────────────── */
.checkin-card { text-align: center; background: var(--bg); padding: 16px; gap: 12px; max-height: 90vh; max-height: 90dvh; overflow-y: auto; }
.checkin-card .modal-heading { gap: 3px; margin-bottom: 12px; }
.checkin-card .modal-heading h3 { font-size: 19px; }
#checkinMainView { display: grid; gap: 12px; }
#checkinMainView[hidden], #checkinCalView[hidden] { display: none; }
/* hero 卡 */
.checkin-hero { background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 18px 16px 16px; display: grid; gap: 12px; }
.checkin-streak { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.checkin-streak[hidden] { display: none; }
.cs-flame { font-size: 30px; line-height: 1; filter: grayscale(1) opacity(0.4); }
.cs-flame.on { filter: none; }
.cs-numrow { display: inline-flex; align-items: baseline; gap: 7px; }
.cs-num { font-size: 46px; font-weight: 900; line-height: 1; color: var(--ink-strong, var(--ink)); letter-spacing: -0.02em; }
.cs-unit { font-size: 22px; font-weight: 800; color: var(--brand-2); }
.cs-label { font-size: 13px; font-weight: 700; color: var(--muted); margin-top: 2px; }
/* 7 天循环连珠 */
.checkin-week[hidden] { display: none; }
.checkin-cycle { position: relative; display: flex; align-items: center; justify-content: space-between; padding: 12px 2px 4px; }
.checkin-cycle::before { content: ""; position: absolute; left: 18px; right: 18px; top: 28px; height: 2px; background: var(--soft); z-index: 0; }
.cyc { position: relative; z-index: 1; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; font-size: 12.5px; font-weight: 800; color: var(--muted); background: var(--soft); box-shadow: 0 0 0 3px var(--card); }
.cyc.done { background: var(--accent-grad); color: #fff; }
.cyc.reward { color: var(--brand-2); background: var(--brand-soft); box-shadow: 0 0 0 3px var(--card), inset 0 0 0 2px var(--brand-2); }
.cyc.reward.done { background: var(--accent-grad); color: #fff; box-shadow: 0 0 0 3px var(--card); }
.cyc-badge { position: absolute; top: -15px; left: 50%; transform: translateX(-50%); background: var(--brand-2); color: #fff; font-size: 9.5px; font-weight: 800; padding: 2px 6px; border-radius: 999px; white-space: nowrap; box-shadow: 0 4px 10px -3px rgba(255, 87, 34, 0.6); }
.cyc-spark { position: absolute; top: -13px; right: -11px; color: var(--brand-2); font-size: 13px; line-height: 1; }
.cyc-progress { font-size: 14px; font-weight: 800; color: var(--ink); margin-top: 16px; }
.cyc-hint { font-size: 12.5px; font-weight: 600; color: var(--muted); margin-top: 2px; }
/* 领取按钮 */
.checkin-claim { display: grid; gap: 8px; }
.checkin-claim[hidden] { display: none; }
.checkin-claim-btn { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 10px; padding: 15px; border: 0; border-radius: var(--radius-md); background: var(--accent-grad); color: #fff; font-size: 16px; font-weight: 800; cursor: pointer; box-shadow: 0 10px 24px -8px rgba(255, 87, 34, 0.6); }
.checkin-claim-btn:active { transform: scale(0.99); }
.checkin-claim-btn:disabled { opacity: 0.6; cursor: default; }
.checkin-claim-btn .ck-play { flex: none; width: 30px; height: 30px; border-radius: 9px; background: rgba(255, 255, 255, 0.22); display: grid; place-items: center; }
.checkin-claim-btn .ck-play svg { width: 15px; height: 15px; fill: #fff; }
.checkin-claim-note { font-size: 12px; color: var(--muted); font-weight: 600; }
/* 主动看广告换 AI:次要样式(描边+软底),与主领取按钮区分 */
.checkin-adbonus { display: grid; gap: 6px; margin-top: 10px; }
.checkin-adbonus[hidden] { display: none; }
.checkin-adbonus-btn { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 9px; padding: 13px; border: 1.5px solid var(--brand-ring); border-radius: var(--radius-md); background: var(--brand-soft); color: var(--brand-2); font-size: 15px; font-weight: 800; cursor: pointer; }
.checkin-adbonus-btn:active { transform: scale(0.99); }
.checkin-adbonus-btn:disabled { opacity: 0.5; cursor: default; }
.checkin-adbonus-btn .ck-play { flex: none; width: 26px; height: 26px; border-radius: 8px; background: var(--brand-soft); display: grid; place-items: center; }
.checkin-adbonus-btn .ck-play svg { width: 13px; height: 13px; fill: currentColor; }
.checkin-claim-note[hidden] { display: none; }
/* 状态行(未登录/付费) */
.checkin-body { display: grid; gap: 6px; }
.checkin-body[hidden] { display: none; }
.checkin-state { font-size: 13px; color: var(--muted); font-weight: 600; line-height: 1.5; }
.checkin-state.ok { color: var(--ok, #16a34a); font-weight: 700; }
/* Saldo AI 行 */
.checkin-saldo { display: flex; align-items: center; gap: 12px; width: 100%; padding: 13px 14px; border: 0; border-radius: var(--radius); background: var(--card); box-shadow: var(--shadow-sm); cursor: pointer; text-align: left; }
.checkin-saldo[hidden] { display: none; }
.checkin-saldo:active { transform: scale(0.995); }
.checkin-saldo .sa-ic { flex: none; width: 42px; height: 42px; border-radius: 13px; background: var(--brand-soft); color: var(--brand-2); display: grid; place-items: center; }
.checkin-saldo .sa-ic svg { width: 22px; height: 22px; fill: currentColor; }
.checkin-saldo .sa-text { flex: 1; min-width: 0; display: grid; gap: 1px; }
.checkin-saldo .sa-text b { font-size: 14.5px; font-weight: 800; color: var(--ink); }
.checkin-saldo .sa-text small { font-size: 11.5px; color: var(--muted); line-height: 1.3; text-transform: none; }
.checkin-saldo .sa-val { display: inline-flex; align-items: baseline; gap: 3px; white-space: nowrap; }
.checkin-saldo .sa-val i { font-style: normal; font-size: 24px; font-weight: 900; color: var(--ink-strong, var(--ink)); }
.checkin-saldo .sa-val span { font-size: 13px; font-weight: 800; color: var(--brand-2); }
.checkin-saldo .sa-chev { flex: none; width: 18px; height: 18px; color: var(--muted); }
/* Riwayat 周条 */
.checkin-hist { background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 14px; text-align: left; }
.checkin-hist[hidden] { display: none; }
.checkin-hist-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.checkin-hist-head > strong { font-size: 14.5px; font-weight: 800; color: var(--ink); }
.checkin-seecal { display: inline-flex; align-items: center; gap: 3px; border: 0; background: transparent; color: var(--brand-2); font-size: 12.5px; font-weight: 800; cursor: pointer; padding: 2px; }
.checkin-seecal svg { width: 14px; height: 14px; }
.checkin-weekstrip { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.ws-day { display: grid; justify-items: center; gap: 6px; }
.ws-circle { width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: var(--soft); font-size: 13px; font-weight: 800; color: var(--muted-strong, var(--ink)); font-feature-settings: "tnum", "lnum"; }
.ws-circle.today:not(.done) { box-shadow: inset 0 0 0 2px var(--brand-2); color: var(--brand-2); }
.ws-circle.done { background: var(--accent-grad); color: #fff; }
.ws-circle svg { width: 16px; height: 16px; fill: none; stroke: #fff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.ws-name { font-size: 11px; font-weight: 700; color: var(--muted); }
/* 励志条 */
.checkin-motivate { display: flex; align-items: center; gap: 12px; padding: 14px; border-radius: var(--radius); background: var(--brand-soft); text-align: left; }
.checkin-motivate[hidden] { display: none; }
.cm-flame { font-size: 26px; flex: none; line-height: 1; }
.cm-text { flex: 1; min-width: 0; display: grid; gap: 2px; }
.cm-text strong { font-size: 14px; font-weight: 800; color: var(--ink); }
.cm-text small { font-size: 12px; color: var(--muted); line-height: 1.35; }
.cm-art { flex: none; color: var(--brand-2); opacity: 0.85; }
.cm-art svg { width: 34px; height: 34px; }
/* 日历视图 */
.checkin-cal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.checkin-cal-back { flex: none; width: 36px; height: 36px; border: 0; border-radius: 50%; background: var(--soft); color: var(--ink); display: grid; place-items: center; cursor: pointer; }
.checkin-cal-back svg { width: 18px; height: 18px; }
.checkin-cal-head > strong { flex: 1; text-align: center; font-size: 16px; font-weight: 800; color: var(--ink); margin-right: 36px; }
.checkin-cal-monthbar { display: flex; align-items: center; justify-content: space-between; margin: 10px 2px 12px; }
.checkin-cal-monthbar #checkinCalTitle { font-size: 14px; font-weight: 800; color: var(--ink); }
.checkin-cal-nav { display: inline-flex; gap: 6px; }
.checkin-cal-nav button { width: 30px; height: 30px; border: 0; border-radius: 9px; background: var(--soft); color: var(--ink); display: grid; place-items: center; cursor: pointer; }
.checkin-cal-nav button:active { transform: scale(0.95); }
.checkin-cal-nav button svg { width: 15px; height: 15px; }
.checkin-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 6px; }
.checkin-weekdays span { font-size: 11px; font-weight: 700; color: var(--muted); text-align: center; }
.checkin-calendar { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.checkin-calendar span { aspect-ratio: 1 / 1; display: grid; place-items: center; font-size: 12.5px; font-weight: 700; color: var(--ink); border-radius: 50%; }
.checkin-calendar span.is-empty { visibility: hidden; }
.checkin-calendar span.muted { color: var(--muted); opacity: 0.45; }
.checkin-calendar span.today { box-shadow: inset 0 0 0 2px var(--brand-2); color: var(--brand-2); font-weight: 800; }
.checkin-calendar span.done { background: var(--accent-grad); color: #fff; font-weight: 800; }
.checkin-calendar span.done svg { width: 15px; height: 15px; fill: none; stroke: #fff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.checkin-calendar span.done.today { box-shadow: inset 0 0 0 2px #fff; }
.checkin-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; margin-top: 14px; }
.checkin-legend .cl { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; color: var(--muted); }
.checkin-legend .cl i { width: 16px; height: 16px; border-radius: 50%; }
.checkin-legend .cl.done i { background: var(--accent-grad); }
.checkin-legend .cl.today i { box-shadow: inset 0 0 0 2px var(--brand-2); }
.checkin-legend .cl.miss i { background: var(--soft); }
.brand h1 {
  font-size: 16px;
  font-weight: 900;
  line-height: 1.15;
  letter-spacing: 0.08em;
}
.brand p {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}
.brand-mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: #ffffff;
  color: #111111; /* C is black */
  box-shadow: 0 4px 12px rgba(255, 87, 34, 0.18), 0 1px 3px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(17, 17, 17, 0.08);
}
.brand-mark svg {
  width: 26px;
  height: 26px;
}
/* ── 节庆装扮 ────────────────────────────────────────────────────────────
   装饰只占页眉四周那圈 22px padding(.app-header padding:22px,内容占 22,22–297,120)。
   画到中间会被 logo / CHECKO / 0% 药丸压住 —— 旧版清真寺就是这么被切半边的。
   配色不写死:applySeasonalSkin 往 body 上灌 --skin-* 变量,17 套共用这几条规则。 */
.skin-scene { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
.app-header > .top-row, .app-header > .seasonal-banner { position: relative; z-index: 1; }

/* 上/下两条横带:整宽拉伸(只放点和色块,拉伸不失真) */
.skin-band { position: absolute; left: 0; width: 100%; height: 22px; display: block; }
.skin-top { top: 0; }
.skin-bot { bottom: 0; }
/* 角落母题簇:固定尺寸,锚在角上。页眉宽度会变(320→420+),固定尺寸才不会把灯笼拉扁 */
.skin-cl { position: absolute; display: block; }
.skin-tr { top: 0; right: 0; }
.skin-tl { top: 0; left: 0; }
.skin-bl { bottom: 0; left: 0; }
.skin-br { bottom: 0; right: 0; }

/* 页眉底色:淡色洗一层,深色模式走 --skin-wash-dark */
body[data-skin] .app-header { background: linear-gradient(180deg, var(--skin-wash), var(--card) 76%); }
:root[data-theme="dark"] body[data-skin] .app-header { background: linear-gradient(180deg, var(--skin-wash-dark), var(--card) 76%); }

/* 祝福语接管副标题(不再另起横幅)。nowrap + 省略号:「Selamat Kenaikan Isa Al Masih」这种
   长祝福语不能把页眉撑高 —— 撑高会顶掉下面整屏布局。 */
.brand-sub-greet { font-weight: 800; letter-spacing: .01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--skin-tint); }
:root[data-theme="dark"] .brand-sub-greet { color: var(--skin-tint-dark); }
/* 旧横幅:装扮改走副标题后不再使用,保留规则只为老包升级时不留残影 */
.seasonal-banner { display: none !important; }
:root[data-theme="dark"] .brand-mark {
  background: #1a1a1a;
  color: #f5f5f5;
  border-color: rgba(255, 255, 255, 0.08);
}
.language-switch {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: var(--radius-pill);
  background: var(--soft);
  border: 1px solid var(--line);
}
.language-switch button {
  min-width: 32px;
  height: 28px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted-strong);
}
.language-switch button.active {
  background: var(--brand-grad);
  color: #fff;
  box-shadow: 0 4px 12px -4px rgba(255, 90, 40, 0.5);
}

/* ── Simple mode ──────────────────────────────────────────────
   Conversational variant: bottom nav drops Mutasi + Bills tabs,
   Profile side-menu hides per-entity CRUD panels (those are reached
   through chat: catat / 改 / 删). Detailed views still exist in code
   so chat-driven actions can render them, just not in chrome. */
.phone-app[data-ui-mode="simple"] .bottom-nav {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.phone-app[data-ui-mode="simple"] .bottom-nav button[data-view="transactions"],
.phone-app[data-ui-mode="simple"] .bottom-nav button[data-view="debt"] {
  display: none;
}
/* In simple mode, surface Mutasi + Bills inside Profile's side menu
   (they're not in the bottom nav). All other Profile menu items stay
   visible so users keep full access via Profile.
   Use .side-menu .side-menu-nav so we beat the .side-menu button rule. */
.side-menu .side-menu-nav { display: none !important; }
.phone-app[data-ui-mode="simple"] .side-menu .side-menu-nav {
  display: grid !important;
}

/* Header budget shortcut (replaces former language slot) */
/* 预算入口:卡片图标 | 分隔线 | 百分比,横排药丸(描边) */
.header-budget-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  height: 44px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  cursor: pointer;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.header-budget-pill:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.header-budget-pill:active { transform: scale(0.97); }
.hbp-ic { width: 22px; height: 22px; color: var(--ink); flex: none; }
.hbp-divider { width: 1px; height: 18px; background: var(--line); flex: none; }
.header-budget-pill strong {
  font-size: 14px; font-weight: 800; color: var(--brand-2);
  letter-spacing: -0.01em; line-height: 1;
  font-feature-settings: "tnum", "lnum";
}
/* 暗色下 --brand-2 是偏白桃橙(#ff8a65),这个百分比数字读着发白 → 用饱和橙 */
:root[data-theme="dark"] .header-budget-pill strong { color: #ff6a3d; }

/* Language card inside Profile → Settings */
.language-card { display: grid; gap: 12px; }
.language-card .settings-language {
  justify-self: start;
  background: var(--soft);
}
.language-card .settings-language button {
  min-width: 44px;
  height: 32px;
  font-size: 13px;
}

/* Account card (Profile → Settings) */
.account-card { display: grid; gap: 12px; }
.account-status {
  display: grid;
  gap: 4px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--soft);
}
.account-status-label {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-strong);
  word-break: break-all;
}
.account-quota {
  font-size: 12px;
  color: var(--muted);
  font-feature-settings: "tnum", "lnum";
}
.account-card .form-actions.single {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
/* ── Akun 页:卡片 + 彩色图标块(参照 Umum 风格)──────────────── */
.account-info-card { display: grid; gap: 0; padding: 16px 16px 10px; }
.account-user { display: flex; align-items: center; gap: 13px; padding: 2px 2px 12px; }
.account-avatar { flex: none; width: 44px; height: 44px; border-radius: 13px; display: grid; place-items: center; background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.account-avatar svg { width: 23px; height: 23px; }
.account-user-info { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 9px; }
/* 退出按钮移到账户行右上角(紧凑图标),去掉「Akun Checko」副标题后更干净 */
.account-logout-btn { flex: none; align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px 7px 11px; border-radius: 999px; border: 0; background: rgba(239,68,68,.14); color: #ef4444; font-size: 13px; font-weight: 800; cursor: pointer; }
.account-logout-btn svg { width: 16px; height: 16px; }
/* 整行版:放在账号卡最底部,独立按钮 */
.account-logout-full { align-self: stretch; width: 100%; justify-content: center; margin-top: 12px; padding: 12px; border-radius: 14px; font-size: 14px; }
.account-logout-btn:active { transform: scale(0.97); }
.account-logout-btn[hidden] { display: none; }
.account-user-info b { max-width: 100%; font-size: 15.5px; font-weight: 800; color: var(--ink-strong, var(--ink)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-user-info small { font-size: 12.5px; color: var(--muted); }
.account-divider { height: 1px; background: var(--line); margin: 0 -2px; }
.account-row { display: flex; align-items: center; gap: 12px; width: 100%; padding: 13px 2px; border: 0; background: transparent; cursor: pointer; text-align: left; }
.account-row:active { background: var(--soft); border-radius: 12px; }
.account-row .ar-ic { flex: none; width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; }
.account-row .ar-ic svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ar-ic-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.ar-ic-orange svg { fill: currentColor; stroke: none; }
/* Kuota AI 星星:tile + 图标放大到与链接图标(.sch-ic 44/23)一致,金黄实心星
   (fill/stroke 显式覆盖 .account-row .ar-ic svg 的 fill:none,否则只描边不填充) */
#accountQuotaRow .ar-ic { width: 44px; height: 44px; border-radius: 13px; background: rgba(251, 191, 36, 0.16); color: #fbbf24; }
#accountQuotaRow .ar-ic svg { width: 23px; height: 23px; fill: currentColor; stroke: none; }
.ar-ic-red { background: rgba(239, 68, 68, 0.12); color: #ef4444; }
.account-row .ar-text { flex: none; display: grid; gap: 1px; }
.account-row .ar-text > b { font-size: 13.5px; font-weight: 800; color: var(--ink); }
.account-row .ar-sub { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.account-row .ar-sub i { font-style: normal; color: var(--brand-2); font-weight: 800; font-feature-settings: "tnum", "lnum"; }
.account-row .ar-segs { flex: 1; display: flex; gap: 3px; min-width: 0; margin: 0 4px; }
.account-row .ar-segs i { flex: 1; height: 7px; border-radius: 3px; background: var(--line); }
.account-row .ar-segs i.on { background: var(--brand-2); }
.account-row .ar-chev { flex: none; width: 18px; height: 18px; color: var(--muted); }
.account-logout .ar-text > b { color: #ef4444; }
.account-logout .ar-text { flex: 1; }
/* 第三方账号绑定(Akun terhubung)*/
.acc-head--static { cursor: default; }
.linked-list { display: grid; gap: 2px; padding-top: 4px; }
.linked-row { display: flex; align-items: center; gap: 12px; padding: 13px 2px; }
.linked-row + .linked-row { border-top: 1px solid var(--line); }
.linked-ic { flex: none; width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; background: var(--soft); }
.linked-ic svg { width: 20px; height: 20px; }
.linked-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; color: var(--ink); }
.linked-right { flex: none; display: inline-flex; align-items: center; gap: 8px; }
/* 已连接:绿色状态胶囊 + 低调解绑小键 */
.linked-badge { font-size: 12px; font-weight: 800; color: #10a35e; display: inline-flex; align-items: center; gap: 4px; padding: 5px 11px; border-radius: 999px; background: rgba(16, 163, 94, 0.14); }
.linked-badge::before { content: "✓"; font-weight: 900; }
.linked-link { border: 1.5px solid var(--brand-2); background: transparent; color: var(--brand-2); font-size: 13px; font-weight: 800; padding: 7px 18px; border-radius: 999px; cursor: pointer; }
.linked-link:active { background: var(--brand-soft); }
.linked-unlink { border: 1px solid var(--line); background: transparent; color: var(--muted); font-size: 12px; font-weight: 700; padding: 5px 11px; border-radius: 999px; cursor: pointer; }
.linked-unlink:active { color: #ef4444; border-color: #ef4444; }
.linked-hint { font-size: 12px; font-weight: 700; color: var(--muted); }
/* Keluar:单行,收紧高度(比配额行矮一截) */
.account-logout { padding-top: 8px; padding-bottom: 8px; }
.account-logout .ar-ic { width: 30px; height: 30px; }
.account-signin-row { padding-top: 10px; }
/* 卡片头:彩色图标块 + 标题/副标题(密码/邮箱卡)*/
.settings-card-head { display: flex; align-items: flex-start; gap: 13px; margin-bottom: 4px; }
/* 可折叠设置卡(密码/邮箱):默认只显示头,点头展开表单 */
.acc-head { cursor: pointer; margin-bottom: 0; }
.acc-head .acc-chev { width: 20px; height: 20px; flex: none; margin-left: auto; align-self: center; color: var(--muted); transition: transform var(--dur) var(--ease); }
.acc-card.open .acc-head { margin-bottom: 14px; }
.acc-card.open .acc-chev { transform: rotate(180deg); color: var(--brand-2); }
.acc-card:not(.open) > form { display: none; }
.settings-card-head .sch-ic { flex: none; width: 44px; height: 44px; border-radius: 13px; display: grid; place-items: center; }
.settings-card-head .sch-ic svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sch-ic-purple { background: rgba(139, 92, 246, 0.14); color: #8b5cf6; }
.sch-ic-blue { background: rgba(56, 189, 248, 0.18); color: #2f9bf0; }
.settings-card-head h3 { font-size: 16px; font-weight: 800; color: var(--ink-strong, var(--ink)); margin: 1px 0 2px; }
.settings-card-head p { font-size: 12.5px; color: var(--muted); line-height: 1.4; }
/* 邮箱卡按钮:橙色描边(参照图)*/
.form-actions.single.form-actions--outline > button[type="submit"] { background: transparent; border: 1.5px solid var(--brand-2); color: var(--brand-2); box-shadow: none; }
.form-actions.single.form-actions--outline > button[type="submit"]:hover { background: var(--brand-soft); }

/* Export choices modal */
.export-choices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 4px 0 12px;
}
/* Use a unique class + selector to avoid .form-actions button gradient
   from cascading onto these. */
button.export-choice {
  display: grid;
  gap: 6px;
  padding: 18px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  text-align: center;
  cursor: pointer;
  box-shadow: none;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
button.export-choice:hover {
  border-color: var(--brand);
  background: var(--brand-soft);
  transform: translateY(-1px);
  box-shadow: none;
}
button.export-choice .export-choice-tag {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--brand);
}
button.export-choice .export-choice-copy {
  font-size: 11px;
  color: var(--muted-strong);
  font-weight: 600;
}

/* ── Export panel (资料 → 下载明细) ───────────────────────────── */
.export-panel { display: grid; gap: 14px; }
.export-format {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--soft);
}
.export-format button {
  border: 0;
  padding: 9px 14px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted-strong);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.export-format button.active {
  background: var(--card);
  color: var(--ink-strong);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08);
}
/* 导出空盒文字左对齐,和上面标题一致(原 .empty-copy 居中显得没对齐) */
.export-records .empty-copy { text-align: left; }
/* 流水窗口渲染的底部哨兵:滑到这就多渲一屏(顺带告知还有多少条) */
.tx-load-more { text-align: center; padding: 14px 0 6px; font-size: 12.5px; color: var(--muted, #64748b); }
/* 提醒模块:每项 = 开关 + 紧跟其下的自定义参数(天数/百分比) */
.reminder-module { display: block; }
.rem-th { display: grid; gap: 6px; }
.rem-th span { font-size: 12px; color: var(--muted-strong); font-weight: 600; }
.rem-th input { height: 42px; width: 100%; padding: 0 12px; border: 0; border-radius: var(--radius-sm); background: var(--soft); color: var(--ink); font-size: 14px; font-weight: 600; }
.rem-th input:focus { outline: none; background: var(--hover); box-shadow: none; }
/* 模块内联参数:标签左 + 紧凑数字框右,缩进对齐文字,跟随上方开关 */
.rem-th-inline { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 2px 0 12px; padding: 10px 12px; background: var(--soft); border-radius: var(--radius-sm); }
.rem-th-inline span { font-size: 12.5px; color: var(--muted-strong); font-weight: 600; }
.rem-th-inline input { width: 96px; flex: none; height: 38px; text-align: center; padding: 0 8px; border: 0; border-radius: 10px; background: var(--card); color: var(--ink); font-size: 14px; font-weight: 700; box-shadow: var(--shadow-sm); }
.rem-th-inline input:focus { outline: none; box-shadow: 0 0 0 2px var(--brand-soft); }
.reminder-module.is-off .rem-th-inline { opacity: .45; }
.reminder-module.is-off .rem-th-inline input { pointer-events: none; }
/* 单位后缀(% / hari)放进输入框内,与数值成组居中 */
.rem-th-field { display: inline-flex; align-items: center; justify-content: center; gap: 3px; flex: none; width: 96px; height: 38px; padding: 0 8px; background: var(--card); border-radius: 10px; box-shadow: var(--shadow-sm); box-sizing: border-box; }
.rem-th-field:focus-within { box-shadow: 0 0 0 2px var(--brand-soft); }
.rem-th-inline .rem-th-field input { width: 42px; height: 100%; flex: none; text-align: right; padding: 0; background: transparent; box-shadow: none; border-radius: 0; }
.rem-th-inline .rem-th-field input:focus { box-shadow: none; background: transparent; }
.rem-th-unit { font-size: 12.5px; color: var(--muted-strong); font-weight: 700; pointer-events: none; }
.export-filename { display: grid; gap: 6px; }
.export-filename > span { font-size: 12px; color: var(--muted); font-weight: 600; }
.export-filename-row {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--soft);
  padding: 0 12px;
}
.export-filename-row:focus-within { background: var(--hover); }
.export-filename-row input {
  flex: 1 1 auto;
  min-width: 0;
  height: 44px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-size: 14px;
}
.export-filename-row input:focus { outline: none; }
.export-ext { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--muted); }
.export-preview { display: grid; gap: 8px; }
.export-preview-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
.export-preview-head > span:first-child { font-size: 12px; color: var(--muted); font-weight: 600; }
.export-count { font-size: 12px; font-weight: 700; color: var(--brand); }
.export-table {
  display: grid;
  gap: 2px;
  max-height: 230px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.export-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  gap: 0 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--soft);
}
.export-row-name {
  grid-column: 1; grid-row: 1;
  font-size: 13px; font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.export-row-meta {
  grid-column: 1; grid-row: 2;
  font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.export-row-amt {
  grid-column: 2; grid-row: 1 / span 2;
  align-self: center;
  font-size: 13px; font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.export-row-amt.out { color: var(--danger); }
.export-row-amt.in { color: var(--success, #16a34a); }
.export-more { font-size: 12px; color: var(--muted); text-align: center; padding: 4px 0; }
.export-download {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 50px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--brand-grad);
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  cursor: pointer;
  box-shadow: 0 8px 20px -8px var(--brand);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.export-download:active { transform: scale(0.98); }
.export-download:disabled { opacity: 0.55; cursor: default; }
.export-status { font-size: 13px; font-weight: 700; text-align: center; margin: 0; }
.export-status.busy { color: var(--muted-strong); }
.export-status.done { color: var(--success, #16a34a); }
.export-status.fail { color: var(--danger); }

/* Generate modal: transaction count under the filename */
.export-gen-count { font-size: 12px; font-weight: 700; color: var(--brand); margin: 0; }

/* Download list (资料 → 下载明细): one row per generated file */
/* 下载 tab:说明文字与文件卡之间留间距(section-heading.compact 基础是 margin:0,贴太紧) */
#exportTabDownload .section-heading.compact { margin-bottom: 14px; }
.export-records { display: grid; gap: 8px; }
.export-record {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 0;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
.export-record-ic {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: var(--brand-soft); color: var(--brand-2);
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
}
.export-record-ic--csv { background: rgba(16, 185, 129, .14); color: #10a35e; }
.export-record-main { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.export-record-name {
  font-size: 14px; font-weight: 700; color: var(--ink-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.export-record-meta {
  font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.export-record-exp { font-size: 11px; color: var(--muted); opacity: .85; }
.export-record-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.export-record-act {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  cursor: pointer;
}
.export-record-act svg { width: 18px; height: 18px; }
.export-record-act:active { transform: scale(0.94); }
.export-record-act--dl { background: var(--brand-grad); color: #fff; }
/* 下载生成中:按钮内转圈(行内,不浮窗)。隐藏下载箭头,盖上旋转环 */
.export-record-act--dl.is-loading { pointer-events: none; }
.export-record-act--dl.is-loading svg { visibility: hidden; }
.export-record-act--dl.is-loading::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px;
  border: 2px solid rgba(255,255,255,0.45); border-top-color: #fff; border-radius: 50%;
  animation: authspin 0.7s linear infinite;
}
.export-record-act { position: relative; }
.export-record-act--ghost { background: var(--soft); color: var(--brand-2); }
.export-record-del {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--soft); color: var(--muted);
  cursor: pointer;
}
.export-record-del svg { width: 15px; height: 15px; }
.export-record-del:active { transform: scale(0.94); }

/* Admin badge on subscription panel (when /api/me returns isAdmin) */
#profileSubscription[data-admin="1"]::before {
  content: "Admin · 可随时切换套餐，无广告";
  display: block;
  margin-bottom: 10px;
  padding: 8px 12px;
  background: var(--brand-soft);
  color: var(--brand);
  border: 1px solid var(--brand-ring);
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* Spending stats range chooser (chip row inside an AI message card) */
.stats-range-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
/* Chooser card has no header above the chips → no extra top gap. */
.stats-range-card .stats-range-row { margin-top: 0; }
.stats-range-chip {
  height: 30px;
  padding: 0 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.stats-range-chip:hover:not(:disabled) {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand);
}
.stats-range-chip.selected {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}
.stats-range-chip:disabled { opacity: 0.65; cursor: not-allowed; }

/* 聊天里给未识别支出补品类:标签 + 可点品类 chip(选一次即学会) */
.cat-pick-label { margin-top: 10px; font-size: 12px; color: var(--muted); font-weight: 600; }
.cat-pick-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cat-pick-chip {
  height: 30px; padding: 0 12px; border-radius: var(--radius-pill);
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: 12px; font-weight: 600; cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.cat-pick-chip:hover { background: var(--brand-soft); border-color: var(--brand); color: var(--brand); }
.cat-pick-chip:active { transform: scale(0.96); }
/* 听不懂兜底:「猜你想问」chips + 手动 Tanya AI 按钮 */
.fallback-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.fallback-chip {
  padding: 9px 14px; border-radius: var(--radius-pill);
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font-size: 13px; font-weight: 700; cursor: pointer;
}
.fallback-chip:active { transform: scale(0.96); }
/* 导航类 chip(设置/帮助中心):中性灰底,和记账类区分 */
.fallback-chip--nav { background: var(--soft); color: var(--muted-strong); }
.fallback-ai-btn {
  margin-top: 10px; width: 100%; border: 0; border-radius: 12px; padding: 10px 11px;
  background: var(--brand-soft); color: var(--brand); font-size: 14px; font-weight: 800; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.2;
}
.fallback-ai-btn .fb-ai-meta { font-size: 11px; font-weight: 700; opacity: 0.72; }
.fallback-ai-btn:active { transform: scale(0.98); }
.fallback-ai-btn:disabled { opacity: .5; }

/* Inline action confirm card (edit/delete in chat) */
.action-confirm-card { transition: opacity 200ms var(--ease); }
.action-confirm-card.expired,
.action-confirm-card.applied,
.action-confirm-card.cancelled,
.action-confirm-card.failed { opacity: 0.65; }
.action-card-buttons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 10px;
}
.action-confirm-btn,
.action-cancel-btn {
  height: 36px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
  border: 0;
  cursor: pointer;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.action-confirm-btn {
  background: var(--brand-grad);
  color: #fff;
  box-shadow: 0 4px 12px rgba(255, 87, 34, 0.32);
}
.action-confirm-btn:hover:not(:disabled) { transform: translateY(-1px); }
.action-cancel-btn {
  background: var(--soft);
  color: var(--ink);
  border: 1px solid var(--line);
}
.action-cancel-btn:hover:not(:disabled) { background: var(--hover); }
.action-confirm-btn:disabled,
.action-cancel-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.action-state-label {
  display: block;
  margin-top: 8px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
}
.expired-label   { background: var(--soft);        color: var(--muted); }
.applied-label   { background: var(--ok-soft);     color: var(--ok); }
.cancelled-label { background: var(--soft);        color: var(--muted-strong); }
.failed-label    { background: var(--danger-soft); color: var(--danger); }

/* Ad modal — free-user gate */
.ad-modal-backdrop {
  /* same as .modal-backdrop but darker + uninteractable backdrop */
  background: rgba(5, 8, 20, 0.86);
}
.ad-modal-card {
  position: relative;
  width: min(92%, 360px);
  max-height: 88vh;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: grid;
  grid-template-rows: auto 1fr auto;
  overflow: hidden;
}
.ad-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: var(--soft);
  border-bottom: 1px solid var(--line);
}
.ad-tag {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  background: var(--warn-soft);
  color: var(--warn);
  border: 1px solid currentColor;
}
.ad-reason {
  font-size: 11px;
  color: var(--muted);
  text-align: right;
}
.ad-modal-body {
  padding: 24px 18px;
  display: grid;
  place-items: center;
  min-height: 220px;
}
.ad-placeholder {
  display: grid;
  gap: 10px;
  text-align: center;
  justify-items: center;
}
.ad-placeholder-art {
  font-size: 64px;
  line-height: 1;
}
.ad-placeholder h3 {
  font-size: 18px;
  font-weight: 800;
}
.ad-placeholder p {
  font-size: 13px;
  color: var(--muted-strong);
  max-width: 240px;
}
.ad-modal-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--line);
  background: var(--soft);
}
.ad-modal-footer button {
  width: 100%;
  height: 40px;
  border-radius: var(--radius-pill);
  font-weight: 700;
  font-size: 13px;
}
.ad-modal-footer button:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}

/* Auth modal status text */
.auth-status {
  font-size: 12px;
  color: var(--muted-strong);
  padding: 8px 12px;
  background: var(--soft);
  border-radius: var(--radius-sm);
  margin-top: 4px;
}

/* ── 5. View shell ─────────────────────────────────────────────── */
.app-view {
  display: none;
  /* 左右吃 env(safe-area) → 曲面屏/挖孔/横屏时内容不被物理边缘吞掉 */
  padding: 14px calc(16px + env(safe-area-inset-right)) 24px calc(16px + env(safe-area-inset-left));
  gap: 12px;
  min-height: 0;
}
/* 原生横幅固定在**页眉正下方**(TOP_CENTER)。原生浮层不参与网页布局,得自己让位。
   用 margin-top 把整个滚动容器下移,而**不是** padding —— 这不是风格偏好,是两个实测差异:
     · padding 方案:sticky 元素的 top 是在 padding **之后**才算的(实测 padding 74 + top 60
       → 吸顶位置跑到 134),得给每个 sticky 元素单独改 top;而且这个交互各引擎不一致
       (预览是 Blink、iOS WKWebView 是 WebKit),赌不起。
     · margin 方案:容器直接从广告下沿开始 —— sticky top:0 天然吸在广告下面(不用动任何
       sticky 规则),内容也永远不会从广告背后滚过去。
   --ad-banner-h 由 bannerAdSizeChanged 写入(自适应横幅各机型高度不同),没回报前按 60px 兜底。
   ⚠️ 只在 body.has-ad-banner 下生效 —— 付费用户/管理员没这个类,排版一像素不变。 */
body.has-ad-banner .app-view {
  margin-top: var(--ad-banner-h, 60px);
}
.app-view.active {
  display: grid;
  grid-auto-rows: min-content;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* 入场动画改由 .view-anim-in 一次性 class 驱动(见下),这里不留常驻动画 ——
     常驻的话 iOS WebKit 会在原生 select 弹层关闭时重播,整屏鬼影。 */
  /* iOS 风格极细滚动条:细、半透明、圆头,拖动时略加深 */
  scrollbar-width: thin;
  scrollbar-color: rgba(120, 130, 150, 0.32) transparent;
}
.app-view.active::-webkit-scrollbar { width: 3px; }
.app-view.active::-webkit-scrollbar-track { background: transparent; }
.app-view.active::-webkit-scrollbar-thumb { background: rgba(120, 130, 150, 0.3); border-radius: 999px; }
.app-view.active::-webkit-scrollbar-thumb:active { background: rgba(120, 130, 150, 0.5); }
/* Lightweight one-shot enter animation for view / panel switches.
   GPU-only (opacity + transform), no reflow, no JS, no extra assets;
   prefers-reduced-motion already neutralizes it globally (see §reduced-motion). */
@keyframes viewIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
#chatView.active {
  padding: 12px 0 0;
  grid-template-rows: 1fr;
  overflow: hidden;
}
#chatView .messages { overflow-y: auto; overscroll-behavior: contain; }

.view-heading {
  display: grid;
  gap: 2px;
}
.drillable-heading {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto; /* [返回左] [标题] [+ 右] */
  align-items: center;
  gap: 10px;
}
.drillable-heading > .heading-title { display: grid; gap: 2px; min-width: 0; }
/* 进入子页(抽屉打开)→ iOS 风:标题居中,返回键在左 */
/* 下钻时:整条 header(返回+标题+号)固定在顶部浮窗,内容在下面滚动 */
/* 抽屉态:清掉 app-view 顶内边距,sticky 头才能贴住顶栏(top:0 会被顶内边距
   顶下来 14px,留出一条没被磨砂罩住的缝隙)。顶部留白改由头自己的 padding 给。 */
body[data-preview-device="mobile"] .app-view:has(.split-workspace.drill-open) { padding-top: 0; }
.app-view:has(.split-workspace.drill-open) .drillable-heading {
  position: sticky;
  top: 0;
  z-index: 20;
  background: transparent;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  /* 贴住顶栏:不再靠负 margin 上拉(对 sticky 钉住位置无效),靠 padding-top:0 */
  margin: 0 -16px 0;
  padding: 14px 16px 8px;
}
/* 标题绝对居中后,显式锁定返回键在左、操作键(+)在右,避免自动塌进中间列 */
.app-view:has(.split-workspace.drill-open) .drillable-heading > .view-back { grid-column: 1; }
.app-view:has(.split-workspace.drill-open) .drillable-heading > .view-actions { grid-column: 3; }
.app-view:has(.split-workspace.drill-open) .drillable-heading .heading-title {
  position: absolute;
  left: 60px; right: 60px;        /* 左右对称留位给返回键/操作键 → 真正屏幕居中 */
  top: 50%; transform: translateY(-50%);
  text-align: center;
  font-size: 17px;
  font-weight: 800;
  color: var(--ink-strong, var(--ink));
  letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none;
}
/* 标题已移到返回键那行 → 隐藏面板内部那条重复标题(紧跟隐藏的 drill-toolbar) */
.split-workspace.drill-open .content-panel.active > .drill-toolbar + .section-heading { display: none; }
.eyebrow {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand);
}
.view-heading h2 { font-size: 24px; color: var(--brand-2); }
/* Drop the orange eyebrow above each view title (redundant with the big title).
   Card-level eyebrows (e.g. "Left today", "Risk") live outside .view-heading and stay. */
.view-heading .eyebrow { display: none; }

.view-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}
.view-back,
.view-add {
  display: none;
  align-items: center;
  gap: 4px;
  height: 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.view-back { width: 40px; height: 40px; padding: 0; justify-content: center; border: 0; background: var(--card); box-shadow: var(--shadow-sm); }
.view-back svg { width: 20px; height: 20px; }
.view-add {
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  background: var(--brand-grad);
  color: #fff;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(var(--brand-2-rgb), 0.32);
}
.view-back svg,
.view-add svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.view-add svg { width: 19px; height: 19px; }
.view-back:hover { background: var(--hover, var(--line)); }
.view-back:active { transform: scale(0.94); }
.view-add:hover { transform: translateY(-1px); }
/* Show back button when drilled into any sub-panel */
.app-view:has(.split-workspace.drill-open) .view-back { display: inline-flex; }
/* Show add button only when drilled into a panel that has an add-target */
.app-view:has(.split-workspace.drill-open .content-panel.active[data-add-target]) .view-add { display: inline-flex; }
/* Form panels (those with data-back-target but no data-add-target) get a Save button */
/* Top-right Save removed for form panels — the bottom submit button is
   the single save action now. */
.view-save {
  display: none;
  align-items: center;
  gap: 4px;
  height: 32px;
  width: auto;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--brand-grad);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(255, 87, 34, 0.32);
  transition: transform var(--dur) var(--ease);
}
.view-save:hover { transform: translateY(-1px); }
.view-save svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Form panels: one save button at the bottom only. Hide the secondary
   "新增/Reset" button (users can go back + tap + to start a new entry)
   and hide the redundant top-right Save (.view-save). */
.content-panel.active[data-back-target]:not([data-add-target]) .form-actions:not(.form-actions--edit) {
  margin-top: 14px;
  grid-template-columns: 1fr;
}
.content-panel.active[data-back-target]:not([data-add-target]) .form-actions:not(.form-actions--edit) .secondary-button {
  display: none;
}
/* --edit 布局:编辑/新增态都显示 取消(左) + 保存(右) */
.content-panel.active[data-back-target]:not([data-add-target]) .form-actions--edit { margin-top: 14px; }

/* Hide the inline drill-toolbar entirely — replaced by .view-actions in heading */
.content-panel > .drill-toolbar { display: none !important; }
.transaction-heading {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 12px;
}
/* 删掉 Mutasi 标题后:只剩"现金流"芯片,靠右对齐 */
.transaction-heading--titleless { justify-content: flex-end; }
.section-heading {
  display: grid;
  gap: 4px;
  margin: 4px 0 4px;
}
.section-heading p { font-size: 13px; color: var(--muted); }
.section-heading.compact { margin: 0; }
/* 标题右上角动作按钮(如固定费用"提前结束") */
.section-heading:has(.header-action) { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.header-action {
  flex: 0 0 auto;
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.header-action:hover { background: var(--hover); }

/* ── 6. Cards (base) ───────────────────────────────────────────── */
.overview-hero,
.saving-card,
.overview-panel,
.settings-card,
.tool-card,
.radar-card,
.transaction-cashflow-card,
.bill-card,
.budget-item,
.account-item,
.paylater-item,
.fixed-cost-item,
.transaction-item {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

/* ── 7. Overview view (Bento) ──────────────────────────────────── */
#overviewView { gap: 14px; }

/* Sticky global search bar (frosted glass), pinned between header and hero */
.ov-search { position: sticky; top: 0; z-index: 25; }
/* 桌面:全局搜索改底部居中浮窗,腾出顶部让模块整齐不留空;结果向上展开 */
@media (min-width: 760px) {
  body:not([data-preview-device="mobile"]) .ov-search {
    position: fixed; top: auto; bottom: 26px;
    left: calc(50% + 160px); transform: translateX(-50%);
    width: min(620px, 54vw); z-index: 95;
  }
  body:not([data-preview-device="mobile"]) .ov-search-bar {
    height: 50px; box-shadow: 0 16px 40px -10px rgba(15, 23, 42, 0.45);
  }
  body:not([data-preview-device="mobile"]) .ov-search-results {
    top: auto; bottom: calc(100% + 10px);
  }
}
.ov-search-bar {
  display: flex; align-items: center; gap: 8px;
  height: 46px; padding: 0 6px 0 14px;
  border-radius: 999px;
  border: 0;
  background: rgba(255, 255, 255, 0.7);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  backdrop-filter: blur(18px) saturate(160%);
  box-shadow: 0 8px 22px -12px rgba(15, 23, 42, 0.3);
}
:root[data-theme="dark"] .ov-search-bar { background: rgba(26, 28, 34, 0.62); }
.ov-search-ic { width: 18px; height: 18px; color: var(--muted); flex: none; }
.ov-search-input {
  flex: 1; min-width: 0; height: 100%;
  border: 0; background: transparent; outline: none;
  font-family: inherit; font-size: 14.5px; color: var(--ink);
}
.ov-search-input::placeholder { color: var(--muted); }
.ov-search-input::-webkit-search-cancel-button { display: none; }
/* 压过全局 input:focus-visible 的黑色描边(--brand=#111);焦点提示交给整条 bar */
.ov-search-input:focus, .ov-search-input:focus-visible { outline: none; box-shadow: none; }
.ov-search-bar:focus-within { border: 0; }
.ov-search-clear, .ov-search-mic {
  flex: none; width: 34px; height: 34px; border: 0; border-radius: 999px;
  display: inline-grid; place-items: center; cursor: pointer;
  background: transparent; color: var(--muted); transition: transform 120ms var(--ease);
}
.ov-search-clear svg { width: 16px; height: 16px; }
.ov-search-mic svg { width: 19px; height: 19px; }
.ov-search-mic { background: transparent; color: var(--brand-2, #ff6a2b); }
.ov-search-mic.listening { background: var(--brand-2, #ff6a2b); color: #fff; animation: ovMicPulse 1.2s ease-in-out infinite; }
.ov-search-clear:active, .ov-search-mic:active { transform: scale(0.92); }
@keyframes ovMicPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 106, 43, 0.45); }
  50% { box-shadow: 0 0 0 7px rgba(255, 106, 43, 0); }
}
.ov-search-results {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0;
  max-height: min(58vh, 460px); overflow-y: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 18px 44px -14px rgba(15, 23, 42, 0.38);
  padding: 6px; z-index: 40;
}
.ov-sr-group { padding: 9px 10px 4px; font-size: 11px; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.ov-sr-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 9px 10px; border: 0; background: transparent; border-radius: 12px;
  cursor: pointer; text-align: left; font-family: inherit;
}
.ov-sr-item:hover, .ov-sr-item:focus-visible { background: var(--soft); outline: none; }
.ov-sr-ic { flex: none; width: 34px; height: 34px; border-radius: 10px; display: inline-grid; place-items: center; }
.ov-sr-ic svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ov-sr-ic--gray { background: var(--soft); color: var(--muted-strong); }
.ov-sr-body { flex: 1; min-width: 0; display: grid; gap: 1px; }
.ov-sr-name { font-size: 13.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ov-sr-meta { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ov-sr-amt { flex: none; font-size: 13px; font-weight: 800; font-feature-settings: "tnum", "lnum"; }
.ov-sr-amt.in { color: var(--ok); }
.ov-sr-amt.out { color: var(--danger); }
.ov-sr-empty { padding: 18px 14px; text-align: center; color: var(--muted); font-size: 13px; }

.overview-hero {
  position: relative;
  display: grid;
  gap: 20px;
  padding: 24px 20px 22px;
  color: var(--hero-ink);
  background: var(--hero-bg);
  border: 0;
  box-shadow: 0 14px 38px rgba(10, 8, 4, 0.42);
  overflow: hidden;
}
.overview-hero::before {
  content: "";
  position: absolute;
  top: -50%;
  right: -30%;
  width: 80%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--brand-ring), transparent 70%);
  pointer-events: none;
}
.overview-hero::after {
  content: "";
  position: absolute;
  bottom: -40%;
  left: -20%;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(34, 211, 238, 0.28), transparent 70%);
  pointer-events: none;
}
/* ── Ringkasan 主卡:浅色白卡版(覆盖 --hero-* 走亮色,照参照图)──── */
.overview-hero {
  --hero-ink: var(--ink);
  --hero-muted: var(--muted);
  --hero-line: var(--line);
  --hero-soft: var(--soft);
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  padding: 20px 18px 18px;
  gap: 16px;
}
.overview-hero::before, .overview-hero::after { display: none; } /* 去掉深色光晕 */
.overview-hero .rp-prefix { color: var(--muted); -webkit-text-fill-color: var(--muted); opacity: 1; }
.overview-motivation-row { display: flex; align-items: flex-start; gap: 11px; position: relative; z-index: 1; }
.overview-motivation-row .ovm-ic { flex: none; color: var(--brand-2); margin-top: 1px; }
.overview-motivation-row .ovm-ic svg { width: 26px; height: 26px; }
.overview-hero #overviewMotivation { color: var(--ink); }
/* SISA HARI INI:奶油橙底盒 + 橙色渐变大数字 */
.overview-hero .overview-safe {
  background: linear-gradient(180deg, rgba(var(--brand-2-rgb), 0.12), rgba(var(--brand-2-rgb), 0.035));
  border-radius: var(--radius-sm);
  padding: 14px 16px 12px;
}
.overview-hero #todaySpendable {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* 超支(今日可用为负):数字转红 + 盒子底色由奶油橙转淡红 —— 负号本身在小屏上
   太不起眼,颜色才是一眼能分辨「还有得花」和「已经超了」的信号。 */
/* ⚠️ 必须写 background-image,不能写 background —— 简写会把上面那条的
   background-clip:text 一起重置回 border-box,结果是整块涂成红方块、字反而没了。 */
.overview-hero #todaySpendable.is-over { background-image: var(--danger-grad); }
.overview-hero .overview-safe.is-over {
  background: linear-gradient(180deg, var(--danger-soft), rgba(220, 38, 38, 0.04));
}
/* 「本月安全额度」也可能是负数(欠得比手上的钱多)。这格是普通实心字,
   不像上面那个大数字走 background-clip:text,所以直接给 color 就行。 */
#safeBalance.is-over, #dailySafe.is-over { color: var(--danger); }
/* 两个指标格:浅灰块 + 彩色方图标 + 数值(无边框) */
.overview-hero .overview-metrics > span { background: var(--soft); border: 0; padding: 12px 13px 13px; gap: 8px; }
.ovm-val { display: flex; align-items: center; gap: 9px; }
.ovm-tic { flex: none; width: 34px; height: 34px; border-radius: 11px; display: grid; place-items: center; }
.ovm-tic svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ovm-tic-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.ovm-tic-green { background: rgba(16, 185, 129, 0.14); color: #10a35e; }
.overview-hero .overview-metrics b { color: var(--ink-strong, var(--ink)); }
.overview-hero .overview-meter { background: var(--line); }
.overview-greeting { display: grid; gap: 8px; min-width: 0; position: relative; z-index: 1; }
.overview-greeting > span:first-child {
  font-size: 12px;
  color: var(--hero-muted);
  font-weight: 600;
}
.overview-title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
#overviewMotivation {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--hero-ink);
}
#overviewDailyStory { font-size: 12px; color: var(--hero-muted); line-height: 1.5; }

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.08);
  color: var(--hero-ink);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  border: 1px solid rgba(255, 255, 255, 0.16);
}
.status-pill::before {
  content: "";
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: #34d399;
  box-shadow: 0 0 8px #34d399;
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* 日期(到日)+ 工资倒计时 一行,替掉原来两个药丸 */
.overview-datebar { display: flex; justify-content: space-between; align-items: center; gap: 8px; position: relative; z-index: 1; margin-top: -6px; }
.ovd-date { display: inline-flex; align-items: center; gap: 6px; color: var(--hero-muted); font-size: 12.5px; font-weight: 600; white-space: nowrap; min-width: 0; }
.ovd-date svg { width: 15px; height: 15px; flex: none; color: var(--brand-2); }
.ovd-date .overview-month { overflow: hidden; text-overflow: ellipsis; line-height: 1.55; }
.ovd-payday { display: inline-flex; align-items: center; gap: 6px; color: var(--hero-muted); font-size: 12.5px; font-weight: 600; white-space: nowrap; }
/* 工资倒计时前面用钞票图标(不再是绿点,避免和下面风险指数圆点重复);保留绿色表"进账" */
.ovd-payday::before { content: ""; width: 15px; height: 15px; flex: none; background: #34d399;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='6' width='20' height='12' rx='2'/%3E%3Ccircle cx='12' cy='12' r='2.4'/%3E%3Cpath d='M5.5 9.5h.01M18.5 14.5h.01'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='6' width='20' height='12' rx='2'/%3E%3Ccircle cx='12' cy='12' r='2.4'/%3E%3Cpath d='M5.5 9.5h.01M18.5 14.5h.01'/%3E%3C/svg%3E") center / contain no-repeat; }
/* 未设工资:徽章变可点 CTA(去录入收入),下划虚线提示可操作 */
.ovd-payday.is-setup { cursor: pointer; color: var(--brand-2, #ff5722); font-weight: 700; text-decoration: underline dotted; text-underline-offset: 2px; }

.overview-safe {
  position: relative;
  z-index: 1;
}
.overview-safe > .eyebrow {
  color: var(--hero-muted);
  letter-spacing: 0.12em;
}
/* Per hari 右对齐副值:大数字下方,横线分隔 */
.overview-perhari { display: flex; flex-direction: row; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--hero-line); }
.overview-perhari small { margin-left: auto; font-size: 12.5px; font-weight: 700; color: var(--hero-muted); text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; }
.overview-perhari b { font-size: 16px; font-weight: 800; color: var(--hero-ink); font-feature-settings: "tnum", "lnum"; letter-spacing: -0.01em; }
.overview-perhari b[hidden] { display: none; }
#todaySpendable {
  display: block;
  font-family: var(--font-sans);
  font-size: clamp(36px, 10vw, 48px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.035em;
  margin-top: 2px;
  background: linear-gradient(120deg, #ffffff 0%, var(--brand-2) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  font-feature-settings: "tnum", "lnum";
}
.daily-allowance-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.daily-allowance-row > span {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  background: var(--hero-soft);
  border: 1px solid var(--hero-line);
  border-radius: var(--radius-sm);
}
.daily-allowance-row small {
  display: block;
  font-size: 10px;
  font-weight: 700;
  color: var(--hero-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.daily-allowance-row b {
  font-feature-settings: "tnum", "lnum";
  font-weight: 800;
  font-size: 16px;
  color: var(--hero-ink);
  letter-spacing: -0.02em;
}

.overview-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 8px;
  position: relative;
  z-index: 1;
}
.overview-metrics > span {
  display: grid;
  gap: 5px;
  padding: 14px 14px 15px;
  background: var(--hero-soft);
  border: 1px solid var(--hero-line);
  border-radius: var(--radius-sm);
  /* 原有 backdrop-filter: blur(8px) 已删 —— 背后是 hero 的平滑渐变,
     渐变模糊之后≈它自己,肉眼看不出差别,但每帧都要重新采样。 */
}
.overview-metrics small,
.overview-extra small,
.saving-stats small {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.overview-metrics small {
  color: var(--hero-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10px;
  font-weight: 700;
}
.overview-metrics b {
  font-feature-settings: "tnum", "lnum";
  font-weight: 800;
  font-size: 15px;
  color: var(--hero-ink);
  letter-spacing: -0.02em;
}
.overview-extra b,
.saving-stats b {
  font-feature-settings: "tnum", "lnum";
  font-weight: 700;
  font-size: 15px;
  color: var(--ink-strong);
}

.meter {
  position: relative;
  height: 6px;
  background: var(--line);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.meter > span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #ef4444 0%, #f59e0b 35%, #34d399 75%, #10b981 100%);
  border-radius: inherit;
  transition: width 380ms var(--ease);
  box-shadow: 0 0 12px rgba(52, 211, 153, 0.6);
}
.overview-meter { z-index: 1; background: rgba(255, 255, 255, 0.18); }
#healthCopy { font-size: 13px; font-weight: 700; color: var(--hero-muted); position: relative; z-index: 1; }
#healthCopy { display: inline-flex; align-items: center; gap: 7px; }
#healthCopy.risk-low { color: var(--green); }
#healthCopy.risk-medium { color: var(--yellow); }
#healthCopy.risk-high { color: var(--red); }
#healthCopy .risk-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
  box-shadow: 0 0 0 0 currentColor;
  animation: riskPulse 1.4s ease-in-out infinite;
}
@keyframes riskPulse {
  0%   { opacity: 1;   box-shadow: 0 0 0 0 currentColor; }
  70%  { opacity: 0.4; box-shadow: 0 0 0 6px transparent; }
  100% { opacity: 1;   box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { #healthCopy .risk-dot { animation: none; } }

/* 省钱段:三张干净白卡(本月省 / 年度目标 / 2×2 统计格) */
.save-month, .save-target { display: grid; gap: 9px; padding: 15px 16px; }
/* 省钱:三块合一面板 */
.saver-merged { display: grid; gap: 11px; padding: 16px; }
.saver-merged .sm-head { display: flex; align-items: center; gap: 10px; }
.saver-merged .sm-head .panel-head-text { flex: 1; min-width: 0; }
.saver-merged .sm-head .panel-head-title { font-size: 12.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.saver-merged .sm-level { flex: none; font-size: 11.5px; font-weight: 800; color: var(--ok); background: rgba(16, 185, 129, 0.14); border-radius: var(--radius-pill); padding: 4px 11px; white-space: nowrap; }
.saver-merged .st-bar { margin-top: 2px; }
/* 底部:等级徽章 + 说明(替掉原 Tanya Sebelum Beli 按钮) */
.saver-merged .sm-rank { display: flex; align-items: center; gap: 13px; margin-top: 4px; padding: 14px 16px; border-radius: 14px; background: rgba(16, 185, 129, 0.08); }
.saver-merged .sm-rank-badge { flex: none; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: rgba(16, 185, 129, 0.16); color: var(--ok); }
.saver-merged .sm-rank-badge svg { width: 24px; height: 24px; }
.saver-merged .sm-rank-txt { min-width: 0; display: grid; gap: 2px; }
.saver-merged .sm-rank-txt b { font-size: 15px; font-weight: 800; color: var(--ok); }
.saver-merged .sm-rank-txt small { font-size: 12.5px; color: var(--muted); line-height: 1.4; }
.save-stats { padding: 6px; }
.sh-head { display: flex; align-items: center; gap: 10px; }
.sh-ic { flex: none; width: 36px; height: 36px; border-radius: 11px; background: rgba(16, 185, 129, 0.16); color: var(--ok); display: grid; place-items: center; }
.sh-ic svg { width: 20px; height: 20px; }
.sh-title { font-size: 12.5px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ok); }
.sh-title--ink { color: var(--ink); }
.sh-amount { display: block; font-size: clamp(30px, 9vw, 42px); font-weight: 900; line-height: 1; letter-spacing: -0.03em; color: var(--ok); font-feature-settings: "tnum", "lnum"; white-space: nowrap; }
.sh-amount .rp-prefix { color: var(--muted); opacity: 1; }
.sh-accent { display: block; width: 46px; height: 4px; border-radius: 2px; background: var(--ok); margin: 4px 0 2px; }
.sh-msg { font-size: 14px; color: var(--muted-strong); line-height: 1.5; margin: 0; }
.sh-ask { display: flex; align-items: center; gap: 10px; width: 100%; margin-top: 4px; padding: 14px 16px; border: 1.5px solid rgba(16, 185, 129, 0.4); border-radius: var(--radius-md); background: var(--card); color: var(--ok); font-size: 15px; font-weight: 800; cursor: pointer; transition: background var(--dur) var(--ease); }
.sh-ask > span { flex: 1; text-align: center; }
.sh-ask svg { width: 20px; height: 20px; flex: none; }
.sh-ask:hover { background: var(--soft); }
.sh-ask:active { transform: scale(0.99); }

/* 年度目标卡 */
.st-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.st-edit { flex: none; width: 34px; height: 34px; border: 0; border-radius: 10px; background: rgba(16, 185, 129, 0.14); color: var(--ok); display: grid; place-items: center; cursor: pointer; }
.st-edit svg { width: 17px; height: 17px; }
.st-amount { display: block; font-size: clamp(22px, 6vw, 30px); font-weight: 900; line-height: 1; letter-spacing: -0.03em; color: var(--ok); font-feature-settings: "tnum", "lnum"; white-space: nowrap; }
.st-amount .rp-prefix { color: var(--muted); opacity: 1; }
.st-bar { height: 10px; border-radius: 99px; background: var(--soft); overflow: hidden; }
.st-bar-fill { display: block; height: 100%; min-width: 10px; width: 0; border-radius: 99px; background: linear-gradient(90deg, #34d399, var(--ok)); transition: width 0.6s var(--ease); }
.st-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 12.5px; color: var(--muted-strong); }
.st-foot b { color: var(--ink); font-weight: 800; font-feature-settings: "tnum", "lnum"; }
.st-foot .st-foot-l .rp-prefix { color: var(--muted); opacity: 1; }
.st-pct.st-pct { color: var(--ok); font-weight: 800; }

/* 2×2 统计格:圆图标左,数值+标签右,内分隔线 */
.ss-grid { display: grid; grid-template-columns: 1fr 1fr; }
.ss-tile { display: flex; align-items: center; gap: 12px; padding: 16px 14px; min-width: 0; }
.ss-tile:nth-child(odd) { border-right: 1px solid var(--line); }
.ss-tile:nth-child(1), .ss-tile:nth-child(2) { border-bottom: 1px solid var(--line); }
.ss-ic { flex: none; width: 46px; height: 46px; border-radius: 50%; background: rgba(16, 185, 129, 0.14); color: var(--ok); display: grid; place-items: center; }
.ss-ic svg { width: 22px; height: 22px; }
.ss-txt { display: grid; gap: 2px; min-width: 0; }
.ss-txt b { font-size: 22px; font-weight: 900; color: var(--ink); letter-spacing: -0.01em; font-feature-settings: "tnum", "lnum"; line-height: 1.05; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ss-txt b.ss-rank { font-size: 16px; color: var(--ok); white-space: normal; line-height: 1.15; }
.ss-txt b .rp-prefix { color: var(--muted); opacity: 1; font-size: 0.66em; }
.ss-txt small { font-size: 12px; color: var(--muted-strong); line-height: 1.25; }
/* 「今年目标」卡内的统计行:一行三个 + 分隔线(替代旧的 2×2 独立卡) */
.save-target .st-stats, .saver-merged .st-stats {
  display: grid; grid-template-columns: repeat(2, 1fr);
  border-top: 1px solid var(--line); margin-top: 5px; padding-top: 12px;
}
.save-target .st-stats .ss-tile, .saver-merged .st-stats .ss-tile { gap: 8px; padding: 0 9px; border: 0; align-items: center; }
.save-target .st-stats .ss-tile + .ss-tile, .saver-merged .st-stats .ss-tile + .ss-tile { border-left: 1px solid var(--line); }
.save-target .st-stats .ss-ic, .saver-merged .st-stats .ss-ic { width: 36px; height: 36px; }
.save-target .st-stats .ss-ic svg, .saver-merged .st-stats .ss-ic svg { width: 18px; height: 18px; }
.save-target .st-stats .ss-txt b, .saver-merged .st-stats .ss-txt b { font-size: 15px; }
.save-target .st-stats .ss-txt b.ss-rank, .saver-merged .st-stats .ss-txt b.ss-rank { font-size: 12.5px; }
.save-target .st-stats .ss-txt small, .saver-merged .st-stats .ss-txt small { font-size: 10.5px; }
/* 底部鼓励卡:左下角 = 段位(徽章 + 段位名 + Level),右侧 = 鼓励语 */
.save-encourage { display: flex; align-items: center; gap: 0; padding: 16px 18px; background: rgba(16, 185, 129, 0.08); }
.se-level { flex: none; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; width: 78px; }
.se-level-txt { display: flex; flex-direction: column; gap: 1px; align-items: center; }
.se-level-txt b.ss-rank { font-size: 12.5px; font-weight: 800; color: var(--ok); line-height: 1.15; white-space: normal; }
.se-level-txt small { font-size: 10.5px; color: var(--muted); }
.se-ill { flex: none; width: 44px; height: 44px; border-radius: 50%; background: rgba(16, 185, 129, 0.14); color: var(--ok); display: grid; place-items: center; }
.se-ill svg { width: 23px; height: 23px; }
:root[data-theme="dark"] .se-ill { background: rgba(52, 211, 153, 0.14); color: #34d399; }
.se-text { display: grid; gap: 4px; min-width: 0; border-left: 1px solid rgba(16, 185, 129, 0.28); padding-left: 16px; margin-left: 14px; }
.se-text b { font-size: 14px; font-weight: 800; color: var(--ok); line-height: 1.25; }
.se-text p { margin: 0; font-size: 13px; color: var(--muted-strong); line-height: 1.4; }

/* Dark mode: 绿色文字在深色卡上保持可读 */
:root[data-theme="dark"] .sh-title:not(.sh-title--ink),
:root[data-theme="dark"] .sh-amount,
:root[data-theme="dark"] .st-amount,
:root[data-theme="dark"] .st-pct.st-pct,
:root[data-theme="dark"] .ss-txt b.ss-rank,
:root[data-theme="dark"] .sh-ask { color: #34d399; }
:root[data-theme="dark"] .sh-ic,
:root[data-theme="dark"] .st-edit,
:root[data-theme="dark"] .ss-ic { background: rgba(52, 211, 153, 0.14); color: #34d399; }
:root[data-theme="dark"] .sh-ask { border-color: rgba(52, 211, 153, 0.4); }
:root[data-theme="dark"] .st-bar-fill { background: linear-gradient(90deg, #34d399, #10b981); }

/* Bento grid */
.overview-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
.overview-panel {
  display: grid;
  gap: 10px;
  padding: 16px;
}
.overview-panel > span:first-child {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
/* 面板标题行:彩色方图标 + 标题(照参照图) */
/* 统一的区块标题:中等图标 tile + 大写深色标题 + 灰副标题(FOKUS / LAPORAN / HEMAT 同款) */
.panel-head { display: flex; align-items: center; gap: 11px; }
.panel-ic { flex: none; width: 40px; height: 40px; border-radius: 13px; display: grid; place-items: center; }
.panel-ic svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.panel-ic-focus { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.panel-ic-report { background: rgba(124, 58, 237, 0.14); color: #7c3aed; }
.panel-ic-save { background: rgba(16, 185, 129, 0.16); color: var(--ok); }
.panel-head-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.panel-head-title { font-size: 16.5px; font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ink-strong); line-height: 1.15; }
.panel-head-sub { font-size: 12px; font-weight: 500; color: var(--muted); text-transform: none; letter-spacing: normal; line-height: 1.2; }

.focus-list { display: grid; gap: 0; }
.focus-list > span {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 14px 2px;
  background: transparent;
  font-weight: 500;
  color: var(--ink);
}
.focus-list > span + span { border-top: 0; }
/* 焦点项前缀:橙色感叹号(无圆圈背景) */
/* 焦点列表项目符号:锥形竖条 + 圆点的感叹号造型(SVG mask),填语义红 */
.fl-dot {
  flex: none; width: 11px; height: 22px; align-self: flex-start; margin-top: 2px;
  background-color: var(--danger, #ef4444);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='8%202%208%2018.5'%3E%3Cpath%20d='M9.9%204C9.9%203.4%2010.4%203%2011%203L13%203C13.6%203%2014.1%203.4%2014.1%204L13.3%2013.4C13.25%2014%2012.7%2014.4%2012%2014.4%2011.3%2014.4%2010.75%2014%2010.7%2013.4Z'/%3E%3Ccircle%20cx='12'%20cy='18.6'%20r='1.85'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='8%202%208%2018.5'%3E%3Cpath%20d='M9.9%204C9.9%203.4%2010.4%203%2011%203L13%203C13.6%203%2014.1%203.4%2014.1%204L13.3%2013.4C13.25%2014%2012.7%2014.4%2012%2014.4%2011.3%2014.4%2010.75%2014%2010.7%2013.4Z'/%3E%3Ccircle%20cx='12'%20cy='18.6'%20r='1.85'/%3E%3C/svg%3E") center / contain no-repeat;
}
.fl-dot::before { content: none; }
.fl-dot::after { content: none; }
.fl-text { display: grid; gap: 2px; min-width: 0; }
.fl-text b { font-size: 13.5px; font-weight: 800; color: var(--ink); line-height: 1.3; }
.fl-text small { font-size: 12px; color: var(--muted); line-height: 1.35; }

.safe-extra,
.overview-extra {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.overview-extra > span {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  background: var(--soft);
  border-radius: var(--radius-sm);
}
/* 报告小卡:彩色方图标在左 + 标签/数值在右 */
/* 图2 排版:图标+标签在上,大数值独占整行(下)——大金额不再被右边裁掉 */
/* 侧排:小图标 + 标题在右(行1),数值在下方整行靠左(行2),上下留间距;
   标题缩字到能让最长单词 Penghasilan 单行放下,双词标签按空格换行(不硬断) */
/* 2×2 彩色 tile:图标在上、标签、数值,整体居中(参照图) */
.overview-extra .ov-rtile { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; padding: 16px 10px; }
.overview-extra .ov-rtile.ov-rtile--purple { background: rgba(124, 58, 237, 0.08); }
.overview-extra .ov-rtile.ov-rtile--green  { background: rgba(16, 185, 129, 0.09); }
.overview-extra .ov-rtile.ov-rtile--orange { background: rgba(255, 138, 61, 0.11); }
.overview-extra .ov-rtile.ov-rtile--blue   { background: rgba(56, 189, 248, 0.12); }
.ort-ic { flex: none; width: 44px; height: 44px; border-radius: 13px; display: grid; place-items: center; }
.ort-ic svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ort-purple { background: rgba(124, 58, 237, 0.13); color: #7c3aed; }
.ort-green { background: rgba(16, 185, 129, 0.14); color: #10a35e; }
.ort-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.ort-blue { background: rgba(56, 189, 248, 0.18); color: #2f9bf0; }
.overview-extra .ort-text { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; }
.overview-extra .ov-rtile .ort-text small { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.03em; line-height: 1.2; }
/* tile 标签彩色(配图标色);提升优先级压过 .overview-extra small 的灰色 */
.overview-extra .ort-lab-purple { color: #7c3aed; }
.overview-extra .ort-lab-green  { color: #10a35e; }
.overview-extra .ort-lab-orange { color: #ff6a2b; }
.overview-extra .ort-lab-blue   { color: #2f9bf0; }
.overview-extra .ov-rtile .ort-text b { font-size: clamp(12.5px, 3.6vw, 15px); font-weight: 800; letter-spacing: -0.02em; color: var(--ink-strong); overflow-wrap: anywhere; line-height: 1.12; font-feature-settings: "tnum", "lnum"; max-width: 100%; }

/* ── 8. Transactions view ─────────────────────────────────────── */
.cashflow-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 12px;
  border: 1.5px solid var(--brand-2);
  border-radius: var(--radius-pill);
  background: var(--brand-soft);
  color: var(--brand-2);
  font-size: 12px;
  font-weight: 700;
  box-shadow: 0 1px 6px var(--brand-soft);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform 0.1s var(--ease);
}
/* Trend-line icon (i18n replaces textContent, so draw it via ::before mask) */
.cashflow-chip::before {
  content: "";
  width: 17px; height: 17px;
  flex-shrink: 0;
  background: currentColor;
  -webkit-mask: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 17l5-5 4 3 7-8'/%3E%3Cpath d='M17 4h4v4'/%3E%3C/svg%3E");
  mask: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 17l5-5 4 3 7-8'/%3E%3Cpath d='M17 4h4v4'/%3E%3C/svg%3E");
}
.cashflow-chip:active { transform: scale(0.97); }
.cashflow-chip[aria-expanded="true"],
.cashflow-chip:hover {
  background: var(--brand-2);
  border-color: var(--brand-2);
  color: #fff;
}

.transaction-cashflow-card {
  display: grid;
  gap: 14px;
  padding: 18px;
  margin-bottom: 4px;
}
.transaction-tools-row {
  display: grid;
  gap: 10px;
  margin-top: 4px;
}

.filter-tabs,
.range-tabs {
  display: inline-flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  gap: 4px;
  padding: 4px;
  border: 0;
  background: var(--card);
  box-shadow: var(--shadow-sm);
  border-radius: var(--radius-pill);
}
.filter-tabs::-webkit-scrollbar,
.range-tabs::-webkit-scrollbar { display: none; }
.filter-tabs button,
.range-tabs button {
  flex: 0 0 auto;
  min-height: 34px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted-strong);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
  white-space: nowrap;
}
.filter-tabs button.active,
.range-tabs button.active {
  background: var(--brand-2);
  color: #fff;
  box-shadow: none;
}
:root[data-theme="dark"] .filter-tabs button.active,
:root[data-theme="dark"] .range-tabs button.active {
  background: var(--brand-grad); /* 暗色 brand-2 是浅橙会发白 → 用鲜艳橙渐变,与勾选/其它 tab 一致 */
}

/* ── Tab unification ──────────────────────────────────────────────────────
   Every segmented control (money/bills, reimburse, referral) uses the same
   active pill as the transactions (流水) filter-tabs — dark "ink" in light mode,
   brand gradient in dark mode — so tab colors are consistent across screens.
   These come after the per-control rules above, so they win on source order. */
.money-tabs button.active,
.reimburse-tabs button.active,
.referral-tabs button.active {
  background: var(--ink);
  color: #fff;
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.18);
}
:root[data-theme="dark"] .money-tabs button.active,
:root[data-theme="dark"] .reimburse-tabs button.active,
:root[data-theme="dark"] .referral-tabs button.active {
  background: var(--brand-grad);
  color: #fff;
}

/* Segmented control: fixed-column grid that fills width.
   Number of columns is determined by the tab's specific class. */
.filter-tabs.transaction-type-tabs,
[role="tablist"].filter-tabs.transaction-type-tabs {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}
.filter-tabs.account-filter-tabs,
[role="tablist"].filter-tabs.account-filter-tabs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.filter-tabs.transaction-type-tabs button,
.filter-tabs.account-filter-tabs button { width: 100%; }
/* Mutasi 顶部分段(Keluar/Masuk)与资金/账单 money-tabs 同高同字号 */
.filter-tabs.transaction-type-tabs button,
[role="tablist"].filter-tabs.transaction-type-tabs button {
  min-height: 46px;
  font-size: 15px;
  font-weight: 700;
}
/* 账户筛选(Bank/Dompet Digital/Lainnya)缩小,与报销 Menunggu/Riwayat 段控一致 */
.filter-tabs.account-filter-tabs button,
[role="tablist"].filter-tabs.account-filter-tabs button {
  min-height: 36px;
  font-size: 13px;
  font-weight: 700;
}

/* Default fallback for any other tablist filter-tabs (2 columns) */
[role="tablist"].filter-tabs:not(.transaction-type-tabs):not(.account-filter-tabs) {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}
[role="tablist"].filter-tabs:not(.transaction-type-tabs):not(.account-filter-tabs) button {
  width: 100%;
}

.transaction-ranges { width: 100%; }

.custom-date-range {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 8px;
  padding: 10px;
  border-radius: var(--radius-sm);
  background: var(--soft);
}
.custom-date-range label {
  display: grid;
  gap: 4px;
  font-size: 11px;
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.custom-date-range input[type="date"] {
  height: 36px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
}
.custom-date-range button {
  height: 36px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--brand-grad);
  color: #fff;
  font-weight: 700;
  align-self: end;
}

.transaction-search {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  margin: 4px 0;
  position: sticky;     /* 跟随滚动吸顶 */
  top: 0;
  z-index: 15;
}
.transaction-search input {
  height: 42px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.7);   /* 玻璃毛玻璃 */
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  backdrop-filter: blur(18px) saturate(160%);
  box-shadow: 0 8px 22px -12px rgba(15, 23, 42, 0.3);
  color: var(--ink);
  font-size: 14px;
  transition: box-shadow var(--dur) var(--ease);
}
:root[data-theme="dark"] .transaction-search input { background: rgba(26, 28, 34, 0.62); }
/* 吸顶后:导出键不跟随(隐藏),搜索框拉伸占满整行 */
.transaction-search.is-stuck { grid-template-columns: minmax(0, 1fr); }
.transaction-search.is-stuck .tx-export-btn { display: none; }
.transaction-search input::placeholder { color: var(--muted); }
.transaction-search input:focus { outline: none; border: 0; box-shadow: 0 8px 22px -12px rgba(15, 23, 42, 0.3); }
.transaction-search input { padding-right: 40px; } /* 给右侧 X 留位,文字不压到清除键 */
/* 搜索框内的快速清除 X:有字才显示(JS 控 hidden),盖在输入框右侧、导出键左边 */
.transaction-search .tx-search-clear { position: absolute; right: 60px; top: 50%; transform: translateY(-50%); width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border: 0 !important; background: transparent !important; color: var(--muted); cursor: pointer; padding: 0 !important; z-index: 3; box-shadow: none; }
.tx-search-clear svg { width: 16px; height: 16px; }
.transaction-search .tx-search-clear[hidden] { display: none; }
.transaction-search .tx-search-clear:active { transform: translateY(-50%) scale(0.9); }
.transaction-search.is-stuck .tx-search-clear { right: 14px; } /* 吸顶导出键隐藏 → X 靠右 */
.transaction-search button {
  height: 42px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
}
/* Ekspor 改为仅图标的圆形按钮 */
.transaction-search .tx-export-btn {
  width: 42px; height: 42px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.7);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  backdrop-filter: blur(18px) saturate(160%);
  color: var(--ink);
  cursor: pointer;
}
:root[data-theme="dark"] .transaction-search .tx-export-btn { background: rgba(26, 28, 34, 0.62); }
.transaction-search .tx-export-btn svg { width: 21px; height: 21px; }
.transaction-search .tx-export-btn:active { transform: scale(0.95); }

.transaction-list {
  display: grid;
  gap: 8px;
}

/* Pre-accounting (预记账): pending income/bills awaiting confirmation. */
.pending-ledger {
  display: grid;
  gap: 8px;
  margin-bottom: 12px;
  padding: 12px;
  border: 1px solid var(--brand-ring, var(--line));
  border-radius: var(--radius-md);
  background: var(--brand-soft);
}
.pending-ledger[hidden] { display: none; }
.pending-head { font-size: 12px; font-weight: 800; color: var(--brand); text-transform: uppercase; letter-spacing: 0.04em; }
.pending-toggle { width: 100%; margin-top: 2px; border: 0; background: transparent; color: var(--brand); font-size: 12.5px; font-weight: 700; padding: 6px; cursor: pointer; border-radius: 8px; }
.pending-toggle:active { background: var(--brand-soft); }
.pending-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--card);
  border: 1px solid var(--line);
}
/* 待确认卡:左滑出现删除(去掉行内 ✕);✓ 仍内联 */
.pending-item.swipe-row { display: block; padding: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.pending-item.swipe-row > .swipe-content {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--card);
}
.pending-info { min-width: 0; display: grid; gap: 2px; }
.pending-name { font-size: 14px; font-weight: 700; color: var(--ink-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pending-meta { font-size: 11px; color: var(--muted); }
.pending-amt { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pending-amt.in { color: var(--success, #16a34a); }
.pending-amt.out { color: var(--danger); }
/* 待确认按钮:橙色 ✓ 圆 + 灰色 ✕ 圆(图标式,文字隐藏供无障碍读) */
.pending-confirm,
.pending-dismiss {
  flex: 0 0 auto;
  width: 38px; height: 38px; padding: 0;
  border: 0; border-radius: 50%;
  font-size: 0; line-height: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.pending-confirm { background: var(--brand-grad); color: #fff; }
.pending-dismiss { background: var(--soft); color: var(--muted); }
.pending-confirm::before,
.pending-dismiss::before {
  content: ""; background: currentColor;
  -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat;
}
.pending-confirm::before {
  width: 18px; height: 18px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
}
.pending-dismiss::before {
  width: 15px; height: 15px;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E");
}

.transaction-item,
.paylater-item,
.fixed-cost-item {
  position: relative;
  display: grid;
  gap: 10px;
}
/* Whole-card tap target (e.g. expected-income / account rows open the editor). */
.fixed-cost-item.is-tappable,
.account-item.is-tappable { cursor: pointer; }
.app-header .brand.is-tappable { cursor: pointer; }
.fixed-cost-item.is-tappable:active,
.account-item.is-tappable:active { background: var(--hover); border-radius: var(--radius-sm); }
.swipe-row > .swipe-content > .row,
.fixed-cost-item:not(.swipe-row) > .row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}
.swipe-row > .swipe-content > .row > div,
.fixed-cost-item:not(.swipe-row) > .row > div {
  min-width: 0;
  display: grid;
  gap: 2px;
}

.tx-name,
.paylater-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tx-meta,
.paylater-meta {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 流水卡:日期单独一行放最下方(分类·来源在中间) */
.tx-date {
  font-size: 11.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 3px;
}

.tx-code {
  opacity: 0.55;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.transaction-item .swipe-content { -webkit-user-select: none; user-select: none; }

/* 原生 App 观感:长按 UI(按钮/标签/chip/菜单)不弹「选择/复制」文字菜单。
   仅原生壳(.native-app)生效,网页版保留正常选择。输入框 + 聊天正文仍可选(复制 AI 回复)。 */
body.native-app { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
body.native-app input,
body.native-app textarea,
body.native-app [contenteditable="true"],
body.native-app .bubble {
  -webkit-user-select: text; user-select: text; -webkit-touch-callout: default;
}

.tx-reimburse-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  vertical-align: middle;
  letter-spacing: 0.02em;
}
.tx-reimburse-badge.pending {
  background: rgba(255, 87, 34, 0.14);
  color: var(--brand);
}
.tx-reimburse-badge.received {
  background: rgba(16, 185, 129, 0.16);
  color: #059669;
}

/* Loan / fixed-cost lifecycle badge ("已还清" / "已结束") */
.lifecycle-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  vertical-align: middle;
  letter-spacing: 0.02em;
}
.lifecycle-badge.done {
  background: rgba(100, 116, 139, 0.18);
  color: var(--muted);
}
.paylater-item.is-done,
.fixed-cost-item.is-done {
  opacity: 0.55;
}
.paylater-item.is-done strong,
.fixed-cost-item.is-done strong {
  text-decoration: line-through;
  text-decoration-color: rgba(100, 116, 139, 0.5);
}
.paylater-item.is-done .paylater-progress span,
.fixed-cost-item.is-done .paylater-progress span {
  background: var(--muted);
}

.transaction-item.expense strong { color: var(--danger); }
.transaction-item.income strong { color: var(--ok); }
.transaction-item strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.015em;
}

/* category color rail on transaction items */
.transaction-item.swipe-row { position: relative; }
/* 流水卡内容圆角是 --radius-sm(12),而通用 .swipe-row 的 clip-path 用 --radius(16)→
   两条圆弧之间 4px 环带露出身后红删除键(圆角边缘一条橙红线)。裁切半径对齐内容即消除。 */
.transaction-item.swipe-row { clip-path: inset(0 round var(--radius-sm)); }
.transaction-item.swipe-row .swipe-delete { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
/* 结清键已挪到右侧、夹在删除键左边 → 不带圆角(圆角只归最外侧的删除键) */
.transaction-item.swipe-row .swipe-settle { border-radius: 0; }
.transaction-item.swipe-row > .swipe-content { padding-left: 18px; border-radius: var(--radius-sm); overflow: hidden; }
/* 左侧分类色条:全高 + 直角(随卡片圆角裁切),与账单统计卡同款、更有棱角 */
.transaction-item.swipe-row > .swipe-content::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 5px;
  border-radius: 0;
  background: var(--cat-other);
}
.transaction-item.cat-food > .swipe-content::before { background: var(--cat-food); }
.transaction-item.cat-transport > .swipe-content::before { background: var(--cat-transport); }
.transaction-item.cat-shopping > .swipe-content::before { background: var(--cat-shopping); }
.transaction-item.cat-fun > .swipe-content::before { background: var(--cat-fun); }
.transaction-item.cat-bills > .swipe-content::before { background: var(--cat-bills); }
.transaction-item.cat-saving > .swipe-content::before { background: var(--cat-saving); }
.transaction-item.cat-debt > .swipe-content::before { background: var(--cat-debt); }
.transaction-item.cat-income > .swipe-content::before { background: var(--cat-income); }
.transaction-item.cat-travel > .swipe-content::before { background: var(--cat-travel); }
.transaction-item.cat-medical > .swipe-content::before { background: var(--cat-medical); }
.transaction-item.cat-education > .swipe-content::before { background: var(--cat-education); }
.transaction-item.cat-entertainment > .swipe-content::before { background: var(--cat-entertainment); }
.transaction-item.cat-insurance > .swipe-content::before { background: var(--cat-insurance); }
.transaction-item.cat-maintenance > .swipe-content::before { background: var(--cat-maintenance); }
.transaction-item.cat-rent > .swipe-content::before { background: var(--cat-rent); }
.transaction-item.cat-telecom > .swipe-content::before { background: var(--cat-telecom); }
.transaction-item.cat-utilities > .swipe-content::before { background: var(--cat-utilities); }
.transaction-item.cat-tax > .swipe-content::before { background: var(--cat-tax); }
.transaction-item.cat-gift > .swipe-content::before { background: var(--cat-gift); }
.transaction-item.cat-pet > .swipe-content::before { background: var(--cat-pet); }
.transaction-item.cat-fitness > .swipe-content::before { background: var(--cat-fitness); }

.paylater-item strong,
.fixed-cost-item strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-strong);
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 12px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
}
/* PayLater 数据块:彩色圆标 + 标签/值(参照图1) */
.detail-tiles { border-top: 0; padding-top: 4px; gap: 10px; }
.detail-tiles .dt-item { display: flex; align-items: center; gap: 10px; padding: 11px 12px; border-radius: 14px; background: var(--soft); }
.detail-tiles .dt-ic { width: 36px; height: 36px; flex: none; border-radius: 50%; display: grid; place-items: center; }
.detail-tiles .dt-ic svg { width: 19px; height: 19px; }
.detail-tiles .dt-txt { display: grid; min-width: 0; }
.detail-tiles .dt-txt i { font-size: 11px; font-style: normal; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.detail-tiles .dt-txt b { font-size: 14px; font-weight: 800; color: var(--ink-strong, var(--ink)); font-feature-settings: "tnum", "lnum"; }
.dt-loan { background: rgba(249, 115, 22, 0.14); color: #f97316; }
.dt-due { background: rgba(99, 102, 241, 0.14); color: #6366f1; }
.dt-left { background: rgba(14, 165, 233, 0.14); color: #0ea5e9; }
.dt-payoff { background: rgba(34, 197, 94, 0.14); color: #22c55e; }
/* 预期收入卡片(仿贷款卡:头部+大金额+两 tile+进度) */
.income-card { position: relative; background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 16px; display: grid; gap: 12px; }
.income-card .income-amount { display: grid; gap: 3px; }
/* 金额字号对齐贷款卡 .card-amounts .ca-big(收入卡不在 .card-amounts 里,得单独给) */
.income-card .ca-big { font-size: clamp(22px, 7vw, 30px); font-weight: 900; line-height: 1.05; letter-spacing: -0.02em; font-feature-settings: "tnum", "lnum"; }
.income-card .ca-big.income-green { color: #10b981; }
:root[data-theme="dark"] .income-card .ca-big.income-green { color: #34d399; }
.income-card .ca-big .rp-prefix { color: var(--muted); opacity: 1; }
.income-card .paylater-progress.income > span { background: linear-gradient(90deg, #10b981, #34d399); }
.income-card .card-footer.income-foot { display: flex; justify-content: flex-end; }
/* 卡片头:名称/分类(左) + 到期"X天"日历徽章(右) */
.card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.card-head-main { min-width: 0; display: grid; gap: 2px; }
.card-daybadge { display: inline-flex; align-items: center; gap: 9px; flex: none; }
.card-daybadge .cdb-ic { width: 40px; height: 40px; border-radius: 50%; background: rgba(124, 58, 237, 0.12); color: #7c3aed; display: grid; place-items: center; }
.card-daybadge .cdb-ic svg { width: 20px; height: 20px; }
/* 逾期:文字 + 日历圈一起转红。紫色是「还早着呢」的中性色,逾期还用它就没有警示作用了 */
.card-daybadge.is-overdue b { color: var(--danger); }
.card-daybadge.is-overdue .cdb-ic { background: var(--danger-soft); color: var(--danger); }
.paylater-overdue { color: var(--danger); font-weight: 700; }
/* 有待确认 → 黄字挂在徽标下方。
   ⚠️ 用 position:absolute 脱离文档流,**不能**让它参与布局:参与的话卡片头会长高,
      左边的名字/类别块跟着被拉开一行空当,和没有待确认的卡片对不齐(用户实拍两次)。
      徽标本身仍是单行,卡头高度与其它卡片完全一致。 */
.card-daybadge.has-wait { position: relative; }
.cdb-wait {
  position: absolute; top: 100%; right: 0; margin-top: 3px;
  font-size: 12px; font-weight: 700; color: var(--warn, #ef9f27);
  white-space: nowrap; line-height: 1.1; pointer-events: none;
}
.paylater-wait { color: var(--warn, #ef9f27); font-weight: 700; }
/* 日历图标现在是按钮(点开待确认)—— 清掉 button 自带的边框/底色,保持原样式 */
button.cdb-ic { border: 0; padding: 0; font: inherit; cursor: pointer; }
button.cdb-ic:active { transform: scale(0.92); }
/* ⚠️ 「Menunggu konfirmasi」这一行把右侧整块撑到约 135px。card-head-main 默认
   min-width:auto,不给它 0 的话名字会被挤成「欠.」「L…」(上一版实拍过)。 */
.card-head-main { min-width: 0; }
.card-head-main .paylater-name { overflow: hidden; text-overflow: ellipsis; }
.bill-late { color: var(--danger); font-weight: 700; }
.card-daybadge.is-overdue .cdb-ic { background: var(--danger-soft); color: var(--danger); }
.card-daybadge b { font-size: 16px; font-weight: 800; color: var(--ink-strong, var(--ink)); white-space: nowrap; }
.card-daybadge.warn .cdb-ic { background: var(--warn-soft); color: var(--warn); }
.card-daybadge.danger .cdb-ic { background: var(--danger-soft); color: var(--danger); }
/* 顶部两个大金额(每月 / 总额)整行堆叠 + 分隔线 */
.card-amounts { margin-top: 14px; }
.card-amounts .ca-row { display: grid; gap: 3px; }
.card-amounts .ca-label, .income-card .income-amount .ca-label { font-size: 13px; color: var(--muted); }
.card-amounts .ca-big { font-size: clamp(22px, 7vw, 30px); font-weight: 900; line-height: 1.05; letter-spacing: -0.02em; color: var(--brand-2); font-feature-settings: "tnum", "lnum"; }
:root[data-theme="dark"] .card-amounts .ca-big { color: #ff6a3d; }
.card-amounts .ca-sub { font-size: 19px; font-weight: 800; line-height: 1.1; letter-spacing: -0.015em; color: var(--ink-strong, var(--ink)); font-feature-settings: "tnum", "lnum"; }
.card-amounts .ca-big .rp-prefix, .card-amounts .ca-sub .rp-prefix { color: var(--muted); opacity: 1; }
.card-amounts .ca-divider { height: 1px; background: var(--line); margin: 12px 0; }
.detail-grid > span {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  font-size: 12px;
  color: var(--muted);
}
.detail-grid b {
  font-feature-settings: "tnum", "lnum";
  font-weight: 700;
  font-size: 12px;
  color: var(--ink-strong);
}

.paylater-progress {
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--line); /* 更明显的灰色底框(原 --soft 太浅几乎看不见) */
  overflow: hidden;
}
.paylater-progress > span {
  display: block;
  height: 100%;
  background: var(--brand-grad);
  transition: width 380ms var(--ease);
}
.paylater-progress.warn > span { background: var(--warn-grad); }
.paylater-progress.danger > span { background: var(--danger-grad); }
/* Progress bar + percentage label on one row, framed in a soft box (图1). */
.progress-row {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px 14px;
  background: var(--card, #fff);
}
.progress-row .paylater-progress { flex: 1; }
.progress-pct {
  font-feature-settings: "tnum", "lnum";
  font-size: 11px;
  font-weight: 700;
  color: var(--muted-strong);
  min-width: 34px;
  text-align: right;
}

/* Card footer: snooze ("remind next month") on the left, Edit on the right. */
.card-footer {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.card-snooze {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--muted-strong);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.card-snooze svg { width: 17px; height: 17px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.card-snooze.is-snoozed {
  background: var(--brand-soft);
  color: var(--brand);
  border-color: var(--brand);
}
.card-action {
  align-self: start;
  justify-self: start;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
}
.card-action:hover { background: var(--hover); }
/* "···" 更多按钮(贷款/固定费用卡):圆形点点,替代 Edit 文字 */
.card-action--more { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; padding: 0 8px; border: 0; background: transparent; font-size: 24px; line-height: 1; letter-spacing: 1px; color: var(--muted-strong); padding-bottom: 8px; }
.card-action--more:hover { background: transparent; }
/* Chevron affordance on whole-card-tappable rows (income / account / reimburse).
   Replaces the old "Edit" pill now that the entire card opens the editor. */
.card-chevron {
  align-self: center;
  justify-self: end;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  font-weight: 400;
  flex: 0 0 auto;
}
.save-action {
  border: 0;
  background: var(--ok-soft);
  color: var(--ok);
}

/* swipe-to-delete */
.swipe-row {
  position: relative;
  overflow: hidden;
  padding: 0;
  border: 0; /* 无边框,靠 box-shadow 区分(全 App 卡片统一风格) */
  /* 建立独立层叠上下文,iOS Safari 才会把带 z-index 的子元素(滑出按钮)
     裁进圆角内 —— 否则红色删除键会从右下圆角"漏"出一条橙红边。 */
  isolation: isolate;
  /* isolation 在某些 iOS 版本仍会漏出一条红/橙边 → 用 clip-path 硬裁进圆角,彻底堵住。 */
  clip-path: inset(0 round var(--radius));
}
/* 滑出按钮外侧圆角跟卡片对齐,任何渗漏都顺着卡片轮廓而非露出方角 */
.swipe-row .swipe-delete { border-radius: 0 var(--radius) var(--radius) 0; }
.swipe-row .swipe-settle { border-radius: 0; }   /* 同上:中间的按钮不带圆角 */
/* 滑开后内容块的**右侧**圆角抹平 —— 不抹的话卡片右缘和绿色按钮之间留一道圆角缺口,
   两块颜色对不齐(用户实拍)。静止态仍保留圆角,那是用来盖住身后红键防漏边的。 */
.swipe-row.dragging > .swipe-content,
.swipe-row.open > .swipe-content,
.swipe-row.open-settle > .swipe-content {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
/* 静止时彻底隐藏红/绿滑出按钮 —— 身后没有任何红色像素,圆角处的 clip-path 抗锯齿
   接缝就无从"漏红"(反复用 clip-path/isolation 都堵不干净的橙红边,根因即此)。
   拖拽(.dragging)或已展开(.open/.open-settle)时才亮出,此刻内容正好滑开露出按钮,无缝衔接。 */
.swipe-row .swipe-delete, .swipe-row .swipe-settle { opacity: 0; }
.swipe-row.dragging .swipe-delete, .swipe-row.open .swipe-delete,
.swipe-row.dragging .swipe-settle, .swipe-row.open-settle .swipe-settle { opacity: 1; }
.swipe-row > .swipe-content {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 10px;
  padding: 14px;
  background: var(--card);
  border-radius: var(--radius); /* 白底内容自带圆角,静止时完全盖住身后红删除键,右侧圆角不再漏红边 */
  /* 松手回弹:带一点点过冲的弹簧感(用户要的「流水/反弹」)。
     ⚠️ 过冲幅度要克制 —— 底部导航橙条那次用 y1=1.32,位移全堆在头几帧,
     反而像瞬移。这里滑动距离只有一百多 px,1.12 已经够弹。 */
  transition: transform 260ms cubic-bezier(.22, 1.12, .36, 1);
  touch-action: pan-y; /* 允许纵向滚动,横向留给滑动删除 */
  will-change: transform;
}
/* 拖拽中关掉过渡 → 内容实时跟手指,无 220ms 延迟(松手移除本类,吸附回带动画) */
.swipe-row.dragging > .swipe-content { transition: none; }
.swipe-row .swipe-delete {
  position: absolute;
  inset: 0 0 0 auto;
  z-index: 0;
  display: grid;
  place-items: center;
  min-width: 86px;
  padding: 0 18px;
  border: 0;
  background: var(--danger);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* 展开位移 = 露出的按钮总宽。--swipe-w 由 JS 按「这一行有几个按钮」写入
   (86 = 只有删除;172 = 结清+删除)。
   ⚠️ 不用 :has(.swipe-settle) 来判断 —— Safari 16.4 才支持,而 Capacitor 6
   最低支到 iOS 13,老机器上会整条失效。 */
.swipe-row.open > .swipe-content { transform: translateX(calc(-1 * var(--swipe-w, 86px))); }
/* 「提前结束/还清」(绿色)。改成和删除键一起收在**右侧**,紧挨它左边 ——
   微信那种「左滑一次,几个动作并排出来」。
   原来是左滑露删除(右)、右滑露结清(左),分在两个方向,用户得记两个手势,
   而且右滑和「边缘返回」手势方向一致,很容易误触。 */
.swipe-row .swipe-settle {
  position: absolute;
  inset: 0 86px 0 auto;   /* 86 = 删除键宽度,正好让它贴在删除键左边 */
  z-index: 0;
  display: grid;
  place-items: center;
  min-width: 86px;
  padding: 0 18px;
  border: 0;
  background: var(--green, #16a34a);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* 结清键现在夹在中间,不该带圆角(圆角只留给最外侧的删除键) */
.swipe-row .swipe-settle { border-radius: 0; }
/* 两个按钮都在右侧后,展开时它们一起亮起 */
.swipe-row.dragging .swipe-settle, .swipe-row.open .swipe-settle { opacity: 1; }
/* 滑出按钮文字(MARK PAID / DELETE)太挤时换两行居中,不再单行被裁 */
.swipe-row .swipe-settle, .swipe-row .swipe-delete { white-space: normal; text-align: center; line-height: 1.12; letter-spacing: 0.02em; }
/* Chat/AI 设置页 + Backup&Reset 页:去掉各卡片主标题下的灰色副标题(用户要求) */
.chat-ai-panel .settings-card-head p { display: none; }
#profileBackup .section-heading.compact p { display: none; }
#autoUpdateRow small { display: none; }

.empty-copy {
  padding: 22px;
  text-align: center;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--soft);
  color: var(--muted);
  font-size: 13px;
}

/* ── 9. Cashflow chart ────────────────────────────────────────── */
.cashflow-breakdown {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.cashflow-dimension {
  display: grid;
  gap: 4px;
  padding: 12px;
  background: var(--soft);
  border-radius: var(--radius-sm);
}
.cashflow-dimension > span {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.cashflow-dimension > strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 18px;
  font-weight: 700;
  color: var(--ink-strong);
}
.cashflow-dimension > small { font-size: 11px; color: var(--muted); }
.cashflow-dimension > strong.cashflow-in { color: var(--success, #16a34a); }
.cashflow-dimension > strong.cashflow-out { color: var(--danger); }

.cashflow-chart {
  display: grid;
  align-items: stretch;
  gap: 4px;
  height: 188px;
  padding: 10px 8px 8px;
  background: var(--soft);
  border-radius: var(--radius-sm);
  overflow-x: auto;
  scrollbar-width: thin;
}
.cashflow-day {
  display: grid;
  grid-template-rows: 1fr auto auto;
  justify-items: center;
  align-items: end;
  gap: 4px;
  min-width: 46px;
  height: 100%;
}
.cashflow-bar {
  width: 70%;
  align-self: end;
  border-radius: 6px 6px 2px 2px;
  background: var(--brand-grad);
  transition: height 380ms var(--ease);
}
.cashflow-bar.warn { background: linear-gradient(180deg, #f59e0b, #d97706); }
.cashflow-bar.danger { background: linear-gradient(180deg, #ef4444, #b91c1c); }
.cashflow-label {
  font-feature-settings: "tnum", "lnum";
  font-size: 10px;
  color: var(--muted);
  white-space: nowrap;
}
.cashflow-value {
  font-feature-settings: "tnum", "lnum";
  font-size: 9px;
  color: var(--ink);
  white-space: nowrap;
}

/* ── Cashflow redesign (hero + tiles + svg chart + daily list + footer) ───── */
#profileCashflow.active { display: grid; gap: 14px; }

/* Hero card */
.cf-hero {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 18px;
  border-radius: var(--radius);
  background: var(--ok-soft);
  box-shadow: var(--shadow-sm);
}
.cf-hero--warn { background: rgba(245, 158, 11, 0.14); }
.cf-hero--danger { background: var(--danger-soft); }
.cf-hero-text { display: grid; gap: 6px; min-width: 0; }
.cf-hero-label { font-size: 12.5px; font-weight: 700; color: var(--muted-strong); }
.cf-hero-amount {
  font-feature-settings: "tnum", "lnum";
  font-size: clamp(20px, 6.5vw, 30px); font-weight: 800; line-height: 1.05; color: var(--ink-strong);
  white-space: nowrap; min-width: 0;
}
.cf-hero-badge {
  display: inline-flex; align-items: center; gap: 6px; align-self: start;
  padding: 5px 11px; border-radius: var(--radius-pill);
  font-size: 12px; font-weight: 700;
}
.cf-hero-badge svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.cf-hero-badge--ok { background: rgba(16, 185, 129, 0.18); color: var(--ok); }
.cf-hero-badge--warn { background: rgba(245, 158, 11, 0.2); color: #b45309; }
.cf-hero-badge--danger { background: rgba(239, 68, 68, 0.18); color: var(--danger); }
.cf-hero-art { width: 76px; height: 76px; flex: 0 0 auto; }
.cf-hero-art .cf-shield { fill: #10a35e; }
.cf-hero--warn .cf-hero-art .cf-shield { fill: #f59e0b; }
.cf-hero--danger .cf-hero-art .cf-shield { fill: #ef4444; }
.cf-hero-art .cf-sparkle { fill: #fbbf24; }

/* Stat tiles 2×2 */
.cf-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cf-stat {
  display: grid; gap: 3px;
  padding: 14px 16px; border-radius: var(--radius-sm);
  background: var(--card); box-shadow: var(--shadow-sm);
  min-width: 0;
}
.cf-stat-body { display: grid; gap: 2px; min-width: 0; }
.cf-stat-label { font-size: 12px; font-weight: 700; color: var(--muted-strong); }
.cf-stat-value { font-feature-settings: "tnum", "lnum"; font-size: 16px; font-weight: 800; color: var(--ink-strong); white-space: nowrap; }
.cf-stat-value.cf-val-in { color: var(--ok); }
.cf-stat-value.cf-val-out { color: var(--danger); }
.cf-stat-sub { font-size: 11px; color: var(--muted); }

/* Chart card */
.cf-chart-card { padding: 14px; border-radius: var(--radius); background: var(--card); box-shadow: var(--shadow-sm); display: grid; gap: 10px; }
.cf-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cf-chart-head strong { font-size: 14px; color: var(--ink-strong); }
.cf-legend { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.cf-legend-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--brand-2); }
.cf-chart-scroll { overflow-x: auto; scrollbar-width: thin; -webkit-overflow-scrolling: touch; }
.cf-chart-svg { display: block; }
.cf-chart-svg .cf-pt { fill: var(--brand-2); stroke: var(--card); stroke-width: 2; }
.cf-chart-svg .cf-pt-val { font-size: 9.5px; font-weight: 800; fill: var(--ink-strong); text-anchor: middle; font-feature-settings: "tnum","lnum"; }
.cf-chart-svg .cf-x-date { font-size: 9.5px; fill: var(--muted-strong); text-anchor: middle; font-feature-settings: "tnum","lnum"; }
.cf-chart-svg .cf-x-day { font-size: 9px; fill: var(--muted); text-anchor: middle; }
.cf-chart-hint { font-size: 11px; color: var(--muted); text-align: center; margin: 0; }

/* Daily list */
.cf-daily-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 2px; }
.cf-daily-head strong { font-size: 15px; color: var(--ink-strong); }
.cf-daily-more { border: 0; background: transparent; color: var(--brand-2); font-size: 12.5px; font-weight: 700; cursor: pointer; padding: 4px 2px; }
.cf-daily { display: grid; gap: 8px; }
.cf-day-row {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr) auto 14px;
  align-items: center; gap: 10px;
  padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--card); box-shadow: var(--shadow-sm);
}
.cf-day-row--today { background: var(--ok-soft); }
.cf-day-when { display: grid; gap: 1px; min-width: 56px; }
.cf-day-when b { font-size: 13px; font-weight: 800; color: var(--ink-strong); }
.cf-day-when small { font-size: 11px; color: var(--muted); }
.cf-day-flow { display: grid; gap: 1px; font-feature-settings: "tnum","lnum"; font-size: 12px; }
.cf-flow-in { color: var(--ok); font-weight: 700; }
.cf-flow-out { color: var(--danger); font-weight: 700; }
.cf-day-net { display: grid; justify-items: end; gap: 1px; text-align: right; }
.cf-day-net-label { font-size: 10px; color: var(--muted); }
.cf-day-net strong { font-feature-settings: "tnum","lnum"; font-size: 13px; font-weight: 800; color: var(--ink-strong); white-space: nowrap; }
.cf-pill { margin-top: 2px; padding: 2px 8px; border-radius: var(--radius-pill); font-size: 10px; font-weight: 700; }
.cf-pill--ok { background: rgba(16, 185, 129, 0.16); color: var(--ok); }
.cf-pill--warn { background: rgba(245, 158, 11, 0.18); color: #b45309; }
.cf-pill--danger { background: rgba(239, 68, 68, 0.16); color: var(--danger); }
.cf-chev { color: var(--muted); font-size: 18px; line-height: 1; }
.cf-day-row--tap { cursor: pointer; transition: background var(--dur) var(--ease); }
.cf-day-row--tap:active { background: var(--hover); }

/* Cashflow 明细弹窗 */
.cfd-card { width: 380px; max-width: 92vw; max-height: 86vh; overflow-y: auto; }
.cfd-heading { gap: 8px; }
.cfd-net-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cfd-net-label { font-size: 12px; color: var(--muted); }
.cfd-net-row strong { font-size: 18px; font-weight: 800; font-feature-settings: "tnum","lnum"; color: var(--ink-strong); }
.cfd-section { margin-top: 14px; }
.cfd-sec-head { display: flex; align-items: baseline; justify-content: space-between; font-size: 12px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px; }
.cfd-sec-in { color: var(--ok); font-feature-settings: "tnum","lnum"; }
.cfd-sec-out { color: var(--danger); font-feature-settings: "tnum","lnum"; }
.cfd-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.cfd-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 12px; background: var(--soft); border-radius: var(--radius-sm); font-size: 13.5px; }
.cfd-name { color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cfd-amt { font-weight: 700; font-feature-settings: "tnum","lnum"; white-space: nowrap; color: var(--ink-strong); }
.cfd-empty { justify-content: center; color: var(--muted); background: transparent; font-style: italic; }

/* Footer cards */
.cf-footer { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cf-foot-card {
  display: grid; grid-template-columns: auto 1fr; align-items: start; gap: 10px;
  padding: 14px; border-radius: var(--radius-sm);
  background: var(--card); box-shadow: var(--shadow-sm);
}
.cf-foot-card--insight { grid-template-columns: auto 1fr auto; }
.cf-foot-ic { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto; }
.cf-foot-ic svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.cf-foot-ic--ok { background: rgba(16, 185, 129, 0.14); color: var(--ok); }
.cf-foot-ic--warn { background: rgba(245, 158, 11, 0.16); color: #b45309; }
.cf-foot-ic--danger { background: rgba(239, 68, 68, 0.14); color: var(--danger); }
.cf-foot-ic--insight { background: rgba(250, 204, 21, 0.2); color: #ca8a04; }
.cf-foot-body { display: grid; gap: 3px; min-width: 0; }
.cf-foot-body strong { font-size: 13px; color: var(--ink-strong); }
.cf-foot-body span { font-size: 11.5px; color: var(--muted-strong); line-height: 1.35; }
@media (max-width: 380px) {
  .cf-footer { grid-template-columns: 1fr; }
}

.radar-card {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px;
  align-items: center;
  padding: 14px 16px;
}
.radar-card .eyebrow { color: var(--muted); }
.radar-risk { display: inline-flex; align-items: center; gap: 8px; }
/* 现金流卡片底部"收起"按钮(Keluar 上方),点了收起整个 cashflow 卡片 */
/* 收起:极简箭头,无框无底色 */
.cashflow-collapse { display: flex; align-items: center; justify-content: center; width: 100%; margin-top: 2px; height: 30px; border: 0; background: transparent; color: var(--muted); cursor: pointer; }
.cashflow-collapse svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.cashflow-collapse:hover { color: var(--ink); }
#riskBadge,
.risk-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 14px;
  border-radius: var(--radius-pill);
  background: var(--info-soft);
  color: var(--info);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.02em;
  margin-top: 4px;
  border: 1px solid currentColor;
}
.risk-value::before,
#riskBadge::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}
.risk-value.safe { background: var(--ok-soft); color: var(--ok); border-color: rgba(5, 150, 105, 0.4); }
.risk-value.warning { background: var(--warn-soft); color: var(--warn); border-color: rgba(217, 119, 6, 0.4); }
.risk-value.danger {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: rgba(220, 38, 38, 0.4);
  animation: dangerPulse 1.6s ease-in-out infinite;
}
@keyframes dangerPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.4); }
  50% { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0); }
}
.radar-card p { font-size: 12px; color: var(--muted); }

/* ── 10. Bills view (split workspace) ─────────────────────────── */
/* Default: mobile drill pattern (one column, menu OR content) */
.split-workspace {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  align-items: stretch;
  position: relative;
}
.side-menu {
  display: grid;
  align-content: start;
  gap: 0;
  padding: 0;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.side-menu button {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 14px;
  align-items: center;
  gap: 10px;
  padding: 18px 14px 18px 16px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  text-align: left;
  letter-spacing: -0.005em;
  transition: background var(--dur) var(--ease);
}
.side-menu button + button { border-radius: 0; }
/* The first VISIBLE row must not show a divider: hidden leading buttons (the
   desktop nav, or the money/bills section toggled off) would otherwise leave an
   orphan top line that doubles with the card border ("2 lines at the top").
   JS (normalizeSideMenuDividers) tags the first visible button. */
.side-menu button.is-first-visible { border-top: 0; }
/* Selected/hover highlight: a rounded pill inset evenly inside the row (4px all
   around), consistent on every row — not a flush, square, edge-touching block.
   The button is its own stacking context (z-index:0) and the ::before sits at
   z-index:-1, so it paints above the transparent button bg but BEHIND the label
   (works even for buttons whose label is a bare text node). */
.side-menu button { z-index: 0; }
.side-menu button::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 0;
  background: transparent;
  transition: background var(--dur) var(--ease);
  z-index: -1;
}
/* 按下瞬间给反馈;但不保留「选中」灰高亮 → 手机回到列表时不高亮任何行
   (桌面两栏的选中态由 6046 的 brand-soft 单独负责) */
.side-menu button:active::before { background: var(--soft); }
/* 只在有指针悬停的设备(鼠标)给 hover,避免触屏点完灰色「卡住」 */
@media (hover: hover) {
  .side-menu button:hover::before { background: var(--soft); }
}
.side-menu button > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.side-menu button strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--muted-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 160px;
}
.side-menu button::after {
  content: "";
  width: 8px;
  height: 8px;
  border-right: 1.5px solid var(--muted);
  border-top: 1.5px solid var(--muted);
  transform: rotate(45deg);
  /* Always sit in column 3 of the grid so items without a strong value
     (汇总报表 / 设置) still align with items that have one. */
  grid-column: 3;
  justify-self: end;
}
/* 手机端抽屉导航:点过的行会留 .active,别把它的值染橙(桌面≥760px 分栏另有规则高亮) */
.side-menu button.active strong { color: var(--muted-strong); }
/* Subscription row: AI quota pill sits left of the plan name (both in grid col 2). */
.side-menu button > span.menu-value-group {
  grid-column: 2;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  overflow: visible;
}
.ai-gift-ic { width: 12px; height: 12px; display: inline-block; vertical-align: -1.5px; }
.menu-quota-pill {
  font-feature-settings: "tnum", "lnum";
  font-size: 11px;
  font-weight: 700;
  color: var(--brand-2);
  background: var(--brand-soft);
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}

/* Mobile drill: menu visible by default, content panels hidden until drill-open */
.side-content {
  display: grid;
  gap: 12px;
  min-width: 0;
  align-content: start;
}
/* 面板切换动画(微信那种推入感)。
   以前是 display:none → grid 硬切,一帧到位,所以显得「不流畅」——
   display 本身不能过渡,只能靠 animation 在切到 .active 的那一帧跑一次。
   方向:进入下级页从右侧推入;返回上级从左侧推回(body.panel-back 由返回逻辑打上)。
   位移只用 14%,不用整屏 —— 整屏推在中低端机上掉帧,而印尼多的是中低端机。 */
/* translateZ(0) 一起写进关键帧:某些 WebKit 版本只有 transform 里出现 3D 变换
   才真正走 GPU 合成,纯 2D 的 translateX 仍可能每帧重绘。
   起始不透明度用 .35 而不是 0 —— 全透明起步会让人觉得「闪了一下才出来」,
   带点底色的推入更接近微信那种连续感。 */
@keyframes panel-push-in {
  from { transform: translate3d(14%, 0, 0); opacity: .35; }
  to   { transform: translate3d(0, 0, 0); opacity: 1; }
}
@keyframes panel-pop-in {
  from { transform: translate3d(-14%, 0, 0); opacity: .35; }
  to   { transform: translate3d(0, 0, 0); opacity: 1; }
}
.content-panel { display: none; gap: 12px; }
.content-panel.active {
  display: grid;
  /* 单列必须显式 minmax(0,1fr):默认隐式列 = auto = max-content,任一子元素(如长文本)
     会把整列撑到比屏宽 → 面板 overflow-x:hidden 裁掉右侧(Z Fold 邀请页整片被切的根因)。 */
  grid-template-columns: minmax(0, 1fr);
  grid-auto-rows: min-content;
  align-content: start;
}

/* 面板导航动画 —— **一次性 class,不是常驻动画**。
   为什么不能写成 `.content-panel.active { animation: … }`:iOS WebKit 会在原生
   <select> 弹层关闭时重播常驻在元素上的入场动画,整屏鬼影滑动(见下方
   body.native-app 那条,当年就是为此把动画全关了 —— 代价是原生端切面板毫无过渡感)。
   改成 showPanel 打 class、animationend 摘掉,元素上就不存在可被重播的动画,
   于是原生端也能有过渡。位移只用 14%,不用整屏 —— 印尼多中低端机,整屏推会掉帧。 */
/* will-change + translateZ:把面板提升成独立合成层再动。
   卡顿的不是动画本身 —— 是面板刚从 display:none 变成 grid,浏览器要在**同一帧**里
   把整个面板布局 + 绘制完,然后才轮到合成。中低端机这一帧就丢了,而这条缓动曲线
   把大部分位移放在最前面,丢掉的正好是最显眼的几帧。
   提升成图层后,后续每帧只是搬运一张已经画好的纹理,不再重绘。
   ⚠️ will-change 只挂在动画 class 上,动画结束随 class 一起摘掉 ——
   常驻 will-change 会一直占着显存,页面一多就适得其反。 */
.content-panel.panel-anim-in,
.content-panel.panel-anim-back {
  will-change: transform, opacity;
  backface-visibility: hidden;
}
.content-panel.panel-anim-in { animation: panel-push-in 0.26s cubic-bezier(0.22, 0.61, 0.36, 1); }
.content-panel.panel-anim-back { animation: panel-pop-in 0.26s cubic-bezier(0.22, 0.61, 0.36, 1); }

@media (prefers-reduced-motion: reduce) {
  .content-panel.panel-anim-in,
  .content-panel.panel-anim-back { animation: none; }
}

/* Default (mobile-first): hide side-content when not drilled-in */
.split-workspace:not(.drill-open) .side-content { display: none; }
.split-workspace.drill-open .side-menu { display: none; }

/* 进入(从菜单钻进来):内容滑入 + 淡入。
   ⚠️ 挂在一次性 class .drill-opening 上,而不是常驻的 .drill-open ——
   常驻动画会被 WebKit 在原生端重播成鬼影(原生 <select> 弹层关闭时最明显),
   那正是原来要在原生端把 drillIn 整个关掉的原因。一次性(JS 在 animationend 摘掉,
   见 playDrillIn)原生端就能放心开 —— 同 playPanelAnim / markModalOpening 的做法。
   ⚠️ 淡入是安全的:此刻菜单已 display:none,内容淡入时背后只有 .phone-app 的实底
   背景(--bg),透不出别的东西。之前试过「菜单垫在背后」配合淡入 —— 半透明的内容
   把背后的菜单透出来,就是用户说的「穿透」;而且多画一整层菜单,中低端机上「很卡」。
   所以坚持:任何时候只有 菜单 或 内容 之一在画,不叠层。 */
.split-workspace.drill-open.drill-opening .side-content { animation: drillIn 200ms cubic-bezier(.22, .61, .36, 1); }
@keyframes drillIn {
  from { opacity: 0; transform: translateX(14%); }
  to   { opacity: 1; transform: translateX(0); }
}
/* 返回(点返回键 / 边缘滑动 / 双击 tab):内容直接隐,目标菜单**淡化出现**。
   不再让内容 drillOut 半透明滑走 —— 那会和背后露出的东西叠出穿透;改成干脆的
   交叉:内容瞬间让位(display:none),菜单淡入。背后是实底,不穿透、不卡。
   由 JS 在 closePanel 里给 .side-menu 打一次性 .drill-menu-in(animationend 摘)。 */
.split-workspace .side-menu.drill-menu-in { animation: drillMenuIn 200ms cubic-bezier(.22, .61, .36, 1); }
@keyframes drillMenuIn {
  from { opacity: 0; transform: translateX(-10%); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Drill pattern: always menu-OR-content, regardless of viewport.
   Focuses attention on one task at a time on every screen. */

.drill-toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  margin: -4px 0 4px;
}
.drill-toolbar:empty { display: none; }
.drill-back,
.drill-add {
  height: 30px;
  padding: 0 12px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--muted-strong);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.drill-back::before {
  content: "‹ ";
  margin-right: 2px;
  font-weight: 800;
}
.drill-add::before {
  content: "+ ";
  margin-right: 2px;
  font-weight: 800;
}
.drill-add {
  background: var(--brand-grad);
  color: #fff;
  border-color: transparent;
  box-shadow: 0 4px 12px rgba(255, 87, 34, 0.32);
}
.drill-add:hover { transform: translateY(-1px); }
.drill-back:hover { background: var(--hover); color: var(--ink); }
/* Hide add button on panels without add-target */
.content-panel:not([data-add-target]) > .drill-toolbar > .drill-add { display: none; }
/* Inline drill-back chip is replaced by top-right .view-back button */
.content-panel > .drill-toolbar > .drill-back { display: none; }

.bill-summary-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
.bill-summary-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px 12px;
  padding: 14px 16px 14px 20px;
  border: 0;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  min-width: 0;
  position: relative;
  overflow: hidden;
}
/* 左侧分类色条(参照图):总计紫 / 贷款绿 / 固定费用蓝 */
.bill-summary-card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
  background: var(--muted);
}
.bill-summary-card--total::before { background: linear-gradient(180deg, #a78bfa, #8b5cf6); }
.bill-summary-card--loan::before { background: linear-gradient(180deg, #34d399, #10a35e); }
.bill-summary-card--fixed::before { background: linear-gradient(180deg, #60a5fa, #3b82f6); }
.bill-summary-card > strong { grid-row: 1 / 3; grid-column: 2; align-self: center; }
.bill-summary-card > small { grid-column: 1; }
.bill-summary-card > span:first-child {
  font-size: 10px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.3;
}
.bill-summary-card > strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bill-summary-card > small { font-size: 11px; color: var(--muted); }

.bill-table { display: grid; gap: 8px; }
.bill-table-head { display: none; }
.bill-table-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  gap: 4px 12px;
  align-items: center;
  padding: 12px 14px 12px 20px;
  border: 0;                       /* 无边框,靠阴影区分(全 App 卡片统一) */
  border-radius: var(--radius-sm);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  font-size: 12px;
  position: relative;
  overflow: hidden;
}
.bill-table-row--link { cursor: pointer; transition: background var(--dur) var(--ease); }
.bill-table-row--link:hover { background: var(--soft); }
.bill-table-row--link:active { background: var(--soft); }
/* 去掉点选时的黑色焦点描边 */
.bill-table-row:focus, .bill-table-row:focus-visible { outline: none; }
/* 左侧色条 + 到期天数着色:按紧迫度(越近越红) */
.bill-table-row::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
  background: var(--line);
}
.bill-table-row.due-urgent::before { background: #ef4444; }  /* ≤3 天 红:最紧急 */
.bill-table-row.due-soon::before   { background: #f97316; }  /* ≤7 天 橙 */
.bill-table-row.due-near::before   { background: #f59e0b; }  /* ≤14 天 琥珀 */
.bill-table-row.due-later::before  { background: #14b8a6; }  /* >14 天 青:还很从容 */
.bill-table-row.due-urgent > span:nth-child(3) { color: #ef4444; font-weight: 700; }
.bill-table-row.due-soon > span:nth-child(3)   { color: #f97316; font-weight: 700; }
.bill-table-row.due-near > span:nth-child(3)   { color: #b45309; font-weight: 700; }
.bill-table-row.due-later > span:nth-child(3)  { color: #0d9488; font-weight: 700; }
.bill-table-row > span:nth-child(1) {
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bill-table-row > span:nth-child(2) {
  grid-column: 1;
  grid-row: 2;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bill-table-row > span:nth-child(3) {
  grid-column: 2;
  grid-row: 2;
  font-size: 11px;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}
.bill-table-row > strong {
  grid-column: 2;
  grid-row: 1;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--ink-strong);
  font-feature-settings: "tnum", "lnum";
  white-space: nowrap;
}
.bill-table-row > span { min-width: 0; }
.bill-table-row > span > b {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bill-table-row > span > small {
  display: block;
  font-size: 11px;
  color: var(--muted);
}
.bill-table-row strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 13px;
  color: var(--ink-strong);
  text-align: right;
}

.paylater-list,
.fixed-cost-list,
.income-list {
  display: grid;
  gap: 8px;
}

/* Compact list cards: hide redundant detail-grid; collapse edit button into
   a chevron-style chip at top-right corner inline with the amount. */
.income-item .detail-grid {
  display: none;
}
/* Paylater + fixed-cost detail grids stay visible — they show contract
   info (months / payment day / end date) the user explicitly asked for. */
.income-item,
.fixed-cost-item:not(.income-item),
.paylater-item,
.account-item,
.transaction-item {
  position: relative;
}
/* Tap-anywhere list cards: name+meta+amount inline, chevron at far right,
   the whole card is clickable. The original "编辑" button collapses into a
   decorative chevron icon for cleaner look + bigger tap target.
   NOTE: must NOT apply to .swipe-row — that pattern needs the article to
   stay padding:0 + overflow:hidden so the absolutely-positioned
   .swipe-delete sits beneath .swipe-content cleanly. */
.income-item,
.fixed-cost-item.income-item,
.account-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20px;
  align-items: center;
  gap: 10px;
  padding: 14px 14px 14px 16px;
  cursor: pointer;
  transition: background var(--dur) var(--ease);
}
.income-item:hover,
.account-item:hover { background: var(--soft); }

/* Edit pill on bill swipe rows (fixed costs + loans share the same style).
   Self-contained so it isn't squashed by .fixed-cost-item .card-action's
   font-size:0 / width:20px chevron rule defined earlier. */
.fixed-cost-item.swipe-row > .swipe-content > .card-action,
.paylater-item.swipe-row > .swipe-content > .card-action {
  position: static;
  align-self: end;
  justify-self: end;
  width: auto;
  min-width: 60px;
  height: 30px;
  padding: 0 16px;
  font-size: 12px;
  font-weight: 700;
  line-height: 28px;
  white-space: nowrap;
  background: var(--brand-soft);
  color: var(--brand);
  border: 1px solid var(--brand-ring);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.fixed-cost-item.swipe-row > .swipe-content > .card-action:hover,
.paylater-item.swipe-row > .swipe-content > .card-action:hover {
  background: var(--brand);
  color: #fff;
}
.fixed-cost-item.swipe-row > .swipe-content > .card-action::after,
.paylater-item.swipe-row > .swipe-content > .card-action::after { content: none; }
.income-item .card-action,
.account-item .card-action {
  position: static;
  margin: 0;
  height: 28px;
  width: 20px;
  padding: 0;
  font-size: 0;
  background: transparent;
  border: 0;
  color: var(--muted);
  display: grid;
  place-items: center;
  cursor: pointer;
}
/* 编辑按钮统一成与预算卡(图1)一致的描边胶囊,替掉原来的弱灰"编辑 ›"文字链 */
.paylater-item .card-action,
.fixed-cost-item .card-action {
  position: static;
  height: 32px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 600;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--ink);
  justify-self: end;
  margin-left: auto; /* snooze 隐藏时 Edit 仍靠右 */
}
/* "···" 更多按钮:无椭圆框、透明底,只留点点点(覆盖上面的药丸样式) */
.paylater-item .card-action--more,
.fixed-cost-item .card-action--more {
  display: inline-flex; align-items: center; justify-content: center;
  height: 36px; min-width: 44px; padding: 0 10px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-pill);
  color: var(--muted-strong);
  font-size: 22px;
  line-height: 1;
  letter-spacing: 2px;
}
/* 按下/选中:灰色圆角底(不再用粉橙) */
.paylater-item .card-action--more:hover,
.fixed-cost-item .card-action--more:hover,
.paylater-item .card-action--more:active,
.fixed-cost-item .card-action--more:active { background: var(--soft); color: var(--ink); border-color: transparent; }
.income-item .card-action::after,
.account-item .card-action::after {
  content: "›";
  font-size: 20px;
  font-weight: 600;
  line-height: 1;
}
.paylater-item .card-action::after,
.fixed-cost-item .card-action::after { content: none; }
.income-item:hover .card-action,
.account-item:hover .card-action {
  color: var(--brand);
}
.paylater-item .card-action:not(.card-action--more):hover,
.fixed-cost-item .card-action:not(.card-action--more):hover {
  color: var(--brand);
  background: var(--brand-soft);
  border-color: var(--brand);
}

/* Income card: two-line layout with prominent amount + recurring badge.
   Override the .income-item grid (1fr+20px) defined earlier — for this
   variant the chevron lives inside line-1 next to the amount so the
   arrow visually aligns with the number instead of floating at the
   vertical middle of the whole card. */
.income-item {
  grid-template-columns: 1fr !important;
  align-items: stretch;
  gap: 8px;
  padding: 16px 14px 16px 18px;
}
/* Stacked income card: name / type·due / date stacked on the left, amount
   vertically centered on the right (so the amount isn't pinned to the top row). */
.income-item.income-item--stacked {
  display: flex;
  align-items: center;
  gap: 12px;
}
.income-item--stacked .income-stack-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}
.income-item--stacked .paylater-name {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.income-item--stacked .paylater-meta,
.income-item--stacked .paylater-date {
  font-size: 12px;
  color: var(--muted);
}
/* Amount + chevron travel together as one vertically-centered group on the
   right, so the number and the › always sit on the same line (parallel). */
.income-item--stacked .income-stack-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  align-self: center;
}
.income-item--stacked .income-stack-amount {
  font-feature-settings: "tnum", "lnum";
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--cat-income);
  white-space: nowrap;
}
.income-item--stacked .income-stack-right .card-chevron { align-self: center; }
/* Amount on top, the 每月固定 badge directly under it, both right-aligned. */
.income-item--stacked .income-amount-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  min-width: 0;
}
.income-item--stacked .income-amount-col .income-badge { margin: 0; }

/* 预期收入卡片(Mendatang):左侧彩色图标 tile + 名称/类型 + 大号绿额 + 时间/日期/周期 chip */
.expinc-card {
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 16px;
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.expinc-card + .expinc-card { margin-top: 12px; }
.expinc-ic { flex: none; width: 48px; height: 48px; border-radius: 14px; display: grid; place-items: center; }
.expinc-ic svg { width: 26px; height: 26px; }
.expinc-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.expinc-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.expinc-titles { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.expinc-name { font-size: 16px; font-weight: 800; color: var(--ink-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.expinc-sub { font-size: 12.5px; color: var(--muted); }
.expinc-more { flex: none; border: 0; background: transparent; color: var(--muted); font-size: 20px; font-weight: 800; line-height: 1; letter-spacing: 1px; padding: 4px 8px; margin: -4px -4px 0 0; border-radius: 10px; cursor: pointer; }
.expinc-more:active { background: var(--soft); }
.expinc-more:focus-visible { outline: none; background: var(--soft); }
.expinc-amount { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; color: var(--cat-income); font-feature-settings: "tnum", "lnum"; line-height: 1.12; }
/* 到期 + Berulang/日期 两个 chip 并排一行,缩小字号让它们放得下 */
.expinc-chips { display: flex; flex-wrap: nowrap; align-items: center; gap: 5px; margin-top: 2px; min-width: 0; }
.expinc-chip { display: inline-flex; align-items: center; gap: 4px; padding: 4px 7px; border-radius: 999px; background: var(--soft); color: var(--muted-strong); font-size: 10px; font-weight: 600; white-space: nowrap; }
.expinc-chip svg { width: 12px; height: 12px; flex: none; color: var(--brand-2); }
.expinc-badge { display: inline-flex; align-items: center; gap: 4px; padding: 4px 7px; border-radius: 999px; background: rgba(16, 185, 129, 0.12); color: #10a35e; font-size: 10px; font-weight: 700; white-space: nowrap; }
.expinc-badge svg { width: 12px; height: 12px; flex: none; }

.income-item .income-line-1 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 12px;
}
.income-item .income-line-1 .paylater-name {
  align-self: center;
}
.income-item .income-line-1 > strong {
  align-self: center;
}
.income-item .income-line-1 .card-action {
  align-self: center;
  margin-left: 2px;
}
.income-item .income-line-1 .paylater-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.income-item .income-line-1 > strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--cat-income);
  white-space: nowrap;
}
.income-item .income-line-2 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}
.income-item .income-line-2 .paylater-meta {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1 1 auto;
}
.income-badge {
  flex: 0 0 auto;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  background: var(--cat-income-soft);
  color: var(--cat-income);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  border: 1px solid rgba(34, 197, 94, 0.28);
}
.income-badge.inline {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  font-size: 10px;
  vertical-align: middle;
  text-transform: none;
  letter-spacing: 0.02em;
}

/* ── 11. Profile view ──────────────────────────────────────────── */
.profile-workspace { gap: 14px; }
.report-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.report-card {
  display: grid;
  gap: 4px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  min-width: 0;
}
.report-card--link {
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.1s var(--ease);
}
.report-card--link:hover { border-color: var(--brand); background: var(--soft); }
.report-card--link:active { transform: scale(0.985); }
.report-card--link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.ov-jump { cursor: pointer; }
.ov-jump:hover b, .ov-jump:hover strong { color: var(--brand-2); }
.report-card > span {
  font-size: 10px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.report-card > strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-strong);
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.report-charts { display: grid; gap: 10px; }
.report-chart {
  display: grid;
  gap: 10px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
}
.report-chart > span:first-child {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
.report-chart .chart-copy { font-size: 12px; color: var(--muted); }
.mini-bars { display: grid; gap: 8px; }
.mini-bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  gap: 4px 10px;
  align-items: center;
}
.mini-bar > b {
  grid-column: 1;
  grid-row: 1;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-strong);
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mini-bar > small {
  grid-column: 2;
  grid-row: 1;
  font-feature-settings: "tnum", "lnum";
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
}
.mini-bar > .mini-track {
  grid-column: 1 / -1;
  grid-row: 2;
  height: 6px;
  background: var(--soft);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.mini-bar > .mini-track > span {
  display: block;
  height: 100%;
  background: var(--brand-grad);
  border-radius: inherit;
  transition: width 380ms var(--ease);
}
/* 余额为负(透支)的账户:占比标红,条清空 */
.mini-bar.is-negative > small { color: var(--danger); }
.mini-bar.is-negative > .mini-track > span { background: var(--danger); }

.balance-overview { display: grid; gap: 0; }
.balance-overview-card {
  display: grid;
  gap: 14px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background:
    linear-gradient(135deg, rgba(255, 87, 34, 0.07), transparent 60%),
    var(--card);
}
.balance-overview-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
}
.balance-overview-top > div:first-child { display: grid; gap: 4px; min-width: 0; }
.balance-overview-top .eyebrow {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.balance-overview-top strong {
  font-size: clamp(15px, 4.8vw, 20px);
  font-weight: 800;
  letter-spacing: -0.025em;
  color: var(--ink-strong);
  font-feature-settings: "tnum", "lnum";
  line-height: 1.1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.account-ring {
  display: none; /* replaced by collapse button + filter dropdown */
}
.balance-overview-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
/* 余额筛选下拉套 csel 后:保持紧凑小胶囊(默认 csel-trigger 是 42px 整宽大字段,会撑破头部) */
#balanceOverview .csel-trigger {
  height: 30px; flex: 0 0 auto; width: auto; min-width: 92px; max-width: 148px;
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--card); font-size: 12px; font-weight: 600;
  padding: 0 30px 0 12px;
}
#balanceOverview .csel-trigger .csel-chev { right: 10px; }
.balance-filter {
  height: 30px;
  padding: 0 28px 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'><path d='M6 9l6 6 6-6' fill='none' stroke='%2364748b' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat right 10px center;
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  appearance: none;
  cursor: pointer;
}
.balance-collapse-btn {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--card);
  color: var(--muted-strong);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.balance-collapse-btn:hover {
  background: var(--brand-soft);
  color: var(--brand);
  border-color: var(--brand-ring);
}
.balance-collapse-btn svg { width: 16px; height: 16px; }
.balance-overview-stats {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
}
.balance-overview-stats > span {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--soft);
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  min-width: 0;
}
.balance-overview-stats > span > b {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--ink-strong);
  text-transform: none;
  font-feature-settings: "tnum", "lnum";
  white-space: nowrap;
  text-align: right;
}
.balance-overview-card > p {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
}
.account-mix {
  display: grid;
  gap: 8px;
  padding: 12px;
  border-radius: var(--radius-sm);
  background: var(--soft);
}
.account-mix > small {
  font-size: 10px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.account-mix > div {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
}
.account-mix span {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--ink);
  min-width: 0;
  white-space: nowrap;
}
.account-mix span > i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: block;
  flex-shrink: 0;
}
.account-mix span > b {
  margin-left: auto;
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-strong);
  letter-spacing: -0.01em;
  font-feature-settings: "tnum", "lnum";
  white-space: nowrap;
}
/* KOMPOSISI ASET 金额里的 Rp 用小号灰前缀(与上方一致) */
.account-mix span > b .rp-prefix { font-size: 0.62em; font-weight: 600; opacity: 0.55; color: var(--muted); }

/* Savings goal card (Profile → 余额) */
.savings-goal-card {
  position: relative;
  display: grid;
  gap: 14px;
  padding: 20px 20px 18px;
  margin-bottom: 4px;
  border-radius: var(--radius);
  color: var(--ink);
  background:
    radial-gradient(120% 70% at 0% 0%, rgba(16, 185, 129, 0.22), transparent 55%),
    radial-gradient(120% 70% at 100% 100%, rgba(34, 211, 238, 0.14), transparent 55%),
    linear-gradient(140deg, #f0fdf4 0%, #ecfdf5 55%, #d1fae5 100%);
  border: 1px solid rgba(16, 185, 129, 0.35);
  box-shadow: 0 6px 20px rgba(16, 185, 129, 0.10);
  overflow: hidden;
}
.savings-goal-card::after {
  content: "";
  position: absolute;
  inset: auto -20% -40% auto;
  width: 60%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(52, 211, 153, 0.35), transparent 70%);
  pointer-events: none;
}
.savings-goal-card > * { position: relative; z-index: 1; }

.savings-goal-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.savings-goal-head > div { min-width: 0; }
.savings-goal-head .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #047857;
  margin-bottom: 6px;
}
.savings-goal-icon { font-size: 14px; line-height: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.18)); }
.savings-goal-head strong {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.025em;
  color: #064e3b;
  font-feature-settings: "tnum", "lnum";
  line-height: 1.1;
}
.savings-goal-edit {
  flex-shrink: 0;
  height: 34px;
  padding: 0 18px;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 700;
  border-radius: var(--radius-pill);
  background: #047857;
  color: #fff;
  border: 0;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(5, 150, 105, 0.34);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.savings-goal-edit:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(5, 150, 105, 0.42); }

.savings-goal-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.savings-goal-stats > span {
  display: grid;
  gap: 4px;
  padding: 12px 12px;
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid rgba(16, 185, 129, 0.18);
  border-radius: var(--radius-sm);
  backdrop-filter: blur(6px);
}
.savings-goal-stats small {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #047857;
}
.savings-goal-stats b {
  font-size: 13px;
  font-weight: 800;
  color: #064e3b;
  letter-spacing: -0.015em;
  font-feature-settings: "tnum", "lnum";
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Make Rp prefix inside the goal-stat tiles use the emerald accent so
   it doesn't disappear into the gradient surface. */
.savings-goal-stats b .rp-prefix {
  color: #047857;
  -webkit-text-fill-color: #047857;
  opacity: 0.75;
}
/* Spacing inside the progress block: stats grid → bar → note */
.savings-goal-progress {
  display: grid;
  gap: 14px;
}
/* Tall progress bar with overlaid percentage label */
.savings-goal-bar {
  position: relative;
  height: 32px;
  margin-top: 4px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(16, 185, 129, 0.18);
  overflow: hidden;
}
.savings-goal-bar-fill {
  display: block;
  height: 100%;
  min-width: 10px;
  background: linear-gradient(90deg, #34d399, #059669);
  box-shadow: 0 0 14px rgba(52, 211, 153, 0.55);
  border-radius: inherit;
  transition: width 380ms var(--ease);
}
.savings-goal-bar-label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: #064e3b;
  font-feature-settings: "tnum", "lnum";
  /* tiny white halo so the % is legible on both filled + empty halves */
  text-shadow: 0 0 4px rgba(255, 255, 255, 0.85), 0 0 2px rgba(255, 255, 255, 0.85);
  pointer-events: none;
}
.savings-goal-note {
  font-size: 12px;
  font-weight: 600;
  color: #047857;
}

/* Dark mode: rich emerald surface, mint highlights, glow */
:root[data-theme="dark"] .savings-goal-card {
  background:
    radial-gradient(120% 70% at 0% 0%, rgba(52, 211, 153, 0.18), transparent 55%),
    radial-gradient(120% 70% at 100% 100%, rgba(34, 211, 238, 0.10), transparent 55%),
    linear-gradient(140deg, #0a2018 0%, #0c2a1e 55%, #103325 100%);
  border-color: rgba(52, 211, 153, 0.32);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.32);
}
:root[data-theme="dark"] .savings-goal-card::after {
  background: radial-gradient(closest-side, rgba(52, 211, 153, 0.28), transparent 70%);
}
:root[data-theme="dark"] .savings-goal-head .eyebrow,
:root[data-theme="dark"] .savings-goal-stats small,
:root[data-theme="dark"] .savings-goal-note {
  color: #6ee7b7;
}
:root[data-theme="dark"] .savings-goal-head strong,
:root[data-theme="dark"] .savings-goal-stats b {
  color: #ecfdf5;
}
:root[data-theme="dark"] .savings-goal-edit {
  /* brighter mint so it reads as a solid CTA against the deep card */
  background: #34d399;
  color: #04201a;
  box-shadow: 0 4px 14px rgba(52, 211, 153, 0.45);
}
:root[data-theme="dark"] .savings-goal-edit:hover {
  background: #6ee7b7;
  box-shadow: 0 6px 18px rgba(110, 231, 183, 0.5);
}
:root[data-theme="dark"] .savings-goal-stats b .rp-prefix {
  color: #6ee7b7;
  -webkit-text-fill-color: #6ee7b7;
  opacity: 0.85;
}
:root[data-theme="dark"] .savings-goal-stats > span {
  background: rgba(16, 185, 129, 0.12);
  border-color: rgba(52, 211, 153, 0.24);
}
:root[data-theme="dark"] .savings-goal-card .budget-bar {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(52, 211, 153, 0.20);
}
:root[data-theme="dark"] .savings-goal-bar {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(52, 211, 153, 0.22);
}
:root[data-theme="dark"] .savings-goal-bar-label {
  color: #ecfdf5;
  text-shadow: 0 0 4px rgba(0, 0, 0, 0.6), 0 0 2px rgba(0, 0, 0, 0.6);
}

/* ── Target Tabungan 卡(绿色,照 mockup 图1) ─────────────────────────── */
.sg-card {
  padding: 20px;
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(16,185,129,0.06), rgba(16,185,129,0.015));
  border: 1px solid rgba(16,185,129,0.16);
}
.sg-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sg-eyebrow { display: inline-flex; align-items: center; gap: 10px; font-size: 12px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: #0f9d58; min-width: 0; }
.sg-bag { width: 38px; height: 38px; flex: none; border-radius: 50%; background: var(--card); display: grid; place-items: center; color: #10a35e; box-shadow: 0 2px 6px rgba(16,185,129,0.14); }
.sg-bag svg { width: 20px; height: 20px; }
.sg-atur { flex: none; display: inline-flex; align-items: center; gap: 7px; min-height: 40px; padding: 0 18px; border: 0; border-radius: 999px; background: linear-gradient(135deg, #16a34a, #0f9d58); color: #fff; font-size: 14px; font-weight: 800; cursor: pointer; box-shadow: 0 6px 14px rgba(16,163,74,0.30); }
.sg-atur::before { content: ""; width: 16px; height: 16px; flex: none; background: currentColor; -webkit-mask: center/contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z'/%3E%3C/svg%3E"); mask: center/contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z'/%3E%3C/svg%3E"); }
.sg-amount { display: block; margin: 10px 0 18px; font-size: 33px; font-weight: 800; letter-spacing: -0.02em; color: #07533a; font-feature-settings: "tnum","lnum"; line-height: 1.05; }
.sg-amount .rp-prefix, .sg-amount small { color: #6b7280; font-weight: 700; }
.sg-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.sg-tile { background: var(--card); border-radius: 16px; padding: 16px; display: grid; gap: 7px; }
.sg-tile-ic { width: 34px; height: 34px; border-radius: 50%; background: rgba(16,185,129,0.10); color: #10a35e; display: grid; place-items: center; }
.sg-tile-ic svg { width: 18px; height: 18px; }
.sg-tile small, .sg-progtop small, .sg-target-txt small { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.sg-tile b { font-size: 18px; font-weight: 800; color: #07533a; font-feature-settings: "tnum","lnum"; }
.sg-tile b .rp-prefix, .sg-tile b small { color: #9ca3af; font-weight: 700; }
.sg-progbox { background: var(--card); border-radius: 16px; padding: 16px; margin-top: 12px; }
.sg-progtop { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.sg-pct { font-size: 17px; font-weight: 800; color: #10a35e; }
.sg-progbox .savings-goal-bar { height: 12px; border-radius: 999px; background: rgba(16,185,129,0.13); overflow: hidden; border: 0; }
.sg-progbox .savings-goal-bar-fill { display: block; height: 100%; background: linear-gradient(90deg, #16a34a, #0f9d58); border-radius: 999px; }
.sg-of { margin-top: 9px; font-size: 12.5px; color: var(--muted); }
.sg-target { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding-top: 14px; border-top: 1px solid rgba(16,185,129,0.14); }
.sg-target-txt { display: grid; gap: 2px; min-width: 0; }
.sg-target-txt b { font-size: 16px; font-weight: 800; color: var(--ink-strong); }
:root[data-theme="dark"] .sg-amount, :root[data-theme="dark"] .sg-tile b { color: #6ee7b7; }

.account-list { display: grid; gap: 8px; }
.account-item {
  display: grid;
  gap: 10px;
  padding: 14px;
}
.account-item .row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}
.account-item .row > div {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.account-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.account-item .account-type {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.account-item strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--ink-strong);
  white-space: nowrap;
}

.budget-grid { display: grid; gap: 8px; }
.budget-item {
  display: grid;
  gap: 8px;
  padding: 14px;
  position: relative;
  --cat-color: var(--cat-other);
  --cat-color-soft: var(--cat-other-soft);
}
.budget-item.cat-food { --cat-color: var(--cat-food); --cat-color-soft: var(--cat-food-soft); }
.budget-item.cat-transport { --cat-color: var(--cat-transport); --cat-color-soft: var(--cat-transport-soft); }
.budget-item.cat-shopping { --cat-color: var(--cat-shopping); --cat-color-soft: var(--cat-shopping-soft); }
.budget-item.cat-fun { --cat-color: var(--cat-fun); --cat-color-soft: var(--cat-fun-soft); }
.budget-item.cat-bills { --cat-color: var(--cat-bills); --cat-color-soft: var(--cat-bills-soft); }
.budget-item.cat-saving { --cat-color: var(--cat-saving); --cat-color-soft: var(--cat-saving-soft); }
.budget-item.cat-debt { --cat-color: var(--cat-debt); --cat-color-soft: var(--cat-debt-soft); }
.budget-item.cat-travel { --cat-color: var(--cat-travel); --cat-color-soft: var(--cat-travel-soft); }
.budget-item.cat-medical { --cat-color: var(--cat-medical); --cat-color-soft: var(--cat-medical-soft); }
.budget-item.cat-education { --cat-color: var(--cat-education); --cat-color-soft: var(--cat-education-soft); }
.budget-item.cat-entertainment { --cat-color: var(--cat-entertainment); --cat-color-soft: var(--cat-entertainment-soft); }
.budget-item.cat-insurance { --cat-color: var(--cat-insurance); --cat-color-soft: var(--cat-insurance-soft); }
.budget-item.cat-maintenance { --cat-color: var(--cat-maintenance); --cat-color-soft: var(--cat-maintenance-soft); }
.budget-item.cat-rent { --cat-color: var(--cat-rent); --cat-color-soft: var(--cat-rent-soft); }
.budget-item.cat-telecom { --cat-color: var(--cat-telecom); --cat-color-soft: var(--cat-telecom-soft); }
.budget-item.cat-utilities { --cat-color: var(--cat-utilities); --cat-color-soft: var(--cat-utilities-soft); }
.budget-item.cat-tax { --cat-color: var(--cat-tax); --cat-color-soft: var(--cat-tax-soft); }
.budget-item.cat-gift { --cat-color: var(--cat-gift); --cat-color-soft: var(--cat-gift-soft); }
.budget-item.cat-pet { --cat-color: var(--cat-pet); --cat-color-soft: var(--cat-pet-soft); }
.budget-item.cat-fitness { --cat-color: var(--cat-fitness); --cat-color-soft: var(--cat-fitness-soft); }
.budget-item.cat-income { --cat-color: var(--cat-income); --cat-color-soft: var(--cat-income-soft); }
.budget-item.cat-reimbursement { --cat-color: var(--cat-reimbursement); --cat-color-soft: var(--cat-reimbursement-soft); }
.budget-item[data-budget-details] { cursor: pointer; }
.budget-item[data-budget-details]:hover { box-shadow: 0 8px 22px rgba(15, 23, 42, 0.10); }
.budget-item .row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}
.budget-item .row > .cat-icon {
  width: 28px;
  height: 28px;
  border-radius: 10px;
  background: var(--cat-color-soft);
  border: 1px solid var(--cat-color);
  color: var(--cat-color);
  display: grid;
  place-items: center;
}
.cat-icon svg { width: 16px; height: 16px; display: block; }
.budget-item .row > div { min-width: 0; }
.budget-item h3 { font-size: 14px; }
.budget-item .account-type {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.budget-metrics {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  color: var(--muted);
}
.budget-metrics > span {
  font-feature-settings: "tnum", "lnum";
}
.budget-metrics > strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--cat-color);
}
.budget-percent-row {
  display: flex;
  justify-content: center;
  margin-top: 4px;
}
.budget-percent-row > strong {
  font-feature-settings: "tnum", "lnum";
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--cat-color);
}
.budget-item.warn .budget-percent-row > strong { color: var(--warn); }
.budget-item.over .budget-percent-row > strong { color: var(--danger); }

.budget-bar {
  position: relative;
  height: 7px;
  border-radius: var(--radius-pill);
  background: var(--soft);
  overflow: hidden;
}
.budget-bar > span {
  display: block;
  height: 100%;
  background: var(--cat-color);
  border-radius: inherit;
  transition: width 380ms var(--ease);
}
.budget-item.warn {
  border-color: rgba(217, 119, 6, 0.4);
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.05), transparent 60%), var(--card);
}
.budget-item.warn .budget-bar > span { background: var(--warn-grad); }
.budget-item.warn .budget-metrics > strong { color: var(--warn); }
.budget-item.over {
  border-color: rgba(220, 38, 38, 0.42);
  background: linear-gradient(135deg, rgba(239, 68, 68, 0.06), transparent 60%), var(--card);
}
.budget-item.over .budget-bar > span { background: var(--danger-grad); }
.budget-item.over .budget-metrics > strong { color: var(--danger); }

/* Monthly / yearly billing toggle above the plan cards */
.billing-cycle {
  display: flex;
  gap: 6px;
  padding: 4px;
  margin-bottom: 12px;
  background: var(--soft);
  border-radius: var(--radius-sm);
}
.billing-cycle button {
  flex: 1;
  padding: 8px 10px;
  border: 0;
  border-radius: calc(var(--radius-sm) - 3px);
  background: transparent;
  color: var(--muted-strong);
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.billing-cycle button.active {
  background: var(--bg);
  color: var(--ink-strong);
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.1);
}
.billing-save {
  font-style: normal;
  font-size: 11px;
  font-weight: 700;
  color: var(--brand-2);
  background: var(--brand-soft);
  padding: 1px 6px;
  border-radius: 999px;
}
.plan-grid {
  display: grid;
  gap: 10px;
}
.plan-card {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr; /* 盾牌 | 文案(满列到底);勾改为绝对定位浮在右侧 */
  align-items: center;
  gap: 12px;
  min-height: 96px; /* 标题移到盾牌下后整框更矮;高度由 badge-col 决定,4 档一致 */
  padding: 12px 16px 12px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  text-align: left;
  color: var(--ink);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* Left metallic accent bar, tinted per tier */
.plan-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--tier-grad, var(--line));
}
/* 盾牌列:徽章 + 名称竖排居中(名称在盾牌下面) */
.plan-badge-col { display: grid; justify-items: center; align-content: center; gap: 4px; }
/* 徽章改用贴图(3D 玻璃质感 PNG):.plan-badge 仅作容器,不再画六边形/渐变/光泽 */
.plan-badge {
  position: relative;
  width: 64px; height: 64px;
  display: grid; place-items: center;
  flex: none;
}
.plan-badge-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.plan-info { display: grid; gap: 3px; min-width: 0; padding-right: 44px; }
/* 功能字独占一行,挣脱右侧留白压在勾上方(满列到底);金额/到期留出勾的位置 */
.plan-info > small:first-child { margin-right: -44px; }
.plan-name {
  font-size: 12px; font-weight: 800;
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em;
  text-align: center; white-space: nowrap;
}
/* 分档标题彩色(照富版):GRATIS 橙 / GOLD 金 / PLATINUM 紫;SILVER 维持灰 */
.plan-card--free .plan-name { color: var(--brand-2); }
.plan-card--gold .plan-name { color: #c5901a; }
.plan-card--platinum .plan-name { color: #8b5cf6; }
.plan-price {
  font-size: 18px; font-weight: 800;
  letter-spacing: -0.02em; font-feature-settings: "tnum", "lnum";
}
.plan-info small { font-size: 12px; color: var(--muted); }
.plan-per { font-size: 13px; font-weight: 600; color: var(--muted); }
.plan-expiry { font-size: 11px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.plan-name-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/* 右侧标记:未选=灰描边 chevron;当前档=主题色实心 + 白勾 */
.plan-mark {
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 1.5px solid var(--line);
  background: transparent;
  display: grid; place-items: center;
}
.plan-mark::before {
  content: "";
  width: 15px; height: 15px;
  background: var(--muted);
  -webkit-mask: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E");
  mask: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E");
}
.plan-card.active {
  border-color: var(--line);
  background:
    linear-gradient(135deg, var(--brand-soft), transparent 60%),
    var(--card);
  box-shadow: var(--shadow-sm);
}
.plan-card.active .plan-mark { border-color: transparent; background: var(--brand-2); }
.plan-card.active .plan-mark::before {
  background: #fff;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
}
.plan-forever { display: inline-flex; align-items: center; gap: 5px; align-self: start; margin-top: 5px; min-height: 26px; box-sizing: border-box; padding: 3px 10px; border-radius: 999px; background: rgba(15, 23, 42, 0.05); font-size: 11px; font-weight: 700; color: var(--muted-strong); }
.plan-forever > span[aria-hidden] { font-size: 13px; font-weight: 800; line-height: 1; }
/* 到期药丸:灰色标签在左、日期(不加粗)靠右 */
.plan-renew { width: 100%; }
.plan-renew .plan-renew-text { display: flex; flex: 1; align-items: center; justify-content: space-between; gap: 8px; }
.plan-renew .pr-lab { color: var(--muted); font-weight: 700; }
.plan-renew .pr-date { color: var(--ink-strong); font-weight: 600; }
/* 未订阅(到期药丸 hidden)时仍占位(隐形):选中/未选中卡片三行布局一致,
   功能字始终在最上方,不会因少一行而下移压到勾/箭头(重叠) */
.plan-renew[hidden] { display: inline-flex !important; visibility: hidden; }
/* 底部安全条 */
.payment-secure { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding: 13px 15px; border-radius: var(--radius); background: var(--soft); }
.payment-secure .ps-ic { flex: none; width: 34px; height: 34px; border-radius: 10px; background: rgba(16, 185, 129, 0.14); color: var(--ok); display: grid; place-items: center; }
.payment-secure .ps-ic svg { width: 19px; height: 19px; }
.payment-secure .ps-text { flex: 1; min-width: 0; display: grid; gap: 1px; }
.payment-secure .ps-text strong { font-size: 13px; font-weight: 800; color: var(--ink); }
.payment-secure .ps-text small { font-size: 11.5px; color: var(--muted); line-height: 1.35; }
.payment-secure .ps-lock { flex: none; width: 18px; height: 18px; color: var(--muted); }

/* Tier metals — deliberately spread across lightness AND hue so free / silver
   / platinum no longer read as the same grey. */
.plan-card--free     { --tier-grad: linear-gradient(135deg, #ff8a5c, #ff5722 55%, #e8430a); }
.plan-card--silver   { --tier-grad: linear-gradient(135deg, #ffffff 0%, #c4c9d2 34%, #eef1f5 50%, #9098a3 72%, #dfe3e9 100%); }
.plan-card--gold     { --tier-grad: linear-gradient(135deg, #fff4cc 0%, #e3b53c 40%, #fff7d6 54%, #c5901a 80%, #f1c84e 100%); }
.plan-card--platinum { --tier-grad: linear-gradient(135deg, #4a4e5a, #0d0e13 45%, #5a5f6e 60%, #15161c); }

/* (徽章已改贴图,旧的六边形/钻石描边样式不再需要) */

.option-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--soft);
}
.option-grid button {
  display: grid;
  place-items: center;
  min-height: 34px;
  padding: 0 4px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--muted-strong);
  text-align: center;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.option-grid button.active {
  background: var(--ink);
  color: #fff;
  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.18);
}
:root[data-theme="dark"] .option-grid button.active {
  background: var(--brand-grad);
  color: #fff;
}

/* ── Chat AI 设置页(照 mockup) ─────────────────────────────────────────── */
/* 只在激活时用 grid——否则会盖过 .content-panel{display:none},导致 Chat 内容在每个菜单里都显示 */
.chat-ai-panel.active { display: grid; gap: 16px; }
.cai-card { display: grid; gap: 14px; }
.cai-card .settings-card-head { display: flex; align-items: flex-start; gap: 12px; }
/* 分段:图标 + 文字,选中橙色实心,未选之间细分隔线 */
.cai-seg { display: flex; gap: 0; padding: 5px; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--soft); }
.cai-seg button { position: relative; flex: 1; min-width: 0; display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 52px; padding: 6px 2px; border: 0; border-radius: calc(var(--radius-pill) - 2px); background: transparent; color: var(--muted-strong); font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.cai-seg button svg { width: 19px; height: 19px; flex: none; }
.cai-seg button span { overflow: hidden; text-overflow: ellipsis; }
.cai-seg button + button::before { content: ""; position: absolute; left: 0; top: 22%; bottom: 22%; width: 1px; background: var(--line); }
.cai-seg button.active { background: var(--brand-grad); color: #fff; box-shadow: none; }
.cai-seg button.active::before, .cai-seg button.active + button::before { display: none; }
/* Avatar 行:圆形预览 + 虚线上传框 */
.cai-avatar-row { display: grid; grid-template-columns: auto 1fr; gap: 16px; align-items: stretch; }
.chat-ai-panel #avatarPreview { width: 104px; height: 104px; border-radius: 50%; flex: none; box-shadow: 0 2px 10px rgba(15,23,42,0.08); }
.cai-upload { display: flex; align-items: center; gap: 14px; padding: 16px; border: 1.5px dashed var(--line-strong, var(--line)); border-radius: 16px; cursor: pointer; }
.cai-upload input[type="file"] { position: absolute; width: 0; height: 0; opacity: 0; }
.cai-upload-ic { width: 46px; height: 46px; flex: none; border-radius: 12px; background: rgba(255,87,34,0.10); color: var(--brand-2); display: grid; place-items: center; }
.cai-upload-ic svg { width: 24px; height: 24px; }
.cai-upload-txt b { display: block; font-size: 14.5px; color: var(--ink-strong); }
.cai-upload-txt small { font-size: 12.5px; color: var(--muted); line-height: 1.4; }
.cai-default-link { display: block; margin: 2px auto 0; padding: 6px 4px; border: 0; background: transparent; color: var(--muted-strong); font-size: 13.5px; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
/* Panggilan 输入 + 提示 + 底部保存 */
.cai-input { width: 100%; height: 50px; padding: 0 16px; border: 0; border-radius: 14px; background: var(--soft); color: var(--ink-strong); font-size: 15px; outline: none; }
.cai-input:focus { background: var(--hover); }
.cai-hint { margin: 0; font-size: 12.5px; color: var(--muted); }
.cai-simpan { width: 100%; height: 54px; margin-top: 4px; border: 0; border-radius: 16px; background: var(--accent-grad); color: #fff; font-size: 16px; font-weight: 800; cursor: pointer; }
.cai-simpan:active { transform: scale(0.99); }

.avatar-card { display: grid; gap: 12px; padding: 16px; min-width: 0; }
.avatar-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: center;
  gap: 14px;
}
.avatar-row > div { min-width: 0; }
.avatar-row strong { font-size: 14px; }
.avatar-row small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.chat-avatar {
  position: relative;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 14px;
  background: var(--soft);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  flex: 0 0 auto;
  overflow: hidden;
  border: 1px solid var(--line);
}
.chat-avatar .avatar-emoji,
.chat-avatar .avatar-twemoji {
  width: 36px;
  height: 36px;
  display: block;
  /* Soft drop shadow makes the character feel like it floats above the chip */
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.18));
}
.chat-avatar .avatar-emoji {
  font-size: 32px;
  line-height: 1;
  width: auto;
  height: auto;
}
.chat-avatar.custom {
  background: var(--card);
}
.chat-avatar.custom img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.chat-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
/* Bundled persona×tone portrait fills the whole circle (overrides the 36px emoji
   sizing of .avatar-twemoji); top crop keeps the head in frame. When the asset is
   missing, __avatarFallback strips this class and restores the emoji styling. */
.chat-avatar .avatar-portrait {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  border-radius: inherit;
  filter: none;
  /* Settings preview: scale the whole portrait DOWN a touch so the full head
     (incl. hair) always shows and the rounded corners never bite the top. */
  transform: scale(0.95);
}
/* Chat chip should look FULL. The portraits are square with studio padding above
   the head, so cover (square→square) renders that empty space and the subject
   looks small. Zoom in on the face/upper-body (focal point ~30% down) so the
   padding is cropped away while the hairline stays just inside the frame. */
.message .chat-avatar .avatar-portrait {
  /* Show the WHOLE portrait (full body), not a zoomed-in crop. */
  object-fit: contain;
  transform: none;
}
.chat-avatar .avatar-face {
  display: block;
  width: 100%;
  height: 100%;
}
.chat-avatar .avatar-svg {
  width: 100%;
  height: 100%;
  display: block;
}

.avatar-upload {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 10px 14px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  color: var(--brand);
  text-align: center;
  overflow: hidden;
}
.avatar-upload input[type="file"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  font-size: 0;
}

.switch-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
/* Tampilan:每项独立卡 + 彩色图标 tile + 开关(参照图) */
.settings-card.setting-tile { display: flex; align-items: center; gap: 14px; padding: 16px; }
.setting-tile .st-ic { flex: none; width: 48px; height: 48px; border-radius: 14px; display: grid; place-items: center; }
.setting-tile .st-ic svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.st-ic-purple { background: rgba(139, 92, 246, 0.14); color: #8b5cf6; }
.st-ic-green { background: rgba(16, 185, 129, 0.14); color: #10a35e; }
.st-ic-blue { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.st-ic-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.setting-tile .st-row { flex: 1; min-width: 0; border-top: 0; padding: 0; }
/* 主题三档:复用语言 pill 样式(.language-switch),标签左 + pill 右;窄屏 pill 换行占满 */
.setting-tile.st-theme-tile { flex-wrap: wrap; }
.st-theme-tile .st-theme-head { flex: 1; min-width: 96px; }
.st-theme-tile .st-theme-head strong { display: block; font-size: 14.5px; color: var(--ink-strong); }
.st-theme-tile .st-theme-head small { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.st-theme-tile .theme-seg { flex: none; margin-left: auto; }
@media (max-width: 400px) {
  .st-theme-tile .theme-seg { width: 100%; margin: 6px 0 0; }
  .st-theme-tile .theme-seg button { flex: 1; }
}
.setting-foot { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px; background: var(--soft); border-radius: var(--radius); margin-top: 2px; }
.setting-foot > svg { flex: none; width: 22px; height: 22px; color: var(--muted); margin-top: 1px; }
.setting-foot strong { display: block; font-size: 13.5px; color: var(--ink-strong); }
.setting-foot small { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.switch-row[hidden] { display: none; }
.switch-row:first-child,
.input-row:first-child { border-top: 0; padding-top: 0; }
.input-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
.input-row strong { display: block; font-size: 14px; }
.input-row small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
/* The "current time in {tz}" line is a 3rd grid child — left as-is it gets jammed
   into the 1fr label column and clips against the select. Span both columns so the
   localized "{tz} · {date} {time}" string (length varies a lot by language) has the
   full row width to sit on, with breathing room above. */
.input-row .emergency-fund-hint {
  grid-column: 1 / -1;
  margin-top: 8px;
  color: var(--brand);
  font-weight: 600;
  font-size: 13px;
  line-height: 1.4;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.input-row .emergency-fund-hint > span:last-child { color: var(--muted-strong); white-space: nowrap; }
.input-row input {
  width: 130px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.input-row select {
  width: 100%;
  min-width: 168px;
  max-width: 210px;
  padding: 9px 36px 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background-color: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 15px;
  cursor: pointer;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.input-row select:hover { border-color: var(--brand); }
.input-row select:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

/* Brief fade across amount displays right after a currency switch, so the
   whole sheet visibly "re-renders" instead of numbers snapping silently. */
@keyframes currencyFlash {
  from { opacity: .5; }
  to   { opacity: 1; }
}
.currency-flash .rp-line,
.currency-flash [id$="Money"],
.currency-flash [id$="Amount"],
.currency-flash [id$="Total"],
.currency-flash .amount,
.currency-flash .transaction-item small {
  animation: currencyFlash .38s ease;
}
.switch-row strong { display: block; font-size: 14px; }
.switch-row small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.switch-row input[type="checkbox"] {
  appearance: none;
  position: relative;
  width: 44px;
  height: 26px;
  border-radius: var(--radius-pill);
  background: var(--line-strong);
  cursor: pointer;
  transition: background var(--dur) var(--ease);
}
.switch-row input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  transition: transform var(--dur) var(--ease);
}
.switch-row input[type="checkbox"]:checked { background: var(--brand-grad); }
/* 弹性收尾:滑块滑到位时轻微过冲再回弹,比匀速停住有「咔哒」的手感。
   只动 transform,合成器就能搞定,中低端机也不掉帧。 */
.switch-row input[type="checkbox"]::after {
  /* 1.75 的过冲 + 更长的行程时间:之前 1.42/320ms 手感偏"稳",用户反馈不够。
     现在滑块会明显冲过头再弹回来,像真的被弹簧推过去。 */
  transition: transform 400ms cubic-bezier(.34, 1.75, .45, 1), width 180ms var(--ease);
}
/* 轨道底色也跟着渐变,不再是瞬间换色 —— 颜色和位移同步走完才像一个动作 */
.switch-row input[type="checkbox"] { transition: background 300ms var(--ease); }
/* 按下时整体轻微下压,松手回弹 */
.switch-row input[type="checkbox"]:active { transform: scale(.94); }
.switch-row input[type="checkbox"]:checked::after { transform: translateX(18px); }
/* 按住时滑块拉长(iOS 开关就是这个手感),松手缩回 —— 拉长时右端要跟着补偿,
   否则开着的状态下按住会溢出轨道右边。 */
.switch-row input[type="checkbox"]:active::after { width: 26px; }
.switch-row input[type="checkbox"]:checked:active::after { transform: translateX(12px); }

/* ── 展开/收缩箭头:统一用旋转,不换图形 ──────────────────────
   以前是直接对调两个 SVG path(向下↔向上),瞬间切换没有翻转过程,看着像闪了一下。
   这条按 aria-expanded 生效,所以全 App 所有展开控件自动都有 —— 不用逐个改。 */
/* 展开区底部的「收起」:整行可点,比右上角那个小箭头好够。
   刻意做得低调(无底色、灰字)—— 它是退出动作,不该和主操作抢注意力。 */
.balance-collapse-foot {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-top: 10px; padding: 9px 0;
  border: 0; border-top: 1px solid var(--line);
  background: transparent; color: var(--muted);
  font-size: 12.5px; font-weight: 650; cursor: pointer;
  transition: color .15s var(--ease), transform .12s var(--ease);
}
.balance-collapse-foot:hover { color: var(--ink); }
.balance-collapse-foot:active { transform: scale(.98); }
.balance-collapse-foot svg { width: 15px; height: 15px; flex: none; }

/* ── 弹簧 / 流体动效 ────────────────────────────────────────────
   纯 transition 只能过冲**一次**,做不出真弹簧(多次来回衰减振荡)。
   改用一次性关键帧,并把两种运动拆到两个元素上 ——
   同一个 transform 属性同时被 transition 和 animation 写会互相覆盖:
     · <svg>   负责旋转(transition,方向由 aria-expanded 决定)
     · <button> 负责弹簧缩放(animation,一次性 class,JS 在点击时打上)
   开关同理:::after 负责位移(transition),width 走关键帧做「被拽长的水滴」。 */
[aria-expanded] > svg {
  transition: transform 460ms cubic-bezier(.34, 1.56, .5, 1);
}
[aria-expanded="true"] > svg { transform: rotate(180deg); }

/* 弹簧:四次衰减振荡,不是单纯过冲一下 */
@keyframes springPop {
  0%   { transform: scale(1); }
  18%  { transform: scale(.84); }
  38%  { transform: scale(1.16); }
  58%  { transform: scale(.94); }
  76%  { transform: scale(1.06); }
  90%  { transform: scale(.98); }
  100% { transform: scale(1); }
}
.spring-pop { will-change: transform; animation: springPop 460ms cubic-bezier(.36, .07, .19, .97); }

/* iOS 飞行模式开关的手感:滑块像被拖着走 —— 前缘先动,后缘拖成胶囊,落位收圆。
   transform-origin 钉在**前缘**(开=right / 关=left),拉伸才只往后拖;
   用 center 的话两边一起外扩,那是「果冻」不是 iOS。

   ⚠️ 时间函数必须是 linear,缓动**烘进关键帧数值里**。
   这是之前「渲染满帧但看着一顿一顿」的真正原因:关键帧动画的缓动函数是
   **逐段生效**的,不是整段。原来写 cubic-bezier(.32,.72,.3,1) 配 5 个关键帧,
   而这条曲线前 32% 时间就走完 72% 行程(极度前重)—— 于是每一段都「猛冲一下
   再爬行」,4 段接起来就是 4 次顿挫。60fps 逐帧看是连续的,眼睛看到的却是卡顿。

   下面的数值按 10% 等距采样自一条平滑曲线,速度是「加速 → 匀速 → 减速 → 收住」,
   一阶导连续。位移**不做过冲** —— 试过 0.2px 的过冲,那个量级肉眼根本看不见,
   却带来一次方向反转、还让最后 10% 完全静止(空转)。弹性感交给 scaleX 的
   拉伸/回弹去表达,位移只管干净地到位。 */
@keyframes knobLiquidOn {
  0%   { transform: translateX(0)      scaleX(1); }
  10%  { transform: translateX(2.3px)  scaleX(1.06); }
  20%  { transform: translateX(6.1px)  scaleX(1.16); }
  30%  { transform: translateX(9.9px)  scaleX(1.24); }
  40%  { transform: translateX(13px)   scaleX(1.22); }
  50%  { transform: translateX(15.3px) scaleX(1.15); }
  60%  { transform: translateX(16.7px) scaleX(1.08); }
  70%  { transform: translateX(17.5px) scaleX(1.03); }
  80%  { transform: translateX(17.8px) scaleX(1.01); }
  90%  { transform: translateX(17.96px) scaleX(1); }
  100% { transform: translateX(18px)   scaleX(1); }
}
@keyframes knobLiquidOff {
  0%   { transform: translateX(18px)    scaleX(1); }
  10%  { transform: translateX(15.7px)  scaleX(1.06); }
  20%  { transform: translateX(11.9px)  scaleX(1.16); }
  30%  { transform: translateX(8.1px)   scaleX(1.24); }
  40%  { transform: translateX(5px)     scaleX(1.22); }
  50%  { transform: translateX(2.7px)   scaleX(1.15); }
  60%  { transform: translateX(1.3px)   scaleX(1.08); }
  70%  { transform: translateX(.5px)    scaleX(1.03); }
  80%  { transform: translateX(.2px)    scaleX(1.01); }
  90%  { transform: translateX(.04px)   scaleX(1); }
  100% { transform: translateX(0)       scaleX(1); }
}
/* 全 App 四种开关标记共用同一套几何(轨 44x26 / 滑块 20 / 行程 18),一并覆盖。 */
.switch-row input[type="checkbox"].sw-liquid-on::after,
.default-check input[type="checkbox"].sw-liquid-on::after,
.income-monthly-switch input[type="checkbox"].sw-liquid-on::after,
input.pill-switch[type="checkbox"].sw-liquid-on::after {
  transform-origin: right center;
  will-change: transform;
  animation: knobLiquidOn 340ms linear;   /* linear:缓动已烘进关键帧,见上 */
}
.switch-row input[type="checkbox"].sw-liquid-off::after,
.default-check input[type="checkbox"].sw-liquid-off::after,
.income-monthly-switch input[type="checkbox"].sw-liquid-off::after,
input.pill-switch[type="checkbox"].sw-liquid-off::after {
  transform-origin: left center;
  will-change: transform;
  animation: knobLiquidOff 340ms linear;
}

/* iOS 的轨道底色是跟着滑块一起过渡的,200ms 偏快会先于滑块到位 —— 对齐到 320ms */
.switch-row input[type="checkbox"],
.default-check input[type="checkbox"],
.income-monthly-switch input[type="checkbox"],
input.pill-switch[type="checkbox"] { transition: background 340ms cubic-bezier(.45, .05, .25, 1); }

@media (prefers-reduced-motion: reduce) {
  .spring-pop,
  [class*="sw-liquid"]::after { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .switch-row input[type="checkbox"]::after,
  [aria-expanded] > svg { transition: none; }
}

.privacy-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 16px;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
.privacy-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 15px;
  background: var(--brand-grad);
  color: #fff;
  flex-shrink: 0;
}
.privacy-icon svg { width: 25px; height: 25px; }
.privacy-card strong {
  display: block;
  font-size: 19px;
  font-weight: 800;
  color: var(--ink-strong);
  letter-spacing: -0.01em;
  margin-bottom: 6px;
}
.privacy-card p {
  font-size: 14px;
  color: var(--muted);
  line-height: 1.55;
}

/* About 页:帮助/条款/隐私 三张卡(圆形彩色图标 + 标题 + 副标题 + chevron) */
.about-links { display: grid; gap: 12px; margin-top: 14px; }
.about-item {
  display: grid; grid-template-columns: 52px 1fr auto; align-items: center; gap: 15px;
  padding: 16px 18px; border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow-sm);
  text-decoration: none; color: var(--ink); text-align: left;
  border: 0; -webkit-appearance: none; appearance: none; font: inherit; width: 100%; cursor: pointer;
  transition: transform var(--dur) var(--ease);
}
.about-item:active { transform: scale(0.99); }
.about-item .ai-ic { width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center; }
.about-item .ai-ic svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ai-ic-gray   { background: var(--soft); color: var(--muted-strong); }
.ai-ic-blue   { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.ai-ic-purple { background: rgba(139, 92, 246, 0.13); color: #8b5cf6; }
.ai-ic-red    { background: rgba(239, 68, 68, 0.12); color: #ef4444; }
.about-item .ai-text { min-width: 0; }
.about-item .ai-text b { display: block; font-size: 17px; font-weight: 800; letter-spacing: -0.01em; }
.about-item .ai-text small { display: block; margin-top: 3px; font-size: 13px; color: var(--muted); line-height: 1.35; }
.about-item .ai-chev { width: 20px; height: 20px; flex: none; color: var(--muted); fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.about-foot { text-align: center; margin-top: 24px; display: grid; gap: 5px; }
.about-foot p { margin: 0; font-size: 13px; color: var(--muted); }
.about-link { font-size: 13px; font-weight: 700; color: var(--brand-2); text-decoration: none; }
/* 文档子面板(帮助/条款/隐私):内嵌对应页面,页面内部滚动,不跳出 App */
/* 标题已由 App 顶栏(drill 头)显示;面板内的标题仅作 title 取值用,视觉隐藏 */
.doc-head { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.doc-frame { display: block; width: 100%; height: calc(100dvh - 132px); min-height: 360px; border: 0; border-radius: var(--radius); background: var(--soft); box-shadow: var(--shadow-sm); }

.reset-button {
  width: 100%;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--danger);
  font-weight: 700;
}
.reset-button:hover { background: var(--danger-soft); }

.usage-copy { font-size: 12px; color: var(--muted); margin-top: 4px; }

/* ── 12. Forms ─────────────────────────────────────────────────── */
.finance-form { display: grid; gap: 10px; }
/* Two fields side by side (e.g. payment day + contract length). */
.form-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: end; }
.form-row-2 > label { display: grid; gap: 6px; min-width: 0; }
#fixedCostEndDateRow[hidden] { display: none; }

/* Income: 每月固定 toggle on the left, Save on the right. */
.income-save-row { display: flex; align-items: flex-end; gap: 12px; margin-top: 2px; }
.income-monthly-switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 auto;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-strong);
}
.income-monthly-switch input[type="checkbox"],
input.pill-switch[type="checkbox"],
.default-check input[type="checkbox"] {
  appearance: none;
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 26px;
  border-radius: var(--radius-pill);
  background: var(--line-strong);
  cursor: pointer;
  transition: background var(--dur) var(--ease);
}
.income-monthly-switch input[type="checkbox"]::after,
input.pill-switch[type="checkbox"]::after,
.default-check input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  transition: transform var(--dur) var(--ease);
}
.income-monthly-switch input[type="checkbox"]:checked,
input.pill-switch[type="checkbox"]:checked,
.default-check input[type="checkbox"]:checked { background: var(--brand-grad); }
.income-monthly-switch input[type="checkbox"]:checked::after,
input.pill-switch[type="checkbox"]:checked::after,
.default-check input[type="checkbox"]:checked::after { transform: translateX(18px); }
/* 行内开关:开关在左、文字在右(参照「默认」勾选的排列),在网格单元里垂直居中 */
.form-row-2 > label.toggle-inline {
  display: flex;
  align-items: center;
  gap: 10px;
  align-self: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-strong);
  cursor: pointer;
}
.income-save-btn {
  flex: 0 0 auto;
  height: 46px;
  padding: 0 28px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--brand-grad);
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  cursor: pointer;
}
.income-save-btn:active { transform: scale(0.98); }
/* 取消按钮在收入保存行里与保存等高 */
.income-save-row .secondary-button { flex: 0 0 auto; height: 46px; padding: 0 22px; border-radius: var(--radius-md); font-size: 15px; font-weight: 700; cursor: pointer; }
.finance-form label {
  display: grid;
  gap: 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.finance-form input,
.finance-form select {
  height: 42px;
  width: 100%;
  min-width: 0;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--soft);
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  text-transform: none;
  transition: background var(--dur) var(--ease);
}
.finance-form input:focus,
.finance-form select:focus,
.finance-form textarea:focus {
  outline: none;
  border: 0;
  box-shadow: none;
  background: var(--hover);
}
/* ── 图标 tile 表单(Pemasukan 式):每行 = 彩色图标 tile + 标签 + 控件 ── */
.finance-form--tiles { gap: 16px; }
/* 校验失败:抖动 + 红边,直接指出是哪个框 */
@keyframes ff-shake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-6px); }
  30% { transform: translateX(6px); }
  45% { transform: translateX(-5px); }
  60% { transform: translateX(4px); }
  75% { transform: translateX(-2px); }
}
.ff-shake { animation: ff-shake 0.5s ease; }
.ff-shake input:not([type="checkbox"]),
.ff-shake select,
.ff-shake .amount-field {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.16) !important;
}
/* 「分期付款」分组盒(Boleh beli apa? 弹窗):勾选头 + 展开的 tenor/月供 字段 */
.ff-install-group { border: 1px solid var(--line); border-radius: 16px; padding: 14px; background: var(--soft); display: grid; gap: 14px; }
/* 用 .ff-install-group 前缀提高特异度,压过 .finance-form label{display:grid},否则勾选会竖排 */
.ff-install-group .ff-install-toggle { display: flex; align-items: center; gap: 12px; cursor: pointer; margin: 0; justify-content: space-between; }
.ff-install-toggle .pill-switch { flex: none; margin: 0; }
.ff-install-text { display: grid; gap: 3px; flex: 1; min-width: 0; }
.ff-install-text b { font-size: 13px; font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase; color: var(--ink); }
.ff-install-text small { font-size: 12px; line-height: 1.35; color: var(--muted); }
.ff-install-group .ff-rowgroup[hidden] { display: none; }
.ff-install-group .ff-rowgroup { display: grid; gap: 14px; }
.finance-form--tiles > label,
.finance-form--tiles .ff-row {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  text-transform: none;
  letter-spacing: normal;
}
.finance-form--tiles > label[hidden],
.finance-form--tiles .ff-row[hidden] { display: none; }
.ff-ic {
  flex: none;
  width: 46px;
  height: 46px;       /* 小正方形,不随行高拉伸 */
  align-self: center;
  border-radius: 14px;
  display: grid;
  place-items: center;
}
.ff-ic svg { width: 23px; height: 23px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ff-ic.ff-ic-text { font-size: 19px; font-weight: 800; letter-spacing: -0.02em; }
.ff-body { flex: 1; min-width: 0; display: grid; gap: 7px; }
.ff-lab { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
/* "Default" 标记上移到字段标签行右侧,与灰标签同样式;开关留在下拉行右侧 */
.ff-lab-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ff-default-tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); cursor: pointer; white-space: nowrap; }
/* 删除自定义收入种类:仅选中自定义种类时显示,小号红字,推到 Default 标签左侧 */
.ff-kind-del { margin-left: auto; border: 0; background: transparent; color: var(--danger, #dc2626); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; cursor: pointer; padding: 0; white-space: nowrap; }
.ff-kind-del[hidden] { display: none; }
.finance-form--tiles input:not([type="checkbox"]),
.finance-form--tiles select { height: 42px; border-radius: 14px; font-size: 15px; }
/* 整组(可隐藏的一段) */
.ff-rowgroup { display: grid; gap: 16px; }
.ff-rowgroup[hidden] { display: none; }
/* 开关行:图标 + 标签 + 右侧 pill 开关(如 TANPA BATAS) */
/* 开关行(TANPA BATAS / 每月固定)也包进带边框的盒子,图标在盒子里(同输入框) */
/* 开关行上方的小标题:沿用字段标签灰色样式,负 margin 把与开关的间距收到 7px
   (表单 gap 16px - 9px),让节奏和上面带标签的字段一致。 */
.finance-form--tiles > .ff-switch-toplab { margin-bottom: -9px; }
.finance-form--tiles > label.ff-row--switch {
  display: flex;
  align-items: stretch;
  gap: 0;
  min-height: 46px;
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
}
.finance-form--tiles > label.ff-row--switch > .ff-ic {
  flex: none;
  width: 44px;
  align-self: stretch;          /* 充满盒子高度 */
  height: auto;
  border-radius: 0;
  border-right: 1px solid var(--line);
}
.finance-form--tiles > label.ff-row--switch > .ff-body {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 2px;
  padding-left: 12px;
}
.finance-form--tiles > label.ff-row--switch .ff-lab {
  font-size: 14px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
}
.ff-switch { flex: none; align-self: center; margin-left: auto; margin-right: 12px; }
/* 固定费:TGL BAYAR + MASA BERLAKU 并排(半宽开关框自成一列) */
.fc-validity-col { display: grid; gap: 7px; min-width: 0; }
.fc-validity-col > .ff-lab { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.fc-validity-col > label.ff-row--switch { display: flex; align-items: stretch; gap: 0; min-height: 42px; height: 42px; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; cursor: pointer; }
.fc-validity-col > label.ff-row--switch > .ff-ic { flex: none; width: 44px; align-self: stretch; height: auto; border-radius: 0; border-right: 1px solid var(--line); }
.fc-validity-col > label.ff-row--switch > .ff-ic svg { width: 23px; height: 23px; }
.fc-validity-col .ff-row--switch > .ff-body { flex: 1; min-width: 0; display: flex; align-items: center; padding-left: 7px; }
.fc-validity-col .ff-row--switch .ff-lab { font-size: 15px; font-weight: 500; text-transform: none; letter-spacing: normal; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-validity-col .ff-switch { flex: none; align-self: center; margin-left: auto; margin-right: 5px; transform: scale(0.8); }
/* 图1:TGL BAYAR 的「11」放大到和上面输入框(Internet/Rp)一致的 15px,不再比它们小
   (.form-row-2.fc-validity-row 双类叠加,盖过后面 .form-row-2 的 13.5px 规则) */
.finance-form--tiles .form-row-2.fc-validity-row > label .ff-body input:not([type="checkbox"]) { font-size: 15px; }
/* 语义色 tile(固定语义色,不随主题切换) */
/* 不透明实色浅底(图标 tile 叠在灰输入框上,半透明会透出灰色发浑) */
.ff-ic-orange { background: #ffe7d9; color: #ff5722; }
.ff-ic-red    { background: #fde3e3; color: #ef4444; }
.ff-ic-blue   { background: #e4edfd; color: #3b82f6; }
.ff-ic-purple { background: #ece6fd; color: #8b5cf6; }
.ff-ic-green  { background: #ddf3ea; color: #10a35e; }
/* 暗色主题:浅色底在深底上显灰 → 换半透明彩底 + 提亮图标色 */
:root[data-theme="dark"] .ff-ic-orange { background: rgba(255,87,34,.22);  color: #ff8a65; }
:root[data-theme="dark"] .ff-ic-red    { background: rgba(239,68,68,.22);  color: #f87171; }
:root[data-theme="dark"] .ff-ic-blue   { background: rgba(59,130,246,.24); color: #82b4fb; }
:root[data-theme="dark"] .ff-ic-purple { background: rgba(139,92,246,.26); color: #b7a5f9; }
:root[data-theme="dark"] .ff-ic-green  { background: rgba(16,163,94,.24);  color: #4ade80; }
/* ── 图标移进输入框内(前置图标) ───────────────────────────────────────────
   标签在上方整行,彩色图标贴输入框左内侧,输入文字向右让位。
   不动:开关行(ff-row--switch,图标仍作左侧 tile)、default-check 复选框。 */
.finance-form--tiles > label:not(.ff-row--switch),
.finance-form--tiles .ff-rowgroup > label {
  display: block;
  position: relative;
}
.finance-form--tiles > label:not(.ff-row--switch) > .ff-body,
.finance-form--tiles .ff-rowgroup > label > .ff-body {
  display: grid;
  gap: 7px;
}
.finance-form--tiles > label:not(.ff-row--switch) > .ff-ic,
.finance-form--tiles .ff-rowgroup > label > .ff-ic {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 44px;
  /* ⚠️ 这个高度必须和**同一处字段的实际高度**一致,否则图标上沿会探出字段圆角,
     看着像颜色溢出框格。各弹窗字段高度不同的,要在该弹窗的规则里一并对齐
     (例:#pendingConfirmModal 是 46px,连 .csel-trigger 也要跟着设 46px)。 */
  height: 42px;                  /* = 输入框高,与边框对齐 */
  border-radius: 14px 0 0 14px;  /* 贴输入框左侧圆角 */
  border-right: 1px solid var(--line);
  z-index: 2;                    /* 盖在输入框上(金额行 .amount-field 是 relative,否则白底会遮住图标) */
  pointer-events: none;          /* 装饰性:点击穿透到输入框 */
}
.finance-form--tiles > label:not(.ff-row--switch) > .ff-ic svg,
.finance-form--tiles .ff-rowgroup > label > .ff-ic svg { width: 23px; height: 23px; }
.finance-form--tiles > label:not(.ff-row--switch) > .ff-ic.ff-ic-text,
.finance-form--tiles .ff-rowgroup > label > .ff-ic.ff-ic-text { font-size: 17px; }
.finance-form--tiles > label:not(.ff-row--switch) .ff-body input:not([type="checkbox"]),
.finance-form--tiles > label:not(.ff-row--switch) .ff-body select,
.finance-form--tiles .ff-rowgroup > label .ff-body input:not([type="checkbox"]),
.finance-form--tiles .ff-rowgroup > label .ff-body select {
  padding-left: 58px;            /* 给前置图标留位 */
}
/* 仅分期付款(BAYAR DENGAN CICILAN)这一块:输入框白底、无描边(focus 也不变灰蓝),
   左侧彩色图标 tile 去掉分隔线。其他 tile 表单保持原灰底,不受影响。 */
.finance-form--tiles .ff-install-group .ff-rowgroup > label .ff-body input:not([type="checkbox"]),
.finance-form--tiles .ff-install-group .ff-rowgroup > label .ff-body select {
  background: var(--card);
}
.finance-form--tiles .ff-install-group .ff-rowgroup > label .ff-body input:not([type="checkbox"]):focus,
.finance-form--tiles .ff-install-group .ff-rowgroup > label .ff-body select:focus {
  background: var(--card);
}
.finance-form--tiles .ff-install-group .ff-rowgroup > label > .ff-ic {
  border-right: 0;
}
/* 两列行(预期收入的"天数 / 日期")也用框内图标 */
.finance-form--tiles .form-row-2 > label { display: block; position: relative; }
.finance-form--tiles .form-row-2 > label > .ff-body { display: grid; gap: 7px; }
.finance-form--tiles .form-row-2 > label > .ff-ic {
  position: absolute; left: 0; bottom: 0; width: 44px; height: 42px;
  border-radius: 14px 0 0 14px; border-right: 1px solid var(--line);
  z-index: 2; pointer-events: none;
}
.finance-form--tiles .form-row-2 > label > .ff-ic svg { width: 23px; height: 23px; }
.finance-form--tiles .form-row-2 > label .ff-body input:not([type="checkbox"]),
.finance-form--tiles .form-row-2 > label .ff-body select { padding-left: 52px; padding-right: 6px; font-size: 13.5px; }
.finance-form .check-row {
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: nowrap;
  display: flex;
  gap: 8px;
  font-size: 12px;
}
.finance-form .check-row { font-size: 13px; }
.finance-form .check-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  border: 2px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  cursor: pointer;
  position: relative;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.finance-form .check-row input[type="checkbox"]:checked {
  background: var(--brand-2);
  border-color: var(--brand-2);
}
.finance-form .check-row input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.income-date-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: end;
}
.income-date-row > label { min-width: 0; }
.income-date-row > label > input[type="date"] { width: 100%; min-width: 0; box-sizing: border-box; }
.income-date-row .check-row { padding-bottom: 12px; }
/* 只读字段(如「已还月数」——由还款记录自动算出,手改没有意义)。
   ⚠️ 原来只有 7% 的灰底:在 tiles 表单里输入框本来就是 --soft 浅灰,叠上去几乎看不出
   差别,用户点进去才发现打不了字。现在整行一起降调:图标格转灰 + 值转灰 + 底色压深 +
   右侧一把小锁,不点也知道这格是算出来的。 */
.readonly-field input[readonly] {
  background: rgba(127, 127, 127, 0.16);
  color: var(--muted);
  -webkit-text-fill-color: var(--muted);
  cursor: default;
  pointer-events: none;
  /* 小锁(灰,固定色 —— 背景图取不到 currentColor) */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa4b2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='4.5' y='10.5' width='15' height='10' rx='2.5'/><path d='M8 10.5V7.5a4 4 0 0 1 8 0v3'/></svg>");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 15px 15px;
  padding-right: 32px;
}
.finance-form--tiles .readonly-field > .ff-ic {
  background: rgba(127, 127, 127, 0.12);
  color: var(--muted);
}
.readonly-field .ff-lab { color: var(--muted); opacity: .75; }
.field-hint { display: block; margin-top: 5px; font-size: 11px; color: var(--muted); }
.form-actions {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  margin-top: 4px;
}
/* 弹窗取消/删除统一纯图标(✕ / 🗑):文字隐去仍留作读屏可访问名,grid 让主按钮自动撑满。
   复用 iconrow 同款 mask SVG。 */
.icon-x, .icon-trash {
  width: 48px !important; min-width: 48px; min-height: 44px; padding: 0 !important;
  font-size: 0 !important; line-height: 0 !important;
  display: inline-flex; align-items: center; justify-content: center; gap: 0;
}
.icon-x::before, .icon-trash::before {
  content: ""; flex: none; width: 20px; height: 20px; background: currentColor;
  -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat;
}
.icon-x::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E");
}
.icon-trash::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E");
}
.form-actions.single { grid-template-columns: 1fr; }
/* 实体编辑表单:取消(次要)在左窄,保存(主)在右宽 */
/* 弹窗内(如流水详情)form-actions--edit:次要(删除)左窄 + 主按钮(关闭)右宽 */
.form-actions--edit { grid-template-columns: auto 1fr; }
/* 实体编辑表单(在 <form> 内):保存在左且宽,取消在右且窄(用 order 调位,不动 DOM) */
form .form-actions--edit { display: flex; gap: 8px; grid-template-columns: none; }
form .form-actions--edit > button[type="submit"] { order: -1; flex: 1 1 auto; }
form .form-actions--edit > .secondary-button { flex: 0 0 auto; }
/* 报销勾选独占一行(在按钮行上方),替掉与按钮同排的内联式 */
.reimburse-row { display: flex; align-items: center; gap: 11px; margin: 4px 0 2px; font-size: 12.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--ink); cursor: pointer; }
.reimburse-row input[type="checkbox"] { width: 22px; height: 22px; flex: none; accent-color: var(--brand-2); cursor: pointer; }
/* Reimburse 改到表单头部:右侧药丸开关 + (i) 说明,与标题同排 */
.modal-heading-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* 窄屏(如 Z Flip):标题可收缩省略,让右侧 Reimburse pill 永远放得下、不被切 */
.modal-heading-row h3 { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 单端登录弹窗:居中图标 + 标题 + 说明 + 上下两个全宽按钮 */
.session-modal { max-width: 350px; text-align: center; }
.session-modal-icon {
  width: 56px; height: 56px; margin: 2px auto 2px;
  border-radius: 16px; display: grid; place-items: center;
  background: var(--brand-soft, rgba(255, 106, 43, 0.12)); color: var(--brand-2);
}
.session-modal .modal-heading { gap: 6px; }
.session-modal .modal-heading h3 { font-size: 19px; margin: 0; }
.session-modal .auth-gate-copy { font-size: 14px; line-height: 1.5; color: var(--muted-strong); margin: 0; }
.session-modal-actions { grid-template-columns: 1fr; gap: 9px; margin-top: 12px; }
.session-modal-actions > button { width: 100%; }
#sessionModalConfirm { background: var(--brand-2); color: #fff; border: 0; box-shadow: none; }
#sessionModalConfirm:hover { filter: brightness(0.96); }
.reimburse-toggle-wrap { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.reimburse-pill {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 12px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--brand-2);     /* 显眼:橙边 + 浅橙底 + 橙字,避免被忽略 */
  background: var(--brand-soft);
  color: var(--brand-2);
  font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em;
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.reimburse-pill input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; pointer-events: none; }
.reimburse-pill-check {
  width: 16px; height: 16px; flex: none;
  border-radius: 50%; border: 1.5px solid currentColor;
  display: grid; place-items: center;
}
.reimburse-pill-check::before {
  content: ""; width: 9px; height: 9px; background: currentColor; opacity: 0;
  transition: opacity var(--dur) var(--ease);
  -webkit-mask: center/contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
  mask: center/contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E");
}
.reimburse-pill.is-on { background: var(--brand-grad); color: #fff; border-color: var(--brand-2); }
.reimburse-pill.is-on .reimburse-pill-check::before { opacity: 1; }
/* :has 单独成组,旧 WebView 不支持时不会拖累上面的 .is-on 规则 */
.reimburse-pill:has(input:checked) { background: var(--brand-grad); color: #fff; border-color: var(--brand-2); }
.reimburse-pill:has(input:checked) .reimburse-pill-check::before { opacity: 1; }
.reimburse-info {
  width: 24px; height: 24px; flex: none;
  border-radius: 50%; border: 1px solid var(--line);
  background: transparent; color: var(--muted);
  font-size: 13px; font-weight: 800; font-style: italic; font-family: Georgia, "Times New Roman", serif;
  line-height: 1; cursor: pointer; display: grid; place-items: center;
}
.reimburse-info:active { background: var(--soft); }
/* 收入 Catat 表单:保存键左侧的报销开关 */
.income-save-actions { display: flex; align-items: center; gap: 10px; }
.income-save-actions > button[type="submit"] { flex: 1; }
/* 在 .finance-form 内,需压过 .finance-form label{display:grid},否则勾+文字会竖排 */
.income-save-actions .reimburse-pill { display: inline-flex; flex: none; height: 44px; min-height: 44px; padding: 0 16px; border-radius: var(--radius-sm); }
/* 实体编辑表单(贷款/固定费用/账户):保存✓ + 取消✕ + 删除🗑 收进一行,图标式 */
.form-actions.form-actions--iconrow { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
.form-actions.form-actions--iconrow > button { height: 52px; min-height: 52px; border-radius: 14px; padding: 0; }
/* 保存:主题色实心、最宽,✓ 图标 + 文字 */
.form-actions.form-actions--iconrow > button[type="submit"] { order: -1; flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; gap: 9px; background: var(--accent-grad); color: #fff; font-size: 15px; font-weight: 800; }
/* 取消 / 删除:仅图标 */
.form-actions.form-actions--iconrow > .secondary-button { order: 0; flex: 0 0 56px; font-size: 0; line-height: 0; display: inline-flex; align-items: center; justify-content: center; }
/* 删除键(图1 标准):独占下方一整行、居中、无边框红色垃圾桶 */
.form-actions.form-actions--iconrow > .danger-link { order: 2; flex: 0 0 100%; width: auto; height: auto; margin: 2px auto 0; padding: 8px; border: 0; border-radius: 12px; background: transparent; color: var(--muted); display: inline-flex; align-items: center; justify-content: center; font-size: 0; line-height: 0; }
.form-actions.form-actions--iconrow > .danger-link::before { width: 23px; height: 23px; }
.form-actions.form-actions--iconrow > .danger-link[hidden] { display: none; }
.form-actions.form-actions--iconrow > button::before { content: ""; flex: none; width: 21px; height: 21px; background: currentColor; -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat; }
/* Simpan 按钮不要 ✓ 图标(用户嫌多余,Simpan 本身已表意) */
.form-actions.form-actions--iconrow > button[type="submit"]::before { content: none; }
.form-actions.form-actions--iconrow > .secondary-button::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E"); }
.form-actions.form-actions--iconrow > .danger-link::before { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E"); }
/* 垃圾桶与「保存」并排(垃圾桶在左)。--iconrow 是垃圾桶独占下方一行、居中在保存
   正下方 —— 手指够过去容易误触成删除。这个变体把它挪到左侧,和保存平行,误触面小得多。
   图标遮罩直接复用下面 --iconrow 的那条(选择器带 .danger-link::before,两边都命中)。 */
.form-actions.form-actions--saveleft {
  display: flex; gap: 10px; align-items: stretch;
}
.form-actions.form-actions--saveleft > button {
  height: 52px; min-height: 52px; border-radius: 14px; padding: 0;
}
.form-actions.form-actions--saveleft > button[type="submit"] {
  flex: 1 1 auto;             /* 保存占满剩余宽度,仍是主动作 */
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-grad); color: #fff; font-size: 15px; font-weight: 800;
}
.form-actions.form-actions--saveleft > .danger-link {
  flex: 0 0 56px;             /* 固定窄条,只放垃圾桶图标 */
  /* ⚠️ margin:0 必须写 —— 基础 .danger-link 带 margin-top:8px(它原本是独占一行的版式),
     不清掉的话垃圾桶会比「保存」低 8px,并排就不齐(实测就是差这 8px)。 */
  margin: 0;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0; line-height: 0;
}
.form-actions.form-actions--saveleft > .danger-link::before {
  content: ""; flex: none; width: 22px; height: 22px;
  background: currentColor; -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6'/%3E%3C/svg%3E");
}
.form-actions.form-actions--saveleft > .danger-link[hidden] { display: none; }

/* form-actions 外的整行次要动作(已还清/提前结束) */
.form-block-btn { width: 100%; height: 44px; margin-top: 8px; border-radius: var(--radius-sm); font-size: 14px; font-weight: 700; cursor: pointer; }
/* 报销勾选与 保存/取消 同排(保存不再占满) */
.form-actions--reimburse { display: flex; align-items: center; gap: 8px; grid-template-columns: none; }
.form-actions--reimburse .reimburse-inline { display: flex; align-items: center; gap: 6px; margin-right: auto; font-size: 12px; color: var(--ink); cursor: pointer; white-space: nowrap; }
.form-actions--reimburse .reimburse-inline input[type="checkbox"] { accent-color: var(--brand); width: 18px; height: 18px; flex: none; }
.form-actions--reimburse button { flex: 0 0 auto; padding: 0 22px; }
/* 想买判断弹窗:分期勾选 + 展开的期数/月供 */
#affordModalForm .checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink); cursor: pointer; margin: 2px 0; }
#affordModalForm .checkbox-row input[type="checkbox"] { accent-color: var(--brand); width: 18px; height: 18px; flex: none; }
.installment-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 12px; border-radius: 12px; background: var(--surface-2, rgba(0,0,0,0.03)); }
.installment-fields[hidden] { display: none; }
.ai-consent-actions {
  grid-template-columns: 1fr 1fr;   /* Pakai AI(左) · Pakai robot(右) 左右等宽 */
  gap: 10px;
}
.ai-consent-actions button { width: 100%; }
.form-actions button {
  height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--brand-grad);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.form-actions button:active { transform: scale(0.97); }
/* 去掉「点击发亮」光环:移动端 tap 会触发 :hover 让按钮发光,显得廉价。
   :active 的轻微缩放保留作为按压反馈。 */
.secondary-button {
  background: var(--card) !important;
  color: var(--ink) !important;
  border: 1px solid var(--line) !important;
}

.settings-card { display: grid; gap: 12px; padding: 16px; }
/* ── Umum 设置页:卡片 + 彩色图标块(参照图)──────────────────── */
/* 仅在 active 时用 grid —— 否则 display:grid 会盖过 .content-panel{display:none},
   导致 Umum 面板常驻显示、串进 Tampilan 等其他设置页(菜单错乱根因) */
.settings-general { grid-template-columns: minmax(0, 1fr); gap: 12px; }
.content-panel.settings-general.active { display: grid; }
.settings-general > * { min-width: 0; }
.set-card { padding: 14px 16px; min-width: 0; grid-template-columns: minmax(0, 1fr); }
.set-row { display: flex; align-items: center; gap: 13px; min-width: 0; }
.set-row .set-ic { flex: none; width: 44px; height: 44px; border-radius: 13px; background: var(--brand-soft); color: var(--brand-2); display: grid; place-items: center; }
.set-row .set-ic svg { width: 23px; height: 23px; }
.set-ic.set-ic-text { font-size: 15px; font-weight: 800; letter-spacing: -0.02em; }
/* Umum 各项语义色图标 tile(参照图:蓝地球/绿钞票/紫时钟) */
.set-row .set-ic-blue { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.set-row .set-ic-green { background: rgba(16, 185, 129, 0.14); color: #10a35e; }
.set-row .set-ic-purple { background: rgba(139, 92, 246, 0.14); color: #8b5cf6; }
.set-text { flex: 1; min-width: 0; display: grid; gap: 2px; }
.set-text > strong { font-size: 15.5px; font-weight: 800; color: var(--ink-strong, var(--ink)); }
.set-text > small { font-size: 12.5px; color: var(--muted); line-height: 1.4; }
.set-example { justify-self: start; margin-top: 5px; padding: 3px 9px; border-radius: 8px; background: var(--soft); font-size: 11.5px; font-weight: 700; color: var(--muted-strong); font-feature-settings: "tnum", "lnum"; }
.set-row .language-switch { flex: none; }
.set-divider { height: 1px; background: var(--line); margin: 13px 0; }
.set-group-head { display: flex; align-items: center; gap: 8px; margin-bottom: 13px; color: var(--brand-2); }
.set-group-head .set-ghead-ic { display: grid; place-items: center; }
.set-group-head .set-ghead-ic svg { width: 18px; height: 18px; }
.set-group-head > span:last-child { font-size: 13.5px; font-weight: 800; letter-spacing: 0.01em; }
.set-row--toggle { cursor: pointer; }
.set-select { flex: 0 1 auto; min-width: 0; max-width: 56%; height: 46px; border: 0; -webkit-appearance: none; appearance: none; border-radius: var(--radius-md); background: var(--soft) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238a8f98' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 14px center; color: var(--ink); font-size: 13.5px; font-weight: 700; padding: 0 40px 0 18px; text-overflow: ellipsis; }
.set-select--lang { flex: none; width: auto; min-width: 88px; max-width: none; font-weight: 800; }
/* 货币/时区:下拉太宽会挤窄标题,改为整行落到标签下方 */
.set-row--select { flex-wrap: wrap; }
.set-row--select .set-text { flex: 1 1 auto; }
.set-row--select .set-select { flex: 1 1 100%; max-width: 100%; margin-top: 12px; }
.set-now { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 20px; }
.set-now-item { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 700; color: var(--ink); }
.set-now-item:last-child { margin-left: auto; }
.set-now-item svg { width: 17px; height: 17px; color: var(--brand-2); flex: none; }
.settings-info { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px; border-radius: var(--radius); background: var(--brand-soft); }
.settings-info .si-ic { flex: none; color: var(--brand-2); margin-top: 1px; }
.settings-info .si-ic svg { width: 22px; height: 22px; }
.settings-info p { margin: 0; font-size: 12.5px; color: var(--muted-strong); line-height: 1.45; }
/* toggle 复用现有外观(.switch-row),开=主题色 */
.set-switch { appearance: none; position: relative; flex: none; width: 44px; height: 26px; border-radius: var(--radius-pill); background: var(--line-strong); cursor: pointer; transition: background var(--dur) var(--ease); }
.set-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transition: transform var(--dur) var(--ease); }
.set-switch:checked { background: var(--accent-grad); }
.set-switch:checked::after { transform: translateX(18px); }
.flat-card { box-shadow: none; }

/* ── 13. Chat view ─────────────────────────────────────────────── */
#chatView { gap: 0; }
.messages {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 12px 18px;
  overflow-y: auto;
  min-height: 0;
}
/* Bottom-align messages when few (chat feel) but stay scrollable when many:
   the auto top-margin collapses once content overflows, so the top is reachable.
   (The old `display:grid; align-content:end` clipped the top un-scrollably.) */
.messages > :first-child { margin-top: auto; }
.message {
  display: grid;
  gap: 6px;
}
.message.ai {
  /* avatar + bubble, hugging the LEFT. align-self:start + width:max-content stop
     the flex parent from stretching/centering the row; margin-right:auto throws all
     leftover space to the right so the block can never drift right. Center the
     avatar against the bubble so a tall reply doesn't leave a big empty block. */
  grid-template-columns: 70px auto;
  align-items: center;
  gap: 8px;
  justify-content: start;
  align-self: start;
  justify-self: start;
  width: max-content;
  max-width: 100%;
  margin-right: auto;
}
.message.user {
  justify-items: end;
}
.message .chat-avatar {
  width: 70px;
  height: 70px;
  font-size: 13px;
  align-self: end;
  box-shadow: none;
  /* Portraits ship on a white studio backdrop — match the chip to white (both
     themes) and drop the border so the subject reads as edge-to-edge. */
  background: #fff;
  border-color: transparent;
}
/* The chat chip is only 32px, but the base emoji/twemoji are sized for the 48px
   settings avatar (32px glyph / 36px image) — bigger than this container, so the
   round mask was clipping the top of the character. Shrink them to fit here. */
.message .chat-avatar .avatar-emoji { font-size: 28px; }
/* The portrait <img> carries BOTH avatar-twemoji (for emoji fallback) and
   avatar-portrait. This 30px shrink is only for a real emoji fallback — exclude
   portraits, or the photo gets squashed to 30px inside the 96px chip. */
.message .chat-avatar .avatar-twemoji:not(.avatar-portrait) { width: 30px; height: 30px; }
.message-body { display: grid; gap: 4px; min-width: 0; }
/* 聊天「加载更早」按钮:居中小胶囊,置于消息列表最上 */
.chat-load-more { display: block; margin: 6px auto 10px; padding: 6px 16px; border: 1px solid var(--line); border-radius: 999px; background: var(--card); color: var(--muted); font-size: 12.5px; font-weight: 700; cursor: pointer; }
.chat-load-more:active { transform: scale(0.97); }
#chatClearNowBtn { width: 100%; margin-top: 12px; height: 46px; border-radius: var(--radius-md); border: 1px solid rgba(239, 68, 68, 0.4); background: rgba(239, 68, 68, 0.08); color: #ef4444; font-size: 14px; font-weight: 800; cursor: pointer; }
#chatClearNowBtn:active { background: rgba(239, 68, 68, 0.16); }
.bubble {
  max-width: 280px;
  padding: 12px 14px;
  border-radius: 18px;
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.45;
  box-shadow: var(--shadow-sm);
  word-wrap: break-word;
  white-space: pre-line; /* honor \n in multi-line replies (e.g. spending stats) */
}
.chat-retry-btn {
  align-self: start;
  margin-top: 6px;
  height: 30px;
  padding: 0 14px;
  border: 1px solid var(--danger);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--danger);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.message.user .bubble {
  background: var(--brand-grad);
  color: #fff;
  border: 0;
  border-bottom-right-radius: 6px;
}
.message.ai .bubble { border-bottom-left-radius: 6px; }
.message-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 10px;
  color: var(--muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.mm-name { min-width: 0; }
.mm-time { flex: none; text-transform: none; letter-spacing: 0; font-weight: 600; color: var(--muted); font-feature-settings: "tnum", "lnum"; }
/* "AI" tag + credits-spent badge on server-AI replies */
.ai-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--brand-soft);
  color: var(--brand-2);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.04em;
  vertical-align: middle;
}
.ai-cost {
  margin-left: 4px;
  font-size: 10px;
  font-weight: 700;
  color: var(--muted);
  vertical-align: middle;
}
.media-bubble { padding: 6px; }
.media-bubble img { border-radius: 12px; max-width: 220px; cursor: zoom-in; }

.insight-card {
  margin-top: 6px;
  padding: 14px;
  border-radius: var(--radius);
  background: var(--card);
  border: 1px solid var(--line);
  display: grid;
  gap: 8px;
  box-shadow: var(--shadow);
}
.insight-card.go { border-color: var(--ok); background: var(--ok-soft); }
.insight-card.hold { border-color: var(--warn); background: var(--warn-soft); }
.insight-card.stop { border-color: var(--danger); background: var(--danger-soft); }
.insight-card .eyebrow { color: inherit; opacity: 0.7; }
.insight-card strong {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-feature-settings: "tnum", "lnum";
}
.reason-list { display: grid; gap: 4px; font-size: 13px; color: var(--ink); }
.reason-list li { padding-left: 14px; position: relative; }
.reason-list li::before {
  content: "";
  position: absolute;
  top: 8px;
  left: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.5;
}

/* 单张白卡,5 列,列间细分隔线(照参照图) */
.quick-actions {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0;
  margin: 6px 14px 4px;
  padding: 13px 2px;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
.quick-actions button {
  position: relative;
  display: grid;
  gap: 8px;
  padding: 2px 4px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--ink);
  font-size: 10.5px;
  font-weight: 600;
  transition: transform var(--dur) var(--ease);
}
.quick-actions button + button::before {
  content: "";
  position: absolute;
  left: 0;
  top: 14%;
  bottom: 14%;
  width: 1px;
  background: var(--line);
}
.quick-actions button span {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin: 0 auto;
}
/* 自带配色的贴图图标:直接显示,不再套渐变圆底 */
.quick-actions button span.qa-ic img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 4px 8px rgba(15, 23, 42, 0.12));
}
.quick-actions button b {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.18;
  text-align: center;
  white-space: normal;       /* 允许换行:两词的标签(Catat Pemasukan)上下排,不再溢出 */
  word-break: keep-all;      /* 不在词内断开,只在词间换行 */
  min-height: 2.36em;        /* 1行/2行标签按钮高度对齐 */
  display: flex;
  align-items: center;
  justify-content: center;
}
.quick-actions button:active { transform: scale(0.95); }

/* ── 14. Composer (chat input) ────────────────────────────────── */
.composer {
  display: block;
  padding: 6px 12px 4px;
  background: transparent;
  position: relative;
}
/* 图片文件输入:定位到相机按钮那一带(左下),让 iOS 原生的「相册/拍照/文件」菜单
   锚在合理位置,而不是像 visually-hidden 那样被丢到屏幕角落乱弹。透明 + 不挡点击,
   实际由 #photoButton 的 .click() 触发。 */
#receiptInput {
  position: absolute;
  left: 12px;
  bottom: 8px;
  width: 48px;
  height: 48px;
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}
/* 长条玻璃浮窗:相机 / 输入 / 麦克 / 发送 全部收进同一条里 */
.composer-bar {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  padding: 5px 6px;
  border-radius: 26px;
  border: 0;
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  backdrop-filter: blur(18px) saturate(160%);
  box-shadow: 0 8px 24px -12px rgba(15, 23, 42, 0.3);
}
:root[data-theme="dark"] .composer-bar { background: rgba(26, 28, 34, 0.62); }
/* 聊天 Pribadi/Usaha 上下文开关(business 解锁才显示) */
.chat-book-toggle { display: flex; gap: 4px; padding: 2px 4px 6px; }
.chat-book-toggle[hidden] { display: none; }
.chat-book-toggle button { flex: 1; height: 28px; border: 1px solid var(--line); border-radius: 999px; background: var(--card); color: var(--muted-strong); font-size: 12px; font-weight: 700; cursor: pointer; }
.chat-book-toggle button.on { background: var(--brand-grad); color: #fff; border-color: transparent; }
.phone-app:not([data-active-view="chat"]) .composer { display: none; }
/* composer-bar 内的输入控件行(相机/输入/发送) */
.composer-row { display: flex; align-items: center; gap: 4px; }
/* 附件缩略图条:包在 composer-bar 内,排在输入行上方 */
.receipt-preview {
  padding: 8px 8px 6px;
}
.receipt-preview[hidden] { display: none; }
/* GPT 式缩略图条:多张缩略图,每张右上角 × 单独删 */
.receipt-thumbs { display: flex; flex-wrap: wrap; gap: 12px; }
.receipt-thumb { position: relative; width: 60px; height: 60px; flex: 0 0 auto; }
.receipt-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; border: 1px solid var(--line); display: block; cursor: pointer; }
/* 点缩略图放大的预览浮层(点任意处关闭) */
.img-preview-overlay { position: fixed; inset: 0; z-index: 2147483640; display: flex; align-items: center; justify-content: center; padding: 24px; background: rgba(0, 0, 0, 0.82); cursor: zoom-out; }
.img-preview-overlay[hidden] { display: none; }
.img-preview-overlay img { max-width: 96%; max-height: 92%; object-fit: contain; border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); }
.receipt-thumb-x {
  position: absolute; top: -7px; right: -7px;
  width: 22px; height: 22px; padding: 0;
  border: 2px solid var(--card); border-radius: 50%;
  background: var(--ink); color: #fff;
  font-size: 13px; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
}
.receipt-thumb-x:active { transform: scale(0.9); }

.input-wrap { position: relative; min-width: 0; flex: 1; }
.composer input[type="text"] {
  width: 100%;
  height: 42px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink);
  padding: 0 42px 0 6px;
  font-size: 14px;
}
.composer input[type="text"]:focus {
  outline: none;
  background: transparent;
  box-shadow: none;
}

.icon-button,
.send-button,
.input-voice {
  display: grid;
  place-items: center;
  border: 0;
  cursor: pointer;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.icon-button {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: transparent;
  color: var(--muted-strong, var(--ink));
}
.icon-button:hover { background: var(--brand-soft); color: var(--brand); }
.icon-button.listening { background: var(--warn-soft); color: var(--warn); }

.send-button {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--accent-grad);
  color: #fff;
  box-shadow: 0 8px 20px -6px rgba(255, 87, 34, 0.6);
}
.send-button:active { transform: scale(0.94); }

.input-voice {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
}
.input-voice:hover { color: var(--brand); background: var(--brand-soft); }
/* 激活态和搜索麦(.ov-search-mic.listening)一致:橙底 + 白图标 + 脉冲 */
.input-voice.listening { background: var(--brand-2, #ff6a2b); color: #fff; animation: ovMicPulse 1.2s ease-in-out infinite; }

.icon-button svg,
.send-button svg,
.input-voice svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── 15. Bottom nav ────────────────────────────────────────────── */
.bottom-nav {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0;
  /* 白底铺满(全宽,大屏小屏都稳):平直顶边(无弧度)+ 上阴影分层 */
  margin: 0;
  padding: 16px calc(6px + env(safe-area-inset-right)) calc(8px + env(safe-area-inset-bottom, 10px)) calc(6px + env(safe-area-inset-left));
  background: var(--card);
  border-radius: 0;
  box-shadow: 0 -6px 22px -12px rgba(15, 23, 42, 0.16);
  overflow: visible;
  /* 下拉刷新时 .app-view 被 transform:translateY 会另起层叠上下文,若底栏是静态元素
     会被内容盖住(透视)。抬进定位层 + z-index 高于内容 → 内容永远在底栏之下。 */
  position: relative;
  z-index: 30;
}
:root[data-theme="dark"] .bottom-nav {
  box-shadow: 0 -6px 22px -10px rgba(0, 0, 0, 0.55);
}
.bottom-nav button {
  position: relative;
  display: grid;
  gap: 4px;
  place-items: center;
  min-height: 50px;
  border: 0;
  background: transparent;
  color: var(--muted-strong);
  font-size: 11px;
  font-weight: 500;
  transition: color var(--dur) var(--ease);
}
.bottom-nav span {
  position: relative;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  transition: background var(--dur) var(--ease);
}
.bottom-nav svg {
  width: 25px;
  height: 25px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* 未选:细描边灰色;选中:图标+标签变主题色 + 标签下方一小条橙色下划线 */
.bottom-nav button.active { color: var(--brand-2); }
/* ── 分段切换器:共享滑动药丸 ──────────────────────────────────
   UANG/TAGIHAN、BANK/DOMPET/LAINNYA、KELUAR/MASUK 这十来处原来是每个按钮
   各画各的选中背景,切换时「这块消失那块出现」,没有位移感。
   现在容器里插一个共享药丸(JS: syncSegPill 实测位置),按钮自己的背景压掉。
   和底部导航滑块同一套思路:外层平移 + 内层拉伸,飞行中横向拉长像被拽出的水滴。 */
/* ⚠️ z-index:0 + isolation:isolate 不是装饰,是「选中项没有文字」那个真机 bug 的正解:
   容器必须自己起一个**层叠上下文**,药丸才能用 z-index:-1 落进「负层」——
   负层在绘制顺序里排在「本元素背景」之后、**所有在流内容之前**,于是「药丸盖住文字」
   在结构上不可能发生,不再依赖「药丸 0 / 按钮 1」这种要求按钮必须定位的脆弱平衡。
   (之前靠 0 vs 1:iOS 上药丸因 translate3d 常驻合成层,合成层会画到未提升的按钮文字
   之上,z-index 形同虚设 —— 真机上 7 HARI 整个字消失,浏览器复现不出。) */
.has-seg-pill { position: relative; z-index: 0; isolation: isolate; }
/* top 由 JS 实测按钮位置后写入 —— transform 已经被用来做水平位移了,
   不能再塞 translateY 做垂直居中(同一个属性,后写的会覆盖前面的)。
   ⚠️ 选择器**不能**限定在 .has-seg-pill 之下。syncSegPill 量到宽度为 0(容器还没
   布局)时会摘掉 .has-seg-pill 早退,但药丸节点这时已经 prepend 进 DOM 了 ——
   限定写法会让它连 position:absolute 一起失效,从「脱离流的浮层」掉回「流内子元素」。
   .money-tabs 是 grid-template-columns:1fr 1fr,凭空多一个网格项就把两个按钮各挤后
   一格 → PROFIL 到右上、PENGATURAN 到左下(真机实拍就是这个样子)。
   脱离流是药丸的固有属性,与容器有没有挂 class 无关;摘掉 class 时它 opacity:0
   不可见,定位基准落到哪个祖先都无所谓。 */
.seg-pill {
  position: absolute;
  left: 0;
  border-radius: 999px;
  background: var(--brand-grad, linear-gradient(135deg, #ff8a3d, #ff5722));
  box-shadow: 0 6px 16px -8px var(--brand-2, #ff5722);
  pointer-events: none;
  z-index: -1;              /* 负层:永远在文字之下(见 .has-seg-pill 那段) */
  opacity: 0;
  transform: translateX(0);
  transition: transform 320ms cubic-bezier(.34, 1.3, .5, 1),
              width 320ms cubic-bezier(.34, 1.3, .5, 1),
              opacity 160ms linear;
  /* ⚠️ 不常驻 will-change,transform 也用 2D 的 translateX 而不是 translate3d ——
     两者都会把药丸**永久提升成合成层**,而合成层在 iOS 上会画到未提升的兄弟文字之上。
     will-change 在 z730 已经摘了,真机仍复现 → 剩下的元凶就是 translate3d。
     现在改成 2D:只在过渡进行中临时提升,过渡结束自动降回普通绘制。 */
}
.seg-pill.is-flying { will-change: transform, width; }
/* 按钮必须浮在药丸之上,否则文字被药丸盖住。
   ⚠️ 触发条件是「**药丸存在**」而不是「容器挂了 .has-seg-pill」——
   药丸现在是无条件 position:absolute(见上面那段:这是为了修错位),而在同一个
   层叠上下文里,定位元素画在静态兄弟的**文字之上**。只要出现「药丸可见 + 容器
   恰好没挂 class」这一瞬,选中项的字就整个消失(真机实测:好几处都空了)。
   把条件绑到药丸自身,这类失配就不可能再发生。
   药丸是 prepend 进去的(第一个子元素),所以后继兄弟选择器能覆盖全部按钮。 */
.seg-pill ~ button,
.seg-pill ~ [role="tab"] { position: relative; z-index: 1; }
/* 选中按钮自己的背景/阴影全部让位给药丸,只保留文字颜色 */
.has-seg-pill > button.active,
.has-seg-pill > [role="tab"][aria-selected="true"] {
  background: transparent !important;
  box-shadow: none !important;
}
.seg-pill.no-anim { transition: none; }

/* 新接入的三组:药丸接管背景后,文字颜色要跟着改成白字。
   .lang-seg / .theme-seg 走 .language-switch 的样式,本来就是白字,不用管;
   .report-seg 的选中态原本是「白卡片 + 深色字」,落到橙色药丸上对比度就不行了。 */
.has-seg-pill.report-seg > button.active { color: #fff; font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .seg-pill { transition: opacity 120ms linear; }
}

/* 下划线改由共享滑块 .nav-slider 画(见下),这里不再各画各的 ——
   否则切页时是「这条消失、那条出现」,没有位移感。 */

/* 共享滑块:在按钮之间滑过去。
   外层平移 + 内层拉伸分两层做 —— transform 是单一属性,写在同一层会互相覆盖。
   飞行中内层横向拉长(像被拽出来的水滴),落位时缩回 1,这就是那个「水」的观感。 */
/* ⚠️ 选择器必须带 .bottom-nav 前缀。上面有条为按钮内图标容器写的
   `.bottom-nav span { position: relative; display: grid }`,特异性 (0,1,1)
   压过裸的 `.nav-slider` (0,1,0) —— 滑块会被拉回 relative 参与网格排布,
   把 5 列挤成 6 个,profile 直接被顶到第二行去。 */
.bottom-nav .nav-slider {
  position: absolute;
  display: block;
  /* ⚠️ 不能写死 bottom:6px。导航的 padding-bottom = 8px + env(safe-area-inset-bottom),
     iPhone 上安全区约 34px → 底部有 42px 留白(给 home 指示条)。写死 6px 会让橙条
     掉进这块留白里,离文字底边足足 36px,看着「橙条在很下面」(真机实拍)。
     跟着 padding 公式走 → 橙条恒定落在文字底边下方约 5px,不管有没有 home 指示条。 */
  bottom: calc(3px + env(safe-area-inset-bottom, 10px)); left: 0;
  width: 16px; height: 3px;
  pointer-events: none;
  transform: translate3d(0, 0, 0);
  /* ⚠️ 曲线别用带 overshoot 的 cubic-bezier(.34, 1.32, .5, 1)(药丸那套)。y1=1.32 会让
     位移极度前倾:实测时间走到 19%(64ms)时位移已完成 61%。药丸在窄容器里挪几十 px
     看不出来,但底部导航从 Saya 到 Ringkasan 要横跨 792px —— 头两三帧就扫过 Chat,
     剩下 280ms 在磨最后一点距离,观感就是「Chat 下面闪一下,然后不跟手」(用户实拍逐帧确认)。
     换成常规 ease-in-out:位移均匀铺满整段,长距离才跟得住眼睛。 */
  transition: transform 340ms cubic-bezier(.4, .05, .25, 1);
  will-change: transform;
}
.bottom-nav .nav-slider i {
  display: block; width: 100%; height: 100%;
  border-radius: 2px;
  background: var(--brand-2);
  transform: scaleX(1);
}
/* 飞行途中拉长再缩回。
   ⚠️ 原来是「加 .is-flying → scaleX(2.6),200ms 后摘类 → 靠 transition 缩回」,
   但那条 transition 是 340ms:摘类时只拉到约 2.3,缩回又要再走 340ms,收在 540ms ——
   而外层平移 340ms 就落位了。净效果是**滑块已经停了,那根条还在变形 200ms**,
   跨度越大拉伸越满、越明显(用户实测:1→5 时「卡一下飞过去」)。
   改成一条关键帧:拉长和缩回都包在 340ms 里,与外层平移同起同落,不再依赖定时器。 */
.bottom-nav .nav-slider.is-flying i {
  animation: navSliderStretch 340ms cubic-bezier(.34, 1.32, .5, 1);
  /* 外层虽已提升,但内层自己变 transform 会让那一层每帧重绘(实测 will-change: auto)。
     只在飞行期间提升,不常驻 —— 底栏是全 App 一直在的元素,常驻等于白占显存。 */
  will-change: transform;
}
@keyframes navSliderStretch {
  0%   { transform: scaleX(1); }
  40%  { transform: scaleX(2.6); }
  100% { transform: scaleX(1); }
}
/* 首帧不要从左上角滑过来 —— 初始定位时禁用过渡 */
.bottom-nav .nav-slider.no-anim { transition: none; }
.bottom-nav .nav-slider.no-anim i { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .bottom-nav .nav-slider { transition: none; }
  .bottom-nav .nav-slider.is-flying i { animation: none; }
}
/* 选中:线性图标变主题色 + 描边略加粗(与 mockup 的细线风格一致,不再填充实心) */
.bottom-nav button.active:not(.center-tab) svg { stroke-width: 2.2; }
.bottom-nav .nav-money { display: none; } /* desktop sidebar only */
.header-budget-chat { display: flex; align-items: center; gap: 8px; }
.header-chat-d { display: none; } /* desktop only */
/* 中间 Chat:圆形橙色渐变 FAB + 实心白气泡(始终凸显),标签深色加粗 */
.bottom-nav .center-tab { font-size: 11px; font-weight: 700; color: var(--ink); }
/* 4 个线性 tab 图标:贴图当 mask,跟随 currentColor 变色(未选灰/选中橙) */
.bottom-nav .nav-ico {
  width: 32px; height: 32px;
  background-color: currentColor;
  -webkit-mask: var(--ico) center / contain no-repeat;
  mask: var(--ico) center / contain no-repeat;
}
/* 选中:有封闭区域的图标(Saya/Ringkasan/Keuangan)切到实心填充版;
   无封闭区的(Mutasi)无 --ico-fill,退回轮廓版只让线条变橙 */
.bottom-nav button.active .nav-ico {
  -webkit-mask-image: var(--ico-fill, var(--ico));
  mask-image: var(--ico-fill, var(--ico));
}
/* 中间 Chat:全彩橙球贴图,浮出白条 + drop-shadow 光晕 */
.bottom-nav .center-tab span {
  position: relative; z-index: 2;
  width: 58px; height: 58px;
  margin-top: -14px; /* 抬起但收在 nav 内(配合 padding-top:16),不溢出被祖先圆角裁切 */
  background: none; box-shadow: none; border-radius: 0;
}
.bottom-nav .center-tab .center-tab-img {
  width: 100%; height: 100%; object-fit: contain;
  /* 单层、对称的柔和圆形光晕——避免双层偏移叠出方块/不规则的橙影 */
  filter: drop-shadow(0 3px 9px rgba(255, 96, 36, 0.40));
  /* iOS 长按图片会弹「存图/分享」菜单 → 图标装饰性,禁掉长按 callout + 让点击落到按钮 */
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; pointer-events: none;
}

.nav-badge {
  position: absolute;
  top: -4px;
  right: -10px;
  display: inline-grid;
  min-width: 18px;
  height: 18px;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--danger);
  color: #fff;
  font-size: 10px;
  font-style: normal;
  font-weight: 800;
  padding: 0 5px;
  line-height: 1;
  letter-spacing: 0;
  text-indent: 0;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 2px 6px rgba(239, 68, 68, 0.45);
}

/* ── 16. Device float (preview switch) ────────────────────────── */
.device-float {
  position: fixed;
  right: 16px;
  bottom: calc(100px + env(safe-area-inset-bottom));
  z-index: 40;
  display: grid;
  gap: 6px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-lg);
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  touch-action: none; /* let pointer events drive the drag, not scroll */
  user-select: none;
}
.device-float[hidden] { display: none; }
.device-float-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 8px;
  cursor: grab;
}
.device-float-head:active { cursor: grabbing; }
.device-float-collapse {
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 50%;
  background: var(--soft);
  color: var(--ink);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  display: grid;
  place-items: center;
}
.device-float-collapse:hover { background: var(--line-strong); }
.device-float-tab {
  position: fixed;
  right: 16px;
  bottom: calc(100px + env(safe-area-inset-bottom));
  z-index: 40;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--card);
  color: var(--muted-strong);
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
}
.device-float-tab[hidden] { display: none; }

/* Pull-to-refresh indicator — floats above app-view while user drags down */
.pull-refresh {
  position: fixed;
  left: 50%;
  top: 0;
  width: 36px;
  height: 36px;
  margin-left: -18px;
  /* 落在页眉下方、搜索框上方的空档:与 app-header 同用 max(inset,18) 口径对齐,
     再加载时页面下移 84px 腾更大空间,spinner 居中不压搜索框(见 finish() 的 translateY)。 */
  margin-top: calc(max(env(safe-area-inset-top), 18px) + 62px);
  /* 免费档头顶多了一条原生横幅广告(AdMob 画在 WebView 之上,盖住一切网页内容)——
     不往下让的话下拉刷新的转圈就正好躲在广告后面,用户以为卡住了。
     --ad-banner-h 由 syncAdBanner 实测横幅高度后写入。 */
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--card);
  box-shadow: var(--shadow-md);
  color: var(--brand-2);
  z-index: 35;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-100%) scale(.6) rotate(0deg);
  transition: opacity 200ms var(--ease), transform 280ms cubic-bezier(.2,.8,.2,1);
}
body.has-ad-banner .pull-refresh {
  margin-top: calc(max(env(safe-area-inset-top), 18px) + 62px + var(--ad-banner-h, 60px));
}
.pull-refresh.ready { color: var(--brand-2); }
/* 旋转 spinner(替掉原三点):下拉时随手指转(容器 transform:rotate 由 JS 驱动),
   松手加载时内层 svg 持续旋转。比脉冲点更清晰、有「转起来」的加载感。 */
.pull-refresh .ptr-spinner { display: block; color: var(--brand-2); }
.pull-refresh.loading .ptr-spinner { animation: ptr-spin 700ms linear infinite; }
/* Reusable three-dot loader — used app-wide for loading states. */
.dot-loader { display: inline-flex; gap: 5px; align-items: center; color: var(--brand-2); }
.dot-loader i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  animation: dot-pulse 1.1s ease-in-out infinite;
}
.dot-loader i:nth-child(2) { animation-delay: 0.16s; }
.dot-loader i:nth-child(3) { animation-delay: 0.32s; }
@keyframes dot-pulse {
  0%, 70%, 100% { opacity: 0.3; transform: scale(0.82); }
  35% { opacity: 1; transform: scale(1); }
}
@keyframes ptr-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.device-float-tab svg { width: 18px; height: 18px; }
.device-float-tab:hover { color: var(--brand); }
.device-switch {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
}
.device-switch button {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--muted-strong);
  font-size: 11px;
  font-weight: 700;
  text-transform: none;
}
.device-switch button.active {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}
.device-switch button b { font-size: 13px; line-height: 1; }

/* ── 17. Modals ────────────────────────────────────────────────── */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: 20px calc(16px + env(safe-area-inset-right)) 20px calc(16px + env(safe-area-inset-left));
  background: rgba(15, 23, 42, 0.42);
  /* ⚠️ 这里原来有 backdrop-filter: blur(8px) —— 已删除。
     弹窗内部任何动画(DEFAULT 开关、按钮反馈)都在这个模糊层**内部**,
     每帧都会逼整层重新合成,真机上就是「按钮很卡」的主因。
     叠上背景缩放之后更重。iOS 的 pageSheet 本来也不模糊背景,只压暗 + 缩放。 */
  animation: fadeIn 200ms var(--ease);
}
.modal-backdrop[hidden] { display: none; }
.modal-card {
  display: grid;
  gap: 14px;
  width: min(420px, 100%);
  padding: 22px;
  border-radius: var(--radius-lg);
  background: var(--card);
  box-shadow: var(--shadow-lg);
  /* 窄长屏(如三星 Z Flip)防溢出:限高 + 纵向滚动,横向收住不外溢。dvh 排除系统栏。 */
  max-height: calc(100vh - 40px);
  max-height: calc(100dvh - 40px);
  overflow: hidden auto;
}
/* 入场动画只在真正打开时播一次(见 markModalOpening):不再常驻 .modal-card,
   否则 iOS 原生 <select> 弹层关闭会让 WebKit 重播它 → 整卡诡异重影/滑动。 */
/* ── 弹窗入场 ──────────────────────────────────────────────────
   这里原本有一整套 pageSheet:body.modal-open 驱动背景缩放 + 黑底 + 圆角。
   已全部移除,两个原因:
     · 缩放:探针实测证伪了我「它是 68ms 卡顿元凶」的假设(去掉后仍 66ms),
       但用户两次反馈不喜欢这个观感,所以保持移除 —— 理由是观感不是性能。
     · body.modal-open 这个类本身:加在 <body> 上会让**整个文档**重新做
       选择器匹配。缩放没了之后它只剩三条装饰规则(圆角/黑底/遮罩变淡),
       不值一次全文档样式重算 —— 而这次重算恰好落在开弹窗那一帧上。
   现在只保留卡片自身的放大入场,作用域仅限这张卡片。 */
/* 同样按 10% 等距烘进缓动 + linear —— 原来是 3 个关键帧配前重曲线,
   缓动逐段生效,于是「猛放大一下、爬一会、再猛一下」。
   也不做过冲:0.6% 的缩放过冲在 400px 的卡片上约 2.4px,看得见,但它带来的
   方向反转让收尾发顿。干净地减速到位比「弹一下」更耐看。 */
@keyframes modalZoomIn {
  0%   { opacity: 0;   transform: scale(.92); }
  10%  { opacity: .35; transform: scale(.9304); }
  20%  { opacity: .62; transform: scale(.9472); }
  30%  { opacity: .82; transform: scale(.964); }
  40%  { opacity: .94; transform: scale(.9776); }
  50%  { opacity: 1;   transform: scale(.988); }
  60%  { opacity: 1;   transform: scale(.9944); }
  70%  { opacity: 1;   transform: scale(.9976); }
  80%  { opacity: 1;   transform: scale(.9992); }
  90%  { opacity: 1;   transform: scale(.9998); }
  100% { opacity: 1;   transform: scale(1); }
}
.modal-card.modal-opening { animation: modalZoomIn 340ms linear; }

/* 关闭动画。hidden 已经是 true(语义上就是关了),这里只是让它多画 180ms 演完退场。
   pointer-events:none —— 这 180ms 内它不能再挡住下面的点击。 */
/* ⚠️ 日历必须盖在别的弹窗之上。它和 .modal-backdrop 一样是 z-index:80,同级时靠 DOM
   顺序决胜 —— 而 hoistModalsToBody() 把「原本在 phone-app 里」的弹窗追加到 body 末尾,
   #calendarModal 本来就在 body 下所以留在原地,结果反而排到了 #pendingConfirmModal 前面。
   于是从确认弹窗里点日期,日历开在了它**下面**(用户实拍:关掉弹窗才看见日历)。
   日历永远是「从别的弹窗里唤起」的,给它一个更高的层级,不依赖 DOM 顺序。 */
#calendarModal { z-index: 95; }
.modal-backdrop[hidden].modal-closing {
  /* ⚠️ 必须和打开态一致的 grid + place-items:center。原来写的是 display:flex ——
     关闭那 180ms 里布局模式从 grid 换成 flex,且没设对齐,卡片会**瞬间跳到左上角
     并被纵向拉伸**,再淡出。表现就是「关闭时看到错位的残留」。
     退场动画只该改透明度/缩放,绝不该动布局模式。 */
  /* ⚠️⚠️ 必须 !important。全局有一条兜底 `[hidden] { display: none !important }`,
     而 !important 压过一切 specificity —— 没有它,本规则**从来赢不了**,
     退场动画一次都不会播,弹窗是瞬间消失的(真机表现:关闭时看到后面页面的残留)。
     这套 markModalClosing / 多画 180ms 的机制,在此之前实际上是死代码。 */
  display: grid !important;
  place-items: center;
  pointer-events: none;
  animation: modalFadeOut 280ms ease-in forwards;   /* 180→280:180 太快,观感是「闪一下就没」 */
}
.modal-card.modal-closing {
  animation: modalDropOut 280ms linear forwards;    /* 与上面同步;时长拉长=帧更多=更顺 */
  will-change: transform, opacity;
}
@keyframes modalFadeOut { from { opacity: 1; } to { opacity: 0; } }
/* 退场:入场是「减速放大到位」,退场就该是「加速缩回去」—— 对称才不突兀。
   同样烘进关键帧 + linear(见 modalZoomIn 上方关于逐段缓动的注释)。 */
@keyframes modalDropOut {
  0%   { transform: scale(1);     opacity: 1; }
  20%  { transform: scale(.9955); opacity: .88; }
  40%  { transform: scale(.986);  opacity: .68; }
  60%  { transform: scale(.972);  opacity: .44; }
  80%  { transform: scale(.956);  opacity: .2; }
  100% { transform: scale(.94);   opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  /* 上面那条用了 !important,这里要跟着提权才压得住 */
  .modal-backdrop[hidden].modal-closing,
  .modal-card.modal-closing { animation: none; display: none !important; }
  .phone-app, .app-shell { transition: none; }
}
.modal-heading { display: grid; gap: 4px; }
/* 录入表单:去掉说明性灰副标题(如「Isi nama & nominal, simpan.」),主标题放大更醒目。
   覆盖弹窗(记支出/记收入/能不能买)+ 子页表单(贷款/固定费/预算/收入/账户等)。 */
#quickLogModal .modal-heading > p,
#quickIncomeModal .modal-heading > p,
#affordModal .modal-heading > p,
.receipt-capture-card .modal-heading > p,
.receipt-capture-card .secondary-button,
.content-panel[data-back-target] .section-heading p { display: none !important; }
#quickLogModal .modal-heading h3,
#quickIncomeModal .modal-heading h3,
#affordModal .modal-heading h3,
.receipt-capture-card .modal-heading h3,
.content-panel[data-back-target] .section-heading h3 { font-size: 22px; line-height: 1.25; }
.modal-heading p { font-size: 13px; color: var(--muted); }

/* ── 超窄单屏(三星 Z Flip 外屏等,≤340px)加固:固定宽度的元素会被
   .phone-app 的 overflow:hidden 从右侧裁掉,这里让它们缩小/换行以塞进屏。 ── */
/* ≤380:覆盖三星 Z Fold 封面屏(CSS 宽约 344–376)+ 小安卓。里面都是换行/缩间距的优雅降级,
   对 390+ 主流机无影响。原本是 ≤340,Fold 封面屏卡在 340 之上没生效 → 右侧被裁。 */
@media (max-width: 380px) {
  .app-view { padding-left: calc(12px + env(safe-area-inset-left)); padding-right: calc(12px + env(safe-area-inset-right)); }
  .modal-backdrop { padding-left: calc(10px + env(safe-area-inset-left)); padding-right: calc(10px + env(safe-area-inset-right)); }
  .modal-card { padding: 16px; gap: 12px; }
  /* KATEGORI/SUMBER 标签行:标签+DEFAULT 塞不下时换行,DEFAULT 不再被裁掉最后一个字母 */
  .ff-lab-row { flex-wrap: wrap; row-gap: 2px; }
  /* 邀请页(Z Fold 封面屏):积分卡/奖励档缩紧。redeem 按钮保持和积分数字同行靠右(不换行);
     积分信息可压缩让位给按钮。 */
  .referral-hero { padding: 14px; gap: 10px; }
  .referral-hero-info { min-width: 0; }
  .referral-hero strong { font-size: 30px; }
  .referral-hero-cta { flex: 0 1 auto; min-width: 0; }
  .referral-rules > div { padding: 9px 10px; gap: 8px; }
  .referral-rules .rr-ic { width: 38px; height: 38px; }
  /* 邀请码:折叠屏缩字号 + 收紧字间距,8 位码整码显示,Copy 按钮不被顶出右边界 */
  .referral-code-row strong { font-size: 22px; letter-spacing: 0.08em; }
  .referral-code-row button { padding: 8px 14px; }
  /* 贷款/固定费用卡:剩余月数/结清日期两块 + 天数徽标,窄屏缩紧不越界 */
  .detail-tiles .dt-item { padding: 9px 10px; gap: 8px; }
  .detail-tiles .dt-ic { width: 32px; height: 32px; }
  .card-daybadge .cdb-ic { width: 34px; height: 34px; }
  /* 标题行:右侧胶囊(报销/记录)塞不下时换到下一行,而不是被裁 */
  .modal-heading-row { flex-wrap: wrap; }
  /* 签到 7 连珠:圆点缩小,7 颗仍能一行排下,+2AI 徽标不越界 */
  .checkin-cycle .cyc { width: 26px; height: 26px; font-size: 11px; box-shadow: 0 0 0 2px var(--card); }
  .checkin-cycle::before { left: 15px; right: 15px; top: 25px; }
  .cyc-spark { right: -7px; }
  .cs-num { font-size: 40px; }
  /* 首页日期 + 工资倒计时:太挤就换两行,不再 nowrap 溢出被裁 */
  .overview-datebar { flex-wrap: wrap; }
  .ovd-payday { white-space: normal; }
}
/* ── 首次填资料引导向导(5 步简化卡)────────────────────────── */
.setup-wiz-card { text-align: center; display: block; max-width: 400px; }
.sw-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.sw-dots { display: flex; gap: 6px; align-items: center; }
.sw-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); transition: background .2s var(--ease), width .2s var(--ease); }
.sw-dot.on { width: 22px; border-radius: 5px; background: var(--brand-2); }
.sw-dot.done { background: var(--brand-2); }
.sw-skipall { border: 0; background: transparent; color: var(--muted); font-size: 13px; font-weight: 700; cursor: pointer; padding: 4px; }
.sw-ic { width: 58px; height: 58px; margin: 0 auto 14px; display: grid; place-items: center; border-radius: 17px; background: var(--brand-grad); color: #fff; box-shadow: 0 8px 20px -8px rgba(255,87,34,.55); }
.sw-ic svg { width: 30px; height: 30px; }
.sw-title { margin: 0; font-size: 20px; font-weight: 800; }
.sw-sub { margin: 6px 0 20px; font-size: 13.5px; color: var(--muted); line-height: 1.5; }
.sw-fields { display: grid; gap: 12px; text-align: left; }
.sw-field { display: grid; gap: 6px; }
.sw-lab { font-size: 12px; font-weight: 700; color: var(--muted-strong); }
.sw-input { width: 100%; height: 50px; padding: 0 16px; border: 1.5px solid var(--line); border-radius: var(--radius-md); background: var(--soft); color: var(--ink); font-size: 16px; font-weight: 700; outline: none; -webkit-appearance: none; box-sizing: border-box; }
.sw-input:focus { border-color: var(--brand); background: var(--card); }
.sw-actions { display: flex; gap: 10px; margin-top: 22px; }
.sw-skip { flex: 0 0 auto; padding: 0 20px; min-height: 52px; border: 1.5px solid var(--line); border-radius: var(--radius-md); background: var(--card); color: var(--muted-strong); font-size: 15px; font-weight: 700; cursor: pointer; }
.sw-next { flex: 1; min-height: 52px; border: 0; border-radius: var(--radius-md); background: var(--accent-grad); color: #fff; font-size: 16px; font-weight: 800; cursor: pointer; }
.sw-next:active, .sw-skip:active { transform: scale(0.99); }
/* 确认记录弹窗头部图标 tile(鲜艳橙圆角,与主色一致) */
.pending-confirm-ic { width: 46px; height: 46px; display: grid; place-items: center; border-radius: 14px; background: var(--brand-grad); color: #fff; margin: 0 auto 10px; box-shadow: 0 6px 16px -6px rgba(255, 87, 34, .55); }

/* 待确认入账弹窗:沿用 .finance-form--tiles 的「框内左侧彩色图标 tab」样式(label 保持
   block+relative 让绝对定位图标贴左,不要改 flex)。关键:输入框 padding-left 给图标留位
   58px,否则文字会压在图标上(图标是 .ff-ic 绝对定位 left:0 的 tab)。 */
#pendingConfirmModal .pending-confirm-form { display: grid; gap: 12px; margin: 4px 0 2px; }
#pendingConfirmModal .pending-confirm-form .ff-lab { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
#pendingConfirmModal .pending-confirm-form > label > .ff-ic { height: 46px; } /* 与 46px 输入框等高 */
/* ⚠️ 账户那行的原生 <select> 已被换成自定义下拉 .csel-trigger(基础高 42px),而本弹窗
   的 input/select 和左侧图标都是 46px —— 不补这条,图标就比字段高 4px,紫色方块的上沿
   探出字段圆角,看着像「颜色溢出框格」(用户实拍 AKUN 那行)。让触发器也 46px 即对齐。 */
#pendingConfirmModal .pending-confirm-form .csel-trigger { height: 46px; }
/* ⚠️ padding 用 right-only,别写简写。
   这个表单是 .finance-form--tiles:左侧彩色图标是**绝对定位**压在输入框上的,
   靠 `padding-left: 58px` 给它让位(styles.css:5588 那条)。
   这里原来写 `padding: 0 14px` —— 简写会把 padding-left 一起重置成 14px,
   而 ID 选择器特异性(1,0,1)又压得过那条,结果图标直接盖在文字上:
   「Rp500.000」的 Rp 和图标叠成一团。只设右padding,左边留给 tile 规则。 */
#pendingConfirmModal input,
#pendingConfirmModal select {
  width: 100%; height: 46px; padding-right: 14px;
  /* 无描边:本弹窗是 tile 版式(左侧彩色图标 + 灰底字段),加边反而割裂。 */
  border: 0; border-radius: var(--radius-md);
  background: var(--soft); color: var(--ink); font-size: 15px;
  -webkit-appearance: none; appearance: none; outline: none;
  box-sizing: border-box;
}
#pendingConfirmModal input:focus,
#pendingConfirmModal select:focus { background: var(--soft); }
#pendingConfirmModal .amount-field,
#pendingConfirmModal .cal-field { width: 100%; }
#pendingConfirmModal .amount-field input { padding-right: 52px; } /* Aa 按钮留位 */
/* 日期框和其它字段统一:同样的灰底(--soft)、无边、左对齐。
   原来写的是 var(--card)(浅色下是白底)+ 上面那条边框 —— 三个字段里只有它是
   「白底带框」,看着突兀(用户实拍 TANGGAL 那行)。 */
#pendingConfirmModal input[type="date"] { background: var(--soft); text-align: left; }
#pendingConfirmModal input[type="date"]::-webkit-date-and-time-value { text-align: left; line-height: 44px; margin: 0; }
/* 键盘弹出(原生):收起底部 5 tab 导航,别被键盘顶上来挡住输入区。
   ⚠️ 原来是 display:none —— 一帧之内瞬间消失,而 iOS 键盘还要用 ~250ms 往上滑,
   观感就是「底栏啪地不见了,键盘才慢慢上来」,完全不跟手。
   改成沿自身高度滑出 + 淡出,时长/曲线对齐 iOS 键盘动画(--kb-dur 由 JS 按
   keyboardWillShow 上报的真实时长写入,拿不到就用 250ms 兜底)。
   曲线 cubic-bezier(.38,.7,.125,1) 是 iOS 键盘那条私有曲线(UIViewAnimationCurve 7)的通用近似。 */
body.native-app .bottom-nav {
  transition: transform var(--kb-dur, 250ms) var(--kb-ease, cubic-bezier(.38, .7, .125, 1)),
              opacity   var(--kb-dur, 250ms) var(--kb-ease, cubic-bezier(.38, .7, .125, 1));
}
body.native-app.kb-open .bottom-nav {
  /* ⚠️ 用 fixed(锚视口)而不是 absolute(锚 .phone-app)。
     键盘弹出时 .phone-app 会瞬间从整屏高收矮到「键盘上沿」(见 --kb-h),底栏作为它
     的最后一行会跟着**瞬间窜到 339 那一行**,然后才滑下去 —— 视觉上是「先窜上去再
     快速下滑」(用户实拍:键盘一出,5 个菜单迅速下滑)。
     fixed 锚在视口底(=真实屏幕底,resize:none 下 innerHeight 不随键盘变),正好等于
     底栏在流里的原位置,所以切成 fixed 不产生任何跳变,translateY(100%) 就是从原位
     纯下滑出屏。祖先没有 transform/filter/contain,不会给 fixed 建包含块,也不会被
     .phone-app 的 overflow:hidden 裁掉(已实测:navBottom 落在视口底,滑出不被裁)。
     同样脱离文档流,那一行照样立刻收掉,不占位。 */
  position: fixed;
  left: 0; right: 0; bottom: 0;
  transform: translateY(100%);
  opacity: 0;
  pointer-events: none;   /* 滑出途中别再吃点击 */
}
#pendingConfirmModal select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; padding-right: 36px;
}

/* ── 流水导入审核 ───────────────────────────────────────────── */
.import-first-hint { font-size: 12px; font-weight: 600; color: var(--brand); background: var(--brand-soft); border: 1px solid var(--brand-ring); border-radius: var(--radius-sm); padding: 8px 10px; margin: 0; }
.import-card { width: min(560px, 100%); max-height: 88vh; }
.import-mapping { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.import-mapping label { display: grid; gap: 4px; font-size: 11px; color: var(--muted); font-weight: 600; }
.import-mapping select { width: 100%; min-width: 0; }
.import-dupmode { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; font-size: 12px; color: var(--ink); padding: 8px 0; border-top: 1px solid var(--line); }
.import-dupmode > span { font-weight: 700; }
.import-dupmode label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.import-dupmode input { accent-color: var(--brand); }
.import-rows { display: grid; gap: 6px; max-height: 46vh; overflow-y: auto; padding-right: 2px; }
.import-row {
  display: grid;
  gap: 6px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--card);
}
.import-row.is-dup { border-color: var(--brand-ring); background: var(--brand-soft); }
.import-name { width: 100%; height: 32px; font-size: 13px; font-weight: 700; }
.import-row-meta { display: flex; align-items: center; gap: 8px; }
.import-row-meta small { font-size: 11px; color: var(--muted); margin-right: auto; }
.import-row-meta em { color: var(--brand); font-style: normal; font-weight: 700; }
.import-date { height: 28px; font-size: 12px; padding: 0 6px; margin-right: auto; }
.import-date.is-bad { border-color: var(--danger); background: var(--danger-soft, rgba(220,38,38,.08)); }
.import-dup-tag { color: var(--brand); font-style: normal; font-weight: 700; font-size: 11px; }
.import-type { height: 26px; padding: 0 10px; border-radius: var(--radius-pill); border: 1px solid var(--line); background: var(--card); font-size: 11px; font-weight: 700; cursor: pointer; white-space: nowrap; flex: 0 0 auto; }
.import-type.income { color: var(--ok); border-color: var(--ok); }
.import-type.expense { color: var(--danger); border-color: var(--danger); }
.import-amt { font-size: 13px; font-weight: 800; font-feature-settings: "tnum","lnum"; white-space: nowrap; flex: 0 0 auto; }
.import-amt.inc { color: var(--ok); }
.import-amt.exp { color: var(--ink); }
.import-cat { width: 100%; height: 30px; font-size: 12px; }
.import-source { display: grid; gap: 4px; font-size: 11px; color: var(--muted); font-weight: 600; }
.import-source select { width: 100%; }
.import-ai-btn { width: 100%; height: 38px; border-radius: var(--radius-sm); border: 1px solid var(--brand-ring); background: var(--brand-soft); color: var(--brand); font-size: 13px; font-weight: 700; cursor: pointer; }
.import-ai-btn:disabled { opacity: 0.6; cursor: default; }

/* 流水详情弹窗 */
/* 交易详情弹窗:浅灰底 + 白行卡 + 分类色图标(反卡风,无黑线) */
#txDetailModal .modal-card { background: var(--bg); }
/* 行合成一张卡(iOS inset grouped list);分隔线从图标右侧标签处起、右贴卡边、不顶到左边 */
.tx-detail-body { display: grid; gap: 0; background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; }
.txd-irow { position: relative; display: flex; align-items: center; gap: 13px; padding: 14px 16px; background: transparent; }
.txd-irow:not(:last-child)::after { content: ""; position: absolute; left: 69px; right: 0; bottom: 0; height: 1px; background: var(--line); }
.txd-irow .txd-ic { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; }
.txd-irow .txd-ic svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.txd-irow .txd-label { flex: 0 0 auto; color: var(--muted); font-size: 14px; font-weight: 600; }
.txd-irow .txd-val { flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 800; color: var(--ink); text-align: right; white-space: normal; line-height: 1.3; font-feature-settings: "tnum","lnum"; }
.txd-irow .txd-val.txd-inc { color: var(--ok); }
.txd-irow .txd-val.txd-exp { color: var(--danger); }
.txd-ic-blue { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.txd-ic-red { background: rgba(239, 68, 68, 0.12); color: #ef4444; }
.txd-ic-green { background: rgba(16, 185, 129, 0.13); color: #10a35e; }
.txd-ic-purple { background: rgba(139, 92, 246, 0.13); color: #8b5cf6; }
.txd-ic-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
/* 底部三键:删除=红描边幽灵,复制=中性幽灵,关闭=主题色实心(主操作,略宽) */
.txd-actions { display: flex; gap: 10px; margin-top: 4px; }
.txd-btn { height: 52px; border-radius: 15px; display: grid; place-items: center; cursor: pointer; border: 0; background: transparent; transition: transform 0.1s var(--ease); }
.txd-btn:active { transform: scale(0.96); }
.txd-btn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.txd-btn-delete { flex: 1; border: 1.5px solid rgba(239, 68, 68, 0.4); color: var(--danger); }
.txd-btn-copy { flex: 1; border: 1.5px solid var(--line); color: var(--muted-strong); }
.txd-btn-close { flex: 1.4; background: var(--accent-grad); color: #fff; box-shadow: 0 8px 20px -6px rgba(var(--brand-2-rgb), 0.5); }
/* 旧表格式行(仍用于 split 详情等) */
.txd-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.txd-row:last-child { border-bottom: 0; }
.txd-row > span { color: var(--muted); }
.txd-row > b { font-weight: 700; color: var(--ink); text-align: right; }
.txd-row > b.txd-inc { color: var(--ok); }
.txd-row > b.txd-exp { color: var(--danger); }
/* 删除按钮:白底红字,与关闭等高对齐(secondary-button 已给白底+边框+44h) */
.txd-delete-btn { color: var(--danger) !important; border-color: var(--danger) !important; }
/* 编号行:等宽字体,带复制提示感 */
.txd-row > b.txd-code { font-family: var(--mono, ui-monospace, "SF Mono", monospace); letter-spacing: .04em; color: var(--muted-strong); }
/* 详情底部三按钮:删除/复制(次要,等宽分) + 关闭(主,占满剩余) */
.txd-actions { display: flex; gap: 8px; }
.txd-actions .secondary-button { flex: 0 0 auto; padding: 0 16px; }
.txd-actions > button:last-child { flex: 1; }

/* ── 过往预算:月份列表 + 月明细弹窗 ── */
.budget-past-list { display: grid; gap: 8px; }
.budget-past-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--card); cursor: pointer; }
.budget-past-item > div { display: grid; gap: 2px; }
.budget-past-month { font-size: 15px; font-weight: 700; color: var(--ink); }
.budget-past-sub { font-size: 12px; color: var(--muted); }
.budget-month-analysis { margin-bottom: 4px; }
.bm-ana-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.bm-ana-grid > span { display: grid; gap: 3px; padding: 12px 13px; background: var(--card); border: 1px solid var(--line); border-radius: 14px; }
.bm-ana-grid small { font-size: 11px; color: var(--muted); }
.bm-ana-grid b { font-size: 16px; font-weight: 800; color: var(--ink); font-feature-settings: "tnum","lnum"; }
.bm-ana-grid b.bm-pos { color: var(--ok); }
.bm-ana-grid b.bm-neg { color: var(--danger); }
.budget-month-list { display: grid; gap: 8px; }
.bm-row { display: grid; gap: 8px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 14px; background: var(--card); }
/* 超预算行:反转成红底白字(强提示) */
.bm-row.is-over { border-color: transparent; background: var(--danger); box-shadow: 0 6px 16px -8px var(--danger); }
.bm-row-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13.5px; }
.bm-row-top b { font-weight: 800; color: var(--ink); }
.bm-row-top span { color: var(--muted); font-feature-settings: "tnum","lnum"; }
.bm-row.is-over .bm-row-top b { color: #fff; }
.bm-row.is-over .bm-row-top span { color: rgba(255, 255, 255, 0.92); font-weight: 700; }
/* 历史预算行进度条(之前 .mini-track 无独立样式=隐形,这里补上)+ 百分比 */
.bm-row-bar { display: flex; align-items: center; gap: 8px; }
.bm-row .mini-track { flex: 1; height: 6px; background: var(--soft); border-radius: 999px; overflow: hidden; }
.bm-row .mini-track > span { display: block; height: 100%; background: var(--brand-2); border-radius: 999px; }
.bm-row.is-over .mini-track { background: rgba(255, 255, 255, 0.28); }
.bm-row.is-over .mini-track > span { background: #fff; }
.bm-row-bar em { font-style: normal; font-size: 11px; font-weight: 800; color: var(--muted); min-width: 36px; text-align: right; font-feature-settings: "tnum","lnum"; }
.bm-row.is-over .bm-row-bar em { color: #fff; }
.confirm-preview {
  margin: 0;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--soft);
  border-left: 3px solid var(--brand);
  font-size: 13px;
  color: var(--ink);
  display: grid;
  gap: 6px;
}
.confirm-preview-text { color: var(--ink); }
.confirm-preview-action {
  font-size: 12px;
  font-weight: 700;
  color: var(--brand);
  letter-spacing: 0.02em;
}

/* Reimbursement */
.reimburse-check {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--soft);
  cursor: pointer;
  font-size: 13px;
  color: var(--ink);
}
.reimburse-check input[type="checkbox"] {
  accent-color: var(--brand);
  width: 16px;
  height: 16px;
}
.income-badge.reimburse {
  background: rgba(255, 87, 34, 0.12);
  color: var(--brand);
}
.income-item.is-reimburse {
  border-left: 3px solid var(--brand);
}
.card-action.received {
  background: var(--brand);
  color: #fff;
}
.reimburse-summary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 0 0 14px;
}
.reimburse-summary > div {
  padding: 14px 16px;
  border-radius: var(--radius-md);
  background: var(--soft);
  display: grid;
  gap: 6px;
  border: 1px solid var(--line);
}
/* Pending = brand tint, Received = green tint */
.reimburse-summary > div:first-child {
  background: var(--brand-soft);
  border-color: var(--brand-ring);
}
.reimburse-summary > div:last-child {
  background: var(--ok-soft);
  border-color: rgba(16, 185, 129, 0.28);
}
/* Only the label span is uppercased — NOT the Rp prefix inside <strong> */
.reimburse-summary > div > span {
  font-size: 11px;
  color: var(--muted-strong);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.reimburse-summary strong {
  font-size: 20px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.reimburse-summary > div:first-child strong { color: var(--brand-2); }
.reimburse-summary > div:last-child strong { color: var(--ok); }
.reimburse-section-title {
  margin: 16px 0 8px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.reimburse-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin: 4px 0 14px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--soft);
}
.reimburse-tabs button {
  border: 0;
  padding: 10px 14px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.reimburse-tabs button.active {
  background: var(--card);
  color: var(--ink-strong);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08);
}
.reimburse-tab-page[hidden] { display: none; }

/* Referral panel */
.referral-card { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.referral-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 16px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, rgba(255,87,34,0.12), rgba(17,17,17,0.06));
  border: 1px solid var(--line);
}
/* 邀请码页:只把积分卡(POIN KAMU)从渐变改纯色浅橙(主题色,暗色自适应)。
   按钮/tab 高亮仍保持全 App 一致的橙色渐变(--brand-grad),不动。 */
#profileReferral .referral-hero { background: var(--brand-soft); border: 0; }
/* 去掉下方几张卡的描边(输码框 / 你的码 / 链接框),保留纯色软底 */
#profileReferral .referral-apply-box,
#profileReferral .referral-code-box,
#profileReferral .referral-link-field input { border: 0; }
.referral-hero-info { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.referral-hero-info > span {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.referral-hero strong {
  font-size: 36px;
  font-weight: 900;
  color: var(--brand-2);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.referral-hero small {
  font-size: 12px;
  color: var(--muted-strong);
}
.referral-rules {
  display: grid;
  /* 4 tiers (signup / silver / gold / platinum) — 2×2 so the longer tier labels
     don't get crushed into 4 narrow columns on phones. minmax(0,…) 让列在 Z Fold
     折叠屏能真缩,不被 tile 内容固有宽度撑破右边界。 */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.referral-rules > div {
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  background: var(--soft);
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
}
.referral-rules .rr-ic { flex: none; width: 44px; height: 44px; border-radius: 13px; display: grid; place-items: center; }
.referral-rules .rr-ic svg { width: 24px; height: 24px; }
.referral-rules .rr-txt { display: grid; gap: 1px; min-width: 0; }
.referral-rules span { font-size: 11px; color: var(--muted); }
.referral-rules b {
  font-size: 16px;
  font-weight: 800;
  color: var(--brand-2);
}
/* 段位 tile 语义色(固定色) */
.rr-ic-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
.rr-ic-silver { background: rgba(148, 163, 184, 0.20); color: #64748b; }
.rr-ic-gold { background: rgba(234, 179, 8, 0.18); color: #d99e0b; }
.rr-ic-platinum { background: rgba(139, 92, 246, 0.16); color: #8b5cf6; }
/* 补填邀请码 */
/* Z Fold 封面屏:整页防横向溢出(某处内容偶尔宽出几 px 就出横向滚动条 + 右侧文字被裁) */
#profileReferral { overflow-x: hidden; }
.referral-rules-extra { overflow-wrap: anywhere; }
.referral-apply-box { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; padding: 14px 16px; margin-bottom: 12px; border-radius: var(--radius-md); background: var(--soft); border: 1px solid var(--line); }
.referral-apply-box[hidden] { display: none; }
.referral-apply-box > span { font-size: 14px; font-weight: 800; }
.referral-apply-box small { font-size: 12px; color: var(--muted); }
.referral-apply-row { display: flex; gap: 8px; margin-top: 4px; }
.referral-apply-row input { flex: 1; min-width: 0; min-height: 44px; text-transform: uppercase; letter-spacing: .06em; background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 0 14px; color: var(--ink); font-weight: 700; }
.referral-apply-row input:focus { outline: none; border-color: var(--brand-2); }
.referral-apply-row button { flex: 0 0 auto; padding: 0 20px; min-height: 44px; border: 0; border-radius: 12px; background: var(--brand-grad); color: #fff; font-weight: 800; cursor: pointer; }
.referral-apply-status { font-size: 12px; font-weight: 700; }
.referral-apply-status.is-ok { color: var(--ok, #16a34a); }
.referral-apply-status.is-error { color: var(--danger, #dc2626); }
.referral-code-box {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  background: var(--soft);
  border: 1px dashed var(--brand-ring);
}
.referral-code-box > span {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.referral-code-row {
  display: grid;
  /* minmax(0,1fr):默认 1fr = minmax(auto,1fr),auto 最小值 = 码的固有 nowrap 宽度,
     窄屏(Z Fold 折叠)撑不下就把 Copy 按钮顶出屏幕。改 minmax(0,…) 才允许码列真缩。 */
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
}
.referral-code-row strong {
  font-size: 28px;
  font-weight: 900;
  letter-spacing: 0.18em;
  color: var(--brand-2);
  font-variant-numeric: tabular-nums;
  user-select: all;
  min-width: 0;
  overflow-wrap: anywhere;
}
.referral-code-row button {
  padding: 8px 16px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--brand-grad);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.referral-code-box small {
  font-size: 12px;
  color: var(--muted-strong);
}

.referral-tabs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  margin: 4px 0 14px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--soft);
}
.referral-tabs button {
  border: 0;
  padding: 10px 8px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.referral-tabs button.active {
  background: var(--card);
  color: var(--ink-strong);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08);
}
.referral-tab-page[hidden] { display: none; }

.referral-rules-extra {
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  margin: -4px 0 0;
}
.referral-invited-note {
  text-align: center;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--brand-2);
  background: var(--brand-soft);
  border-radius: 999px;
  padding: 5px 12px;
  margin: 8px auto 0;
  width: fit-content;
}

.referral-section-title {
  margin: 0 0 10px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.referral-friends-list,
.referral-ledger-list {
  display: grid;
  gap: 8px;
}
.referral-friend,
.referral-ledger-row {
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--soft);
}
.referral-friend-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.referral-friend-head strong {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.referral-friend-plan {
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
}
.referral-friend-plan.plan-free { background: rgba(100,116,139,0.18); color: var(--muted); }
.referral-friend-plan.plan-silver { background: var(--brand-soft); color: var(--brand-2); }
.referral-friend-plan.plan-gold { background: rgba(124,58,237,0.16); color: #7c3aed; }
.referral-friend-plan.plan-platinum { background: rgba(234,179,8,0.16); color: #a16207; }
.referral-friend-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
}
/* 推荐积分:橙色=已生效,灰色=待生效(被邀请人活跃满 15 分钟才结算) */
.rf-cred { font-weight: 800; }
.rf-cred--on { color: var(--brand-2); }
.rf-cred--pending { color: var(--muted); }
.referral-ledger-line-1 {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}
.referral-ledger-line-1 strong {
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}
.referral-ledger-line-1 strong.in { color: var(--ok); }
.referral-ledger-line-1 strong.out { color: var(--muted); }
.referral-ledger-row small {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
}

/* Link sits on its own full-width row; Copy + Share share the row below. */
.referral-link { display: grid; gap: 10px; }
.referral-link > span {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.referral-link-field { position: relative; }
.referral-link-field input {
  width: 100%;
  height: 46px;
  padding: 0 48px 0 14px; /* 右侧留位给复制图标 */
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--soft);
  color: var(--ink);
  font-size: 13px;
  font-family: var(--font-mono, monospace);
  min-width: 0;
  text-overflow: ellipsis;
}
.referral-link-copy {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; display: grid; place-items: center;
  border: 0; border-radius: 10px; background: transparent; color: var(--muted-strong); cursor: pointer;
}
.referral-link-copy svg { width: 18px; height: 18px; }
.referral-link-copy:active { transform: translateY(-50%) scale(0.92); background: var(--soft); }
.referral-link-actions { display: flex; gap: 10px; }
.referral-action {
  flex: 1 1 0;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  font-size: 14px;
  font-weight: 800;
  cursor: pointer;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}
.referral-action svg { width: 18px; height: 18px; flex: 0 0 auto; }
.referral-action:active { transform: scale(0.98); }
.referral-action--wa {
  width: 100%;
  margin-bottom: 10px;
  background: #25d366;
  color: #fff;
  border: 0;
  box-shadow: 0 8px 20px -8px rgba(37, 211, 102, 0.8);
}
.referral-action--wa svg { width: 20px; height: 20px; }
.referral-action--wa:hover { background: #20bd5a; box-shadow: 0 10px 24px -8px rgba(37, 211, 102, 0.9); }
.referral-action--copy {
  background: var(--soft);
  color: var(--ink-strong);
  border: 1px solid var(--line-strong, var(--line));
}
.referral-action--copy:hover { background: var(--hover, var(--soft)); border-color: var(--brand); }
.referral-action--share {
  background: var(--brand-grad);
  color: #fff;
  border: 0;
  box-shadow: 0 8px 20px -8px var(--brand);
}
.referral-action--share:hover { box-shadow: 0 10px 24px -8px var(--brand); }
/* 报销两个 tab 统一:单卡 + 细分隔线的行(Menunggu 参照 Riwayat 排版,颜色各自保留) */
.reimburse-list {
  display: grid;
  gap: 10px;
}
.reimburse-row {
  display: grid;
  gap: 12px;
  padding: 16px;
  border: 0;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);   /* 每条独立成卡,参照流水列表(无边框靠阴影) */
  text-transform: none;          /* 覆盖表单里同名 .reimburse-row 的 uppercase */
  letter-spacing: normal;
  cursor: default;
}
.rr-head { display: flex; align-items: center; gap: 12px; }
.rr-info { display: grid; gap: 3px; min-width: 0; flex: 1; }
.rr-name { font-size: 15px; font-weight: 800; color: var(--ink); text-transform: uppercase; letter-spacing: 0.02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rr-sub, .rr-date { font-size: 12.5px; font-weight: 500; color: var(--muted); text-transform: none; letter-spacing: normal; }
.rr-amt { font-size: 16px; font-weight: 800; white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--ink); }
.reimburse-row.received .rr-amt { color: var(--ok); }
.rr-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.rr-confirm { display: inline-flex; align-items: center; gap: 8px; padding: 0; border: 0; background: transparent; color: var(--brand-2); font-size: 13px; font-weight: 700; cursor: pointer; }
.rr-radio { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--brand-2); flex: none; transition: border-color var(--dur) var(--ease); }
.rr-confirm:active .rr-radio { background: var(--brand-2); }
.rr-chev { display: inline-grid; place-items: center; flex: none; color: var(--muted); margin-left: 2px; }
.rr-chev svg { width: 18px; height: 18px; }
.reimburse-row.is-tappable { cursor: pointer; }
.reimburse-row.is-tappable:active { background: var(--soft); }

/* Auth modal — referral code disclosure */
.auth-ref-details {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 4px 12px;
  background: var(--soft);
}
.auth-ref-details summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-2);
  padding: 8px 0;
  list-style: none;
}
.auth-ref-details summary::-webkit-details-marker { display: none; }
.auth-ref-details summary::before {
  content: "+ ";
  font-weight: 800;
}
.auth-ref-details[open] summary::before { content: "− "; }
.auth-ref-details .auth-ref-label {
  display: grid;
  gap: 6px;
  padding: 4px 0 10px;
}
.auth-ref-details .auth-ref-label input {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

/* Money / Bills top toggle inside debt view */
.money-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin: 4px 0 10px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
@media (hover: hover) {
  .money-tabs button:not(.active):hover { background: var(--soft); color: var(--ink-strong); }
}
/* Hidden while drilled into a level-3 panel (see toggleMoneyTabsForDrill). */
.money-tabs.drill-hidden { display: none; }

/* Amount field with an Aa/123 keyboard toggle (see setupAmountKeyboardToggles). */
.amount-field { position: relative; display: block; }
.amount-mode-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  min-width: 38px;
  padding: 5px 8px;
  border: 1px solid var(--line);
  background: var(--soft);
  color: var(--muted);
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}
.amount-mode-toggle:active { background: var(--hover); }
.money-tabs button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 0;
  padding: 10px 14px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
/* Count pill on a tab / side-menu row (overdue loans & fixed costs). Mirrors
   .nav-badge styling but flows inline rather than floating in a corner. */
/* Greyed AI entry points for free plan — kept clickable so the tap can surface
   the upgrade nudge (see syncAiLockUi / promptAiUpgrade). */
.is-locked {
  opacity: 0.4;
  filter: grayscale(0.6);
}
.tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--danger);
  color: #fff;
  font-size: 10px;
  font-style: normal;
  font-weight: 800;
  line-height: 18px;      /* = height:让行盒撑满圆圈高度,数字随字体基线在圆内垂直居中 */
  text-align: center;
  letter-spacing: 0;      /* 清掉按钮继承的字距,否则数字后多一格显得偏左 */
  text-indent: 0;
  font-variant-numeric: tabular-nums;
}
/* 徽章暗色统一正红圈(--danger 暗色偏粉 #f87171 → #ef4444):tab 徽章 + 底部导航徽章都红。 */
:root[data-theme="dark"] .tab-badge,
:root[data-theme="dark"] .nav-badge { background: #ef4444; }
/* 激活 tab(橙底)上的徽章用白圈橙字,和橙底区分;非激活仍红圈。 */
.money-tabs button.active .tab-badge { background: #fff; color: #ff5722; }
.money-tabs button.active {
  background: var(--card);
  color: var(--ink-strong);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08);
}
/* Side-menu buttons hidden based on active money sub-tab */
[data-panel-scope="debt"][data-money-tab-active="money"] [data-money-section="bills"] { display: none; }
[data-panel-scope="debt"][data-money-tab-active="bills"] [data-money-section="money"] { display: none; }
/* Profile (我) view: 资料/设置 sub-tab toggles which side-menu section shows */
[data-panel-scope="profile"][data-profile-tab-active="info"] [data-profile-section="settings"] { display: none; }
[data-panel-scope="profile"][data-profile-tab-active="settings"] [data-profile-section="info"] { display: none; }
/* The Mutasi/Bills nav shortcuts use display:grid !important in simple mode, which
   would otherwise leak into the 设置 tab — keep them to the 资料 tab only.
   ⚠️ 两边都是 !important,所以比的是特异性,必须**压过**放行那条:
       放行 .phone-app[data-ui-mode="simple"] .side-menu .side-menu-nav  = (0,4,0)
       本条 .phone-app [scope][tab-active] .side-menu .side-menu-nav     = (0,5,0)
   原来写的是 [scope][tab-active] .side-menu-nav = (0,3,0) —— 少一分,从来没生效过,
   精简模式下 Mutasi/Keuangan 会跟着漏进 PENGATURAN(真机实拍就是这个样子)。 */
.phone-app [data-panel-scope="profile"][data-profile-tab-active="settings"] .side-menu .side-menu-nav { display: none !important; }

/* AI parse-tx modal */
.parse-tx-list {
  display: grid;
  gap: 8px;
  max-height: 50vh;
  overflow-y: auto;
  margin: 0 0 12px;
}
.parse-tx-row {
  display: grid;
  /* ⚠️ 必须 minmax(0,1fr),不能只写 1fr —— fr 的隐式最小值是 auto(=min-content),
     里面任一定宽元素(如 .amount-field 的 flex:0 0 142px)就能把整列顶到比容器宽,
     行溢出 .parse-tx-list,右侧输入框被裁掉一截。
     窄屏尤其明显;而 macOS 预览用悬浮滚动条,肉眼几乎看不出来 ——
     这次是靠遍历祖先链找 overflow 容器才定位到的。
     同样的坑 .content-panel 那条注释里也记过一次。 */
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--soft);
  cursor: pointer;
}
.parse-tx-row input[type="checkbox"] {
  margin-top: 2px;
  accent-color: var(--brand);
}
.parse-tx-row-head {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: baseline;
  font-size: 14px;
}
.parse-tx-row-body small {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--muted);
}
.parse-tx-row-head { cursor: pointer; }
/* <input> 有固有宽度(默认约 20 字符),放进 grid/flex 里**不会自己缩**:
   上面把列改成 minmax(0,1fr) 只修了列,输入框本身仍是 275px,照样顶破 256px 的列,
   行溢出 .parse-tx-list 7px → 右侧被裁。必须显式 width:100% + min-width:0。
   (390px 下才量得出来;375px 恰好差一点没露馅,所以前几轮一直没抓到。) */
.parse-tx-row-body input,
.parse-tx-row-body select { width: 100%; min-width: 0; box-sizing: border-box; }
.parse-tx-row-fields { display: flex; gap: 8px; margin-top: 8px; min-width: 0; }
.parse-tx-row-fields > * { min-width: 0; }
.parse-tx-row-fields input {
  flex: 1 1 0; min-width: 0; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); font-size: 13px;
}
.parse-tx-amount.in { color: var(--success, #16a34a); }
.parse-tx-amount.out { color: var(--ink); }
/* AI 扫描结果全字段可编辑:商家/金额输入 + 品类/种类下拉 */
.parse-tx-row-head { cursor: default; gap: 8px; }
.parse-tx-name {
  flex: 1 1 0; min-width: 0; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); font-size: 14px; font-weight: 700;
}
.parse-tx-row-head .amount-field { flex: 0 0 142px; }
.parse-tx-amount-edit {
  width: 100%; padding: 7px 9px; text-align: right;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.parse-tx-amount-edit.in { color: var(--success, #16a34a); }
.parse-tx-amount-edit.out { color: var(--ink); }
.parse-tx-row-fields select {
  flex: 1 1 0; min-width: 0; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); font-size: 13px;
}
/* ── AI 扫描导入弹窗改版:金额独占一行放大 + 来源/报销同排 ── */
.parse-tx-row { padding: 12px; border-radius: 16px; gap: 10px; }
.parse-tx-row-body { display: grid; gap: 8px; }
.parse-tx-name { width: 100%; flex: none; padding: 9px 11px; border-radius: 10px; }
.parse-tx-row-body > .amount-field {
  position: relative; border: 1px solid var(--line); border-radius: 10px; background: var(--card);
}
.parse-tx-row-body > .amount-field::before {
  content: "Rp"; position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  font-size: 13px; font-weight: 700; color: var(--muted); pointer-events: none;
}
.parse-tx-row-body > .amount-field > .parse-tx-amount-edit {
  width: 100%; border: 0; background: transparent; text-align: left;
  padding-top: 12px; padding-bottom: 12px; padding-left: 38px;
  font-size: 19px; font-weight: 800;
}
.parse-tx-row-fields { margin-top: 0; }
.parse-tx-row-fields input, .parse-tx-row-fields select { padding: 9px 11px; border-radius: 10px; }
/* 来源 + 报销 同一行 */
.parse-tx-source { margin: 16px 0 14px; }
.parse-tx-source-lab {
  display: block; font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .03em; margin-bottom: 7px;
}
.parse-tx-source-row { display: flex; gap: 8px; align-items: stretch; }
.parse-tx-account-field { flex: 1 1 0; min-width: 0; position: relative; }
.parse-tx-account-field .csel-trigger { width: 100%; }
.parse-tx-source-row .reimburse-check {
  flex: 0 0 auto; margin: 0; border: 1px solid var(--line); background: var(--card);
}
/* 票据录入选择:拍照 / 扫描 两个大块 */
/* Batal(取消):做成整行软底按钮,别裸描边(与三个选项 tile 协调) */
.receipt-capture-card .secondary-button {
  width: 100%; margin-top: 2px; padding: 13px; border-radius: var(--radius-md);
  background: var(--soft) !important; border: 0 !important; color: var(--muted-strong) !important;
  font-size: 15px; font-weight: 700; cursor: pointer;
}
.receipt-capture-card .secondary-button:active { background: var(--hover) !important; transform: scale(0.99); }
.receipt-capture-card .rc-options { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* 三选项(拍照/扫描/浏览):整行,图标居左跨两行,右侧标题/副标题左对齐上下堆叠 */
.receipt-capture-card .rc-options--3 { grid-template-columns: 1fr; gap: 12px; }
.rc-options--3 .rc-opt { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 14px; row-gap: 2px; justify-items: start; text-align: left; align-items: center; padding: 14px 16px; }
.rc-options--3 .rc-opt .rc-ic { grid-row: 1 / 3; width: 44px; height: 44px; border-radius: 13px; margin-bottom: 0; align-self: center; justify-self: center; }
.rc-options--3 .rc-opt b { grid-column: 2; justify-self: start; align-self: end; font-size: 15.5px; font-weight: 700; }
.rc-options--3 .rc-opt small { grid-column: 2; justify-self: start; align-self: start; font-size: 12.5px; color: var(--muted); }
.rc-opt {
  display: grid; gap: 4px; justify-items: center; text-align: center;
  padding: 18px 12px; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--soft); color: var(--ink); cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.rc-opt:hover, .rc-opt:active { background: var(--brand-soft); border-color: var(--brand); }
.rc-opt .rc-ic { width: 40px; height: 40px; display: grid; place-items: center; border-radius: 50%; background: var(--brand-soft); color: var(--brand-2); margin-bottom: 4px; }
.rc-opt .rc-ic svg { width: 22px; height: 22px; }
.rc-opt b { font-size: 15px; }
.rc-opt small { font-size: 11.5px; color: var(--muted); line-height: 1.3; }
/* 卡片 ⋯ 菜单:标题 + 右侧 Akhiri(危险色,分离防误触);下面 Edit/Riwayat 横排居中 */
.card-menu-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.card-menu-head h3 { margin: 0; font-size: 16px; font-weight: 800; color: var(--ink-strong, var(--ink)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.card-menu-end { flex: none; border: 1.5px solid var(--danger); background: transparent; color: var(--danger); font-size: 13px; font-weight: 800; padding: 7px 16px; border-radius: 999px; cursor: pointer; }
.card-menu-end:active { background: rgba(239, 68, 68, 0.12); transform: scale(0.97); }
.card-menu-list { display: grid; gap: 8px; margin-top: 12px; }
.card-menu-item { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 11px 14px; border: 1px solid var(--line); border-radius: 14px; background: var(--soft); color: var(--ink); font-size: 15px; font-weight: 700; cursor: pointer; }
.card-menu-item:active { background: var(--brand-soft); border-color: var(--brand-2); }
.card-menu-ic { flex: none; width: 40px; height: 40px; display: grid; place-items: center; border-radius: 12px; background: var(--brand-soft); color: var(--brand-2); }
.card-menu-ic svg { width: 21px; height: 21px; fill: none; stroke: currentColor; }
/* 付款记录汇总页 */
.rwy-card { max-height: 78vh; display: flex; flex-direction: column; }
.rwy-list { margin-top: 12px; overflow-y: auto; -webkit-overflow-scrolling: touch; display: grid; gap: 0; }
.rwy-item { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 2px; }
.rwy-item + .rwy-item { border-top: 1px solid var(--line); }
.rwy-when { display: grid; gap: 2px; min-width: 0; }
.rwy-when b { font-size: 14.5px; font-weight: 700; color: var(--ink); }
.rwy-when small { font-size: 12px; color: var(--muted); }
.rwy-amt { flex: none; font-size: 15.5px; font-weight: 800; color: var(--ink-strong, var(--ink)); font-feature-settings: "tnum", "lnum"; }
.rwy-empty { text-align: center; padding: 26px 0; color: var(--muted); font-size: 13.5px; }
/* 原生 App(Play 合规):App 内不得售卖数字订阅 / 引导外部支付。隐藏选购+支付 UI,
   只保留只读当前档位 + AI 额度;升级在网页完成,档位经 /api/me 自动同步回 App。 */
/* 网页版隐藏原生独有、网页用不了的功能:OTA更新页 / 生物+推送提醒 / 签到看广告 / 实时票据扫描 */
body:not(.native-app) [data-panel-target="settingsUpdate"],
body:not(.native-app) [data-panel-target="settingsSecurity"],
body:not(.native-app) #checkinDot,
body:not(.native-app) #scScan,
body:not(.native-app) #rcScan { display: none !important; }

/* iOS App Store 3.1.1:App 内不得用「码」解锁数字内容(AI 次数/会员)。
   iOS 上隐藏两个「当场发货」的入口:①输好友码换 +5 AI ②积分换会员;订阅页那条
   「邀请换会员」的引导也去掉。其余(你的邀请码/链接、积分数字、规则、好友、ledger)
   都保留展示。奖励仍在后端累计,用户去网页兑换,次数/档位经 /api/me 同步回 App。 */
body.ios-native #subReferralPrompt,
body.ios-native .redeem-gift-card .redeem-gift-copy,
body.ios-native .referral-hero-cta { display: none !important; }
/* iOS 保留「输入邀请码」框(仅绑定邀请归属,不在 App 内发 AI),
   但去掉「→ 换 5 次 AI」这行奖励说明(奖励在网页/安卓兑换) */
body.ios-native #referralApplyBox > small { display: none !important; }
/* 积分 hero 只展示数字,去掉「兑换积分→会员」这个可点动作(改去网页兑换) */
body.ios-native .referral-hero { cursor: default; pointer-events: none; }

.native-plan-ro { display: none; }
body.native-noiap #nativePlanRO {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 16px; margin-bottom: 4px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-md);
}
body.native-noiap #nativePlanRO .npr-label { font-size: 13px; color: var(--muted); }
body.native-noiap #nativePlanRO strong { font-size: 16px; font-weight: 800; }
/* 无内购的原生(Android / iOS 未配 RevenueCat):隐藏选购,只留只读档位(合规) */
body.native-noiap #profileSubscription .billing-cycle,
body.native-noiap #profileSubscription .plan-grid,
body.native-noiap #profileSubscription #subManageBox { display: none !important; }
/* Xendit「安全支付」徽标任何原生都不显示(IAP 走 App Store,不用它) */
body.native-app #profileSubscription .payment-secure { display: none !important; }
.parse-tx-account {
  display: grid;
  gap: 6px;
  margin: 0 0 14px;
  font-size: 13px;
}
.parse-tx-account select {
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border, rgba(0,0,0,0.12));
  background: var(--surface, #fff);
  color: var(--ink);
  font: inherit;
}

/* ── 18. Toast ────────────────────────────────────────────────── */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(96px + env(safe-area-inset-bottom));
  z-index: 90;
  display: grid;
  grid-auto-flow: column;
  align-items: center;
  gap: 12px;
  width: fit-content; /* 短文案 → 窄框自适应 */
  max-width: min(300px, calc(100vw - 40px)); /* 硬上限:超出则第二行,不会拉满屏 */
  transform: translateX(-50%) translateY(20px);
  padding: 11px 20px;
  border-radius: 999px;
  /* 跟随主题:亮=白底深字 / 暗=深底白字,圆角胶囊浮在中间按钮上方 */
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 14px 34px -10px rgba(15, 23, 42, 0.3);
  opacity: 0;
  transition: opacity 200ms var(--ease), transform 200ms var(--ease);
}
:root[data-theme="dark"] .toast { box-shadow: 0 14px 34px -8px rgba(0, 0, 0, 0.6); }
.toast > span { text-align: center; line-height: 1.35; } /* 多行时两行都居中 */
.toast-ic { width: 22px; height: 22px; flex: none; color: var(--ok, #16a34a); }
.toast--error .toast-ic { color: var(--danger, #dc2626); }
.toast[hidden] { display: none; }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast button {
  border: 0;
  background: transparent;
  color: var(--brand-2);
  font-weight: 800;
  letter-spacing: 0.04em;
  padding: 4px 6px;
  text-transform: uppercase;
}

/* OTA 更新提示条:进度条 + 百分比 + 完成态 */
.ota-update {
  position: fixed;
  left: 50%;
  bottom: calc(96px + env(safe-area-inset-bottom));
  z-index: 95;
  width: min(360px, calc(100vw - 24px));
  transform: translateX(-50%) translateY(20px);
  opacity: 0;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  transition: opacity 220ms var(--ease), transform 220ms var(--ease);
}
.ota-update[hidden] { display: none; }
.ota-update.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.ota-update .ota-row { display: flex; align-items: center; gap: 11px; }
.ota-update .ota-title { flex: 1; font-size: 14px; font-weight: 700; letter-spacing: -0.01em; }
.ota-update .ota-pct { font-size: 13px; font-weight: 800; color: var(--brand-2); font-feature-settings: "tnum","lnum"; }
.ota-update .ota-ic { flex: none; width: 18px; height: 18px; }
.ota-update:not(.ota-done) .ota-ic {
  border: 2px solid rgba(128,128,128,0.3);
  border-top-color: var(--brand-2);
  border-radius: 50%;
  animation: authspin 0.7s linear infinite;
}
.ota-update.ota-done .ota-ic { display: grid; place-items: center; color: #34d399; font-size: 16px; font-weight: 900; }
.ota-update.ota-done .ota-ic::after { content: "✓"; }
.ota-update .ota-bar { margin-top: 11px; height: 6px; border-radius: 99px; background: rgba(128,128,128,0.2); overflow: hidden; }
.ota-update .ota-bar > i { display: block; height: 100%; width: 0; border-radius: 99px; background: var(--brand-grad); transition: width 250ms var(--ease); }
.ota-update.ota-done .ota-bar > i { background: #34d399; }

/* 「更新已就绪」卡片:半屏遮罩 + 底部弹出卡片,主按钮立即更新 */
.ota-ready {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 16px;
  padding-bottom: calc(20px + env(safe-area-inset-bottom));
  background: rgba(8, 10, 16, 0.55);
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity 240ms var(--ease);
}
.ota-ready[hidden] { display: none; }
.ota-ready.show { opacity: 1; }
.ota-ready-card {
  width: min(420px, 100%);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 26px 22px 18px;
  text-align: center;
  box-shadow: var(--shadow-lg);
  transform: translateY(26px);
  transition: transform 260ms var(--ease);
}
.ota-ready.show .ota-ready-card { transform: translateY(0); }
.ota-ready-ic {
  width: 58px; height: 58px; margin: 0 auto 14px;
  display: grid; place-items: center;
  border-radius: 18px;
  background: var(--brand-grad);
  color: #fff; font-size: 28px; font-weight: 900; line-height: 1;
  box-shadow: 0 8px 20px rgba(255, 106, 61, 0.35);
}
.ota-ready-title { display: block; font-size: 19px; font-weight: 800; letter-spacing: -0.02em; color: var(--ink); }
.ota-ready-body { margin: 8px 4px 20px; font-size: 14px; line-height: 1.5; color: var(--muted); }
.ota-ready-now {
  width: 100%; padding: 14px; border: none; cursor: pointer;
  border-radius: var(--radius-md);
  background: var(--brand-grad); color: #fff;
  font-size: 15px; font-weight: 800; letter-spacing: -0.01em;
  box-shadow: 0 6px 16px rgba(255, 106, 61, 0.3);
}
.ota-ready-now:disabled { opacity: 0.7; }
.ota-ready-later {
  width: 100%; margin-top: 6px; padding: 11px; border: none; cursor: pointer;
  background: transparent; color: var(--muted);
  font-size: 14px; font-weight: 600;
}

/* ── 19. Animations ───────────────────────────────────────────── */
@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes slideUp {
  from { opacity: 0; transform: translateY(20px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    /* iteration-count:1 关键——否则循环 spinner(logo圈/加载圈)变成 0.01ms 转一圈 = 快到飞起。设 1 = 转一次即停(静态) */
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── 动效:按钮加载态(FB 式:文字隐去 → 转圈,颜色随按钮自适应) ── */
/* 隐藏文字但保留行高(font-size:0 会清掉行高→按钮塌扁)。-webkit-text-fill-color
   只让字形透明,color 不变,所以下面 ::after 的 currentColor 仍是真实文字色。 */
.btn-loading, .is-loading, .is-checking { position: relative; pointer-events: none; -webkit-text-fill-color: transparent; }
.btn-loading > *, .is-loading > *, .is-checking > * { visibility: hidden; }
.btn-loading::after, .is-loading::after, .is-checking::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 15px; height: 15px; margin: -8px 0 0 -8px;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
  opacity: 0.85; animation: btnSpin 0.6s linear infinite;
}
@keyframes btnSpin { to { transform: rotate(360deg); } }

/* ── 动效:视图/面板进入 + tab 轻触(可在设置关闭 → body.no-fx) ── */
@keyframes fxViewIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes fxPanelIn { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: none; } }
/* 常驻的 .app-view.active 入场动画已移除,换成一次性 .view-anim-in(同 .content-panel 的做法)*/
.app-view.view-anim-in { animation: fxViewIn 0.26s cubic-bezier(0.22, 0.61, 0.36, 1); will-change: transform, opacity; }
@media (prefers-reduced-motion: reduce) { .app-view.view-anim-in { animation: none; } }
/* .content-panel.active 这里原本挂着 `animation: fxPanelIn`(常驻)。已删除 ——
   面板进场改由 playPanelAnim 打一次性 class 完成(见 .panel-anim-in/-back)。
   留着这条的话元素上仍有常驻动画可被 WebKit 重播,原生端就还得继续关,前功尽弃。 */
/* iOS/原生 WebKit 会在原生 <select> 弹层关闭时「重播」常驻在元素上的入场动画,
   表现为整屏/整卡横向或纵向的鬼影滑动。原生端把所有常驻入场动画全关掉根治;web 保留。
   覆盖:fxViewIn/fxPanelIn(view/panel)· viewIn · drillIn(抽屉横滑,之前漏了)· slideUp(弹窗卡片)。 */
/* 注:.content-panel.active 已从这份名单里移除 —— 它的进场动画改成了一次性 class
   (playPanelAnim,动画结束就摘),元素上不再有常驻动画可被 WebKit 重播,
   所以原生端可以放心保留过渡。其余几条仍是常驻动画,继续关。 */
/* .modal-card / .modal-opening 也已从名单里移除:入场动画本来就是一次性 class
   (markModalOpening,animationend 就摘),静止态没有常驻动画可被 WebKit 重播。
   留在名单里只会让原生端白白失去开关弹窗的过渡感。 */
/* .side-content(抽屉)同样已移除:drillIn 原来是常驻动画,原生端只能整个关掉,
   代价是进抽屉毫无过渡。现在进=一次性 .drill-opening、退=一次性 .drill-menu-in
   (见 playDrillIn / closePanel),没有常驻动画可被重播,原生端可以全开。
   → 名单里现在只剩 #chatView.active 一条。 */
body.native-app #chatView.active { animation: none; }
/* 不做按压跳动:选中只换颜色 + 下划线,稳重 */

/* 关闭特效(低端机):瞬时过渡 + 取消进入动画;加载转圈降级为静态环(仍是"忙"提示) */
body.no-fx *, body.no-fx *::before, body.no-fx *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important; /* 循环 spinner 转一次即停,不再无限加速 */
  transition-duration: 0.01ms !important;
}

/* 点按微反馈:按下轻微缩放,给「按得动」的手感(只绑 :active,不触发原生入场重播鬼影)。
   仅无「减弱动效」偏好时生效;body.no-fx 由上面全局规则自动降级。curated 列表都不用 transform 定位,缩放安全。 */
@media (prefers-reduced-motion: no-preference) {
  .quick-action, .rc-opt, .account-row, .acc-head, .settings-card-head,
  .card-action, .dt-item, .ff-row--switch, .form-actions button, .set-select {
    transition: transform 0.13s cubic-bezier(0.22, 0.61, 0.36, 1), background-color 0.16s ease, border-color 0.16s ease;
  }
  .quick-action:active, .rc-opt:active, .account-row:active, .acc-head:active,
  .settings-card-head:active, .card-action:active, .dt-item:active,
  .form-actions button:active {
    transform: scale(0.95);
    opacity: 0.88;
  }
}

/* ── 20. Focus ─────────────────────────────────────────────────── */
/* 不要黑色焦点描边框(--brand=#111)——点按钮/输入框不再出现黑框「点击特效」。
   超链接同样去掉焦点框与点按高亮。 */
button:focus,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
a:focus,
a:focus-visible,
[role="button"]:focus,
[role="button"]:focus-visible {
  outline: none;
}
a, button, [role="button"] { -webkit-tap-highlight-color: transparent; }

/* ── 21. Responsive ───────────────────────────────────────────── */
@media (max-width: 540px) {
  .app-shell { padding: 0; }
  .phone-app { border-radius: 0; border: 0; min-height: 100vh; }
}

/* ── Native app (Capacitor): true full-bleed, no document rubber-band ──────────
   The shell was built as a desktop "phone mockup" (framed, centered, padded). In
   the native shell we instead pin the document to the screen so the background
   reaches every edge (incl. under the Dynamic Island / home indicator) and the
   whole page can't be dragged. Only the inner .app-view scrolls. Safe-area insets
   are honored by the header / bottom-nav padding (they already use env()). */
body.native-app {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}
body.native-app .app-shell {
  min-height: 0;
  /* 外壳必须和 .phone-app 一起变矮。只让 phone-app 变矮是不够的:外壳仍是整屏高,
     而它是 grid 容器,下面那条 place-items 会把变矮后的 phone-app **居中** ——
     真机实测:phoneAppH 已经正确算成 339px,却被居中到 top=191/bottom=530,
     而键盘顶边在 339,等于把整个 App 又推回了键盘后面(截图里顶部那片空白就是它)。 */
  height: calc(var(--app-h, 100dvh) - var(--kb-h));
  /* ⚠️ 必须显式 stretch。body[data-preview-device="mobile"] .app-shell 里是
     place-items:center(为了在宽窗口里把手机框居中),两条特异性相同、靠源码顺序
     决胜 —— 本条更靠后所以能压住。键盘弹出时绝不能居中,必须贴顶。 */
  place-items: stretch;
  padding: 0;
}
body.native-app .phone-app {
  height: 100%;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

@media (max-width: 380px) {
  .app-view { padding: 14px 14px 24px; }
  .option-grid { grid-template-columns: repeat(2, 1fr); }
}

/* 侧栏账号区:默认隐藏(全局),只有桌面侧栏才显示(见下方 @media 内的 display:flex)。
   注意必须放在 @media 外,否则手机宽度下无规则命中 → 默认 block 漏出到底部。 */
.sidebar-account { display: none; }

/* Desktop preview (toggle via [data-preview-device]) */
@media (min-width: 760px) {
  body:not([data-preview-device="mobile"]) .app-shell { padding: 24px; }
  body:not([data-preview-device="mobile"]) .phone-app {
    width: min(1920px, calc(100vw - 36px));
    min-height: min(820px, calc(100vh - 36px));
    grid-template-columns: 320px minmax(0, 1fr);
    grid-template-rows: auto 1fr auto;
    border-radius: 24px;
    box-shadow: var(--shadow-lg);
  }
  body:not([data-preview-device="mobile"]) .app-header {
    grid-column: 1;
    grid-row: 1 / 2;
    border-right: 1px solid var(--line);
    border-bottom: 0;
    padding: 22px;
    display: grid;
    align-content: start;
    gap: 18px;
  }
  body:not([data-preview-device="mobile"]) .top-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }
  body:not([data-preview-device="mobile"]) .app-view {
    grid-column: 2;
    grid-row: 1 / 3;
    padding: 24px 28px 24px;
  }
  body:not([data-preview-device="mobile"]) #chatView.active {
    padding: 0;
  }
  body:not([data-preview-device="mobile"]) .composer {
    grid-column: 2;
    grid-row: 3;
  }
  body:not([data-preview-device="mobile"]) .bottom-nav {
    grid-column: 1;
    grid-row: 2 / -1;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    border-top: 0;
    gap: 4px;
    padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  }
  /* Desktop: chat sits to the right of the budget % shortcut; center-tab hidden. */
  body:not([data-preview-device="mobile"]) .bottom-nav > .center-tab { display: none; }
  body:not([data-preview-device="mobile"]) .header-budget-chat { width: 100%; }
  body:not([data-preview-device="mobile"]) .header-chat-d {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    padding: 9px 18px;
    border: 0;
    border-radius: 999px;
    background: var(--brand-grad);
    color: #fff;
    font-size: 13px;
    font-weight: 800;
    box-shadow: var(--shadow-md);
    flex-shrink: 0;
    cursor: pointer;
  }
  body:not([data-preview-device="mobile"]) .header-chat-d svg {
    width: 18px; height: 18px;
    fill: none; stroke: currentColor; stroke-width: 2.2;
    stroke-linecap: round; stroke-linejoin: round;
  }
  body:not([data-preview-device="mobile"]) .header-chat-d:hover { filter: brightness(1.06); transform: translateY(-1px); }
  /* Chat 改底部圆形浮钮,贴在浮动搜索框右侧;进入 chat 视图后与浮动搜索一起消失 */
  body:not([data-preview-device="mobile"]) .header-chat-d {
    position: absolute; bottom: 22px; right: 24px; left: auto; top: auto;
    margin-left: 0; padding: 0;
    width: 52px; height: 52px; border-radius: 50%;
    justify-content: center; z-index: 95;
  }
  body:not([data-preview-device="mobile"]) .header-chat-d > b { display: none; }
  body:not([data-preview-device="mobile"]) .header-chat-d svg { width: 23px; height: 23px; }
  body:not([data-preview-device="mobile"]) .phone-app[data-active-view="chat"] .header-chat-d,
  body:not([data-preview-device="mobile"]) .phone-app[data-active-view="chat"] .ov-search { display: none; }
  body:not([data-preview-device="mobile"]) .bottom-nav .nav-money { display: grid; }
  body:not([data-preview-device="mobile"]) .bottom-nav button:not(.nav-money) + .nav-money,
  body:not([data-preview-device="mobile"]) .bottom-nav .nav-settings {
    margin-top: 10px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
  }
  body:not([data-preview-device="mobile"]) .bottom-nav button {
    grid-auto-flow: column;
    justify-content: start;
    align-items: center;
    min-height: 0;
    gap: 12px;
    padding: 10px 14px;
    border-radius: var(--radius-sm);
    font-size: 13px;
  }
  body:not([data-preview-device="mobile"]) .bottom-nav button.active::after { display: none; }
  body:not([data-preview-device="mobile"]) .bottom-nav button.active {
    background: var(--brand-soft);
  }
  /* Desktop sidebar account block — pinned to the bottom of the sidebar */
  body:not([data-preview-device="mobile"]) .sidebar-account {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid var(--line);
  }
  .sidebar-account { display: none; }
  .sidebar-account .sidebar-account-main {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--surface-2, var(--brand-soft));
    cursor: pointer;
    text-align: left;
  }
  .sidebar-account .sidebar-account-main:hover { background: var(--brand-soft); }
  .sidebar-account .sidebar-account-avatar {
    flex-shrink: 0;
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border-radius: 999px;
    background: var(--brand-grad);
    color: #fff;
    font-size: 14px; font-weight: 800;
    text-transform: uppercase;
  }
  .sidebar-account .sidebar-account-meta {
    display: flex; flex-direction: column;
    min-width: 0; gap: 1px; flex: 1;
  }
  .sidebar-account .sidebar-account-email {
    font-size: 12.5px; font-weight: 700;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    max-width: 100%;
  }
  .sidebar-account .sidebar-account-plan {
    font-size: 11px; font-weight: 700; color: var(--brand);
  }
  .sidebar-account .sidebar-account-go {
    width: 16px; height: 16px; flex-shrink: 0;
    fill: none; stroke: var(--ink-soft, currentColor); stroke-width: 2.2;
    stroke-linecap: round; stroke-linejoin: round;
    opacity: .55;
  }
  .sidebar-account .sidebar-account-signout {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--ink-soft, inherit);
    font-size: 12.5px; font-weight: 700;
    cursor: pointer;
  }
  .sidebar-account .sidebar-account-signout:hover {
    border-color: var(--danger, #d33);
    color: var(--danger, #d33);
  }
  body:not([data-preview-device="mobile"]) .overview-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  /* Overview = 2-col dashboard: hero | saving on top, full-width grid below */
  body:not([data-preview-device="mobile"]) #overviewView.active {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 18px;
    align-items: start;
  }
  body:not([data-preview-device="mobile"]) #overviewView.active > .view-heading,
  body:not([data-preview-device="mobile"]) #overviewView.active > .overview-grid {
    grid-column: 1 / -1;
  }
  /* Desktop: recent components that were still single-column on wide screens */
  body:not([data-preview-device="mobile"]) .plan-grid,
  body:not([data-preview-device="mobile"]) .budget-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  body:not([data-preview-device="mobile"]) .input-row select {
    max-width: 300px;
  }
  body:not([data-preview-device="mobile"]) .plan-card { cursor: pointer; }
  body:not([data-preview-device="mobile"]) .plan-card:hover {
    border-color: var(--brand);
    box-shadow: var(--shadow-md);
  }
  /* Desktop: drop only the pull-to-refresh affordance (touch-only gesture).
     The device floatie stays — it's the mobile/desktop preview switcher. */
  body:not([data-preview-device="mobile"]) .pull-refresh {
    display: none !important;
  }
  /* Desktop: reveal row delete on hover instead of swipe gesture */
  body:not([data-preview-device="mobile"]) .swipe-row .swipe-delete {
    z-index: 2;
    inset: 6px 6px 6px auto;
    min-width: 0;
    padding: 0 14px;
    border-radius: var(--radius-sm);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s var(--ease);
  }
  body:not([data-preview-device="mobile"]) .swipe-row:hover .swipe-delete {
    opacity: 1;
    pointer-events: auto;
  }
  /* Desktop: split workspace = full-width content with a horizontal tab bar on
     top (no middle vertical menu). Default-show the first panel until picked. */
  body:not([data-preview-device="mobile"]) .split-workspace {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }
  body:not([data-preview-device="mobile"]) .split-workspace .side-menu {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 0 0 12px;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    background: transparent;
  }
  body:not([data-preview-device="mobile"]) .split-workspace .side-menu button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    width: auto;
    min-height: 0;
    padding: 8px 14px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--card);
  }
  body:not([data-preview-device="mobile"]) .split-workspace .side-menu button::after { content: none; }
  body:not([data-preview-device="mobile"]) .split-workspace .side-menu button strong {
    font-size: 12px;
    color: var(--muted);
    font-weight: 700;
  }
  body:not([data-preview-device="mobile"]) .split-workspace .side-menu button.active {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--ink-strong);
  }
  body:not([data-preview-device="mobile"]) .split-workspace .side-content { display: grid; }
  body:not([data-preview-device="mobile"]) .split-workspace:not(:has(.content-panel.active)) .content-panel:first-child {
    display: grid;
  }
  /* 桌面端菜单与内容是并排常显的(上面那条 display:grid),压根没有「钻进/退出」这回事 ——
     进/退动画在这里只会变成无缘无故的闪一下,全部压掉(内容 drillIn + 菜单 drillMenuIn)。 */
  body:not([data-preview-device="mobile"]) .split-workspace.drill-open .side-content,
  body:not([data-preview-device="mobile"]) .split-workspace.drill-open.drill-opening .side-content,
  body:not([data-preview-device="mobile"]) .split-workspace .side-menu.drill-menu-in { animation: none; }
  body:not([data-preview-device="mobile"]) .view-back { display: none !important; }

  /* Desktop: the 我 (profile/settings) page is a proper two-column master-detail
     — a vertical nav on the left, the active panel on the right — instead of the
     wrapping pill bar the generic .split-workspace rule above produces. The pill
     bar reads as "很乱" once there are a dozen entries. */
  body:not([data-preview-device="mobile"]) .profile-workspace {
    grid-template-columns: 300px minmax(0, 1fr);
    align-items: start;
    gap: 24px;
  }
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu {
    display: grid;
    align-content: start;
    flex-wrap: nowrap;
    gap: 1px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--card);
    position: sticky;
    top: 0;
  }
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu button {
    display: grid;
    /* 标签列按内容取宽(不被截断),数值列吃剩余空间、过长则自己省略 */
    grid-template-columns: auto minmax(0, 1fr);
    width: 100%;
    justify-content: stretch;
    align-items: center;
    gap: 8px;
    min-height: 0;
    padding: 11px 12px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    font-size: 13.5px;
  }
  /* 标签:不省略(优先完整显示) */
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu button > span:first-child {
    overflow: visible;
    text-overflow: clip;
  }
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu button strong {
    grid-column: 2;
    justify-self: end;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 12px;
    color: var(--muted-strong);
  }
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu button > span.menu-value-group {
    grid-column: 2;
    min-width: 0;
    overflow: hidden;
  }
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu button.active {
    background: var(--brand-soft);
    border-color: transparent;
    color: var(--ink-strong);
    font-weight: 700;
  }
  body:not([data-preview-device="mobile"]) .profile-workspace .side-menu button.active strong { color: var(--brand); }
  /* The 资料/设置 segmented control sits neatly above the left nav column,
     not stretched across the full content width. */
  body:not([data-preview-device="mobile"]) #profileView .money-tabs {
    max-width: 320px;
    margin-bottom: 16px;
  }
  /* Desktop: keep add/edit forms + settings from stretching the full content
     width (a single text input spanning ~900px reads as "mobile in a big box").
     Lists/cards already scale fine, so only the form/settings inputs are capped. */
  body:not([data-preview-device="mobile"]) .finance-form {
    max-width: 420px;
  }
  body:not([data-preview-device="mobile"]) .settings-card {
    max-width: 560px;
  }
  /* Desktop only: bills page drops the redundant "money" sub-group (余额/收入/报销/
     备用金 already live in the sidebar money shortcuts). Mobile keeps both groups. */
  body:not([data-preview-device="mobile"]) [data-panel-scope="debt"] .money-tabs { display: none; }
  body:not([data-preview-device="mobile"]) [data-panel-scope="debt"] [data-money-section="money"] { display: none !important; }
  body:not([data-preview-device="mobile"]) [data-panel-scope="debt"] [data-money-section="bills"] { display: inline-flex !important; }
}

/* ── Admin dashboard (standalone /admin.html) ────────────────── */
.admin-wrap { max-width: 1160px; margin: 0 auto; padding: 24px 18px 60px; }
.admin-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.admin-head h1 { font-size: 22px; }
.admin-head-right { display: flex; align-items: center; gap: 10px; }
.admin-lang { display: inline-flex; gap: 2px; background: rgba(255,255,255,.06); border-radius: 999px; padding: 3px; }
.admin-lang button { min-width: 34px; height: 28px; border: 0; border-radius: 999px; background: transparent; color: var(--muted-strong, #94a3b8); font-size: 12px; font-weight: 700; cursor: pointer; }
.admin-lang button.active { background: var(--brand-2, #ff5722); color: #fff; }
.mbr-form { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--line); border-radius: 12px; margin-bottom: 8px; }
.mbr-form input, .mbr-form select { height: 40px; }
.mbr-perms { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center; }
.mbr-perm { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; cursor: pointer; }
.mbr-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.mbr-row b { font-size: 14px; }
.cp-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; align-items: end; padding: 12px; border: 1px solid var(--line); border-radius: 12px; margin-bottom: 8px; }
.cp-form h4 { grid-column: 1 / -1; margin: 0; font-size: 13px; color: var(--muted); }
.cp-form label { display: grid; gap: 5px; font-size: 12.5px; color: var(--muted); }
.cp-form input, .cp-form select { height: 38px; border: 1px solid var(--line); border-radius: 10px; padding: 0 10px; background: var(--card); color: var(--ink); }
.cp-form .cp-active { flex-direction: row; align-items: center; gap: 6px; }
.cp-form .cp-active input { height: auto; }
.cp-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.cp-acts { display: flex; gap: 6px; flex: none; }
.cp-acts button { min-height: 32px; padding: 0 12px; font-size: 12.5px; }
/* 用户端优惠券卡(Saya → 优惠券) */
.coupons-list { display: grid; gap: 10px; }
.coupon-card { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--card); cursor: pointer; }
.coupon-card:active { transform: scale(0.99); }
.coupon-disc { flex: none; min-width: 52px; height: 52px; border-radius: 12px; display: grid; place-items: center; background: var(--brand-soft); color: var(--brand-2); font-weight: 800; font-size: 14px; padding: 0 8px; }
.coupon-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.coupon-body b { font-size: 14.5px; color: var(--ink); }
.coupon-body small { font-size: 12px; color: var(--muted); }
.coupon-code { flex: none; font-weight: 800; font-size: 12.5px; color: var(--brand-2); border: 1px dashed var(--brand-ring); border-radius: 8px; padding: 4px 8px; letter-spacing: .04em; }
.coupon-go { flex: none; color: var(--muted); font-size: 18px; }
/* 「该不该买」结果里的推荐卡(平替/比价) */
.reco-block { margin-top: 12px; display: grid; gap: 8px; }
.reco-head { font-size: 12.5px; font-weight: 700; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.reco-adtag { font-size: 10px; font-weight: 700; color: var(--muted); background: var(--soft); border-radius: 6px; padding: 1px 6px; }
.beta-tag { display: inline-block; font-size: 10px; font-weight: 800; letter-spacing: .3px; color: #fff; background: var(--brand-2); border-radius: 6px; padding: 1px 6px; vertical-align: middle; }
.reco-card { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--card); cursor: pointer; }
.reco-card:active { transform: scale(0.99); }
.reco-body { flex: 1; min-width: 0; display: grid; gap: 1px; }
.reco-body b { font-size: 14px; color: var(--ink); }
.reco-body small { font-size: 11.5px; color: var(--muted); }
.reco-meta { color: var(--brand-2) !important; }
.reco-price { font-size: 13px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.reco-price s { color: var(--muted); font-weight: 500; margin-left: 5px; }
.reco-tag { flex: none; font-size: 10.5px; font-weight: 700; color: var(--brand-2); background: var(--brand-soft); border-radius: 8px; padding: 3px 8px; }
.admin-login { display: flex; justify-content: center; padding: 6vh 0 0; }
.admin-login-card { width: 100%; max-width: 380px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 30px 26px; box-shadow: 0 18px 50px rgba(15, 23, 42, 0.12); display: grid; gap: 14px; }
.admin-login-brand { margin-bottom: 2px; }
.admin-login-hint { font-size: 13px; color: var(--muted); margin: 0; line-height: 1.5; }
.admin-login form { display: flex; flex-direction: column; gap: 10px; }
.admin-login input { width: 100%; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--soft); color: var(--ink); font-size: 14px; }
.admin-login input:focus { outline: none; border-color: var(--brand-2); background: var(--card); }
.admin-login button { width: 100%; padding: 12px 16px; border: 0; border-radius: var(--radius-md); background: var(--brand-grad); color: #fff; font-weight: 700; font-size: 15px; cursor: pointer; }
.admin-login button:active { transform: scale(0.99); }
.admin-login .admin-msg { text-align: center; font-size: 13px; }
.admin-user button, .admin-setplan button, .admin-login + section button { padding: 9px 16px; border: 0; border-radius: var(--radius-sm); background: var(--brand-grad); color: #fff; font-weight: 700; cursor: pointer; }
.admin-msg { font-size: 13px; color: var(--muted); }
.admin-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 12px; }
.admin-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px; margin-bottom: 12px; }
.admin-card h3 { font-size: 14px; margin-bottom: 8px; }
.admin-card.stat { display: grid; gap: 4px; }
.admin-stat-label { font-size: 12px; color: var(--muted); }
.admin-stat-value { font-size: 22px; font-weight: 800; }
.admin-card form { display: flex; gap: 8px; margin-bottom: 8px; }
.admin-card form input { flex: 1; padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--ink); }
.admin-plan-bars { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.admin-plan-bar { display: grid; gap: 2px; padding: 10px; border-radius: var(--radius-sm); background: var(--soft); text-align: center; }
.admin-plan-bar span { font-size: 11px; color: var(--muted); text-transform: uppercase; }
.admin-plan-bar strong { font-size: 18px; }
.admin-warn { color: var(--warn); display: block; margin-top: 8px; }
.admin-user { display: grid; gap: 6px; margin-top: 10px; }
.admin-setplan { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
.admin-setplan select { padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--ink); }
.admin-setplan input { padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--ink); }
.adm-ban-badge { font-size: 11px; font-weight: 800; color: #fff; background: var(--danger); padding: 2px 8px; border-radius: 999px; }
.admin-user button.adm-danger, .admin-setplan button.adm-danger { background: var(--danger); }
.push-form { display: grid; gap: 10px; max-width: 460px; margin-top: 12px; }
.push-form input, .push-form textarea, .push-form select { padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--ink); font: inherit; }
.push-form textarea { resize: vertical; }
.push-form button { padding: 11px 16px; border: 0; border-radius: var(--radius-sm); background: var(--brand-grad); color: #fff; font-weight: 700; cursor: pointer; }

/* UI 润色:卡片阴影 + 指标强调色 */
.admin-card { box-shadow: 0 1px 4px rgba(0,0,0,0.16); }
.admin-stat-value { color: var(--brand-2); letter-spacing: -0.01em; }
.admin-user { line-height: 1.7; }

/* 运行时配置编辑 */
.cfg-group { margin-top: 16px; }
.cfg-group h4 { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin-bottom: 9px; }
.cfg-row { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.cfg-row label { flex: 1; font-size: 13.5px; color: var(--ink); }
.cfg-row input { width: 150px; padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--ink); font-feature-settings: "tnum","lnum"; }
.cfg-row button { padding: 8px 15px; border: 0; border-radius: var(--radius-sm); background: var(--brand-grad); color: #fff; font-weight: 700; cursor: pointer; }
@media (max-width: 560px) {
  .cfg-row { flex-wrap: wrap; }
  .cfg-row label { flex-basis: 100%; }
  .cfg-row input { flex: 1; width: auto; }
}
@media (max-width: 560px) { .admin-grid { grid-template-columns: 1fr; } .admin-plan-bars { grid-template-columns: repeat(2, 1fr); } }

/* ── admin 总览重构(彩色图标 stat / 套餐表 / AI 环形 / 广告 / 营收成本 / 参数)── */
.adm-tone-purple { --tone:#7c3aed; --tone-bg:rgba(124,58,237,.13); }
.adm-tone-blue   { --tone:#3b82f6; --tone-bg:rgba(59,130,246,.13); }
.adm-tone-amber  { --tone:#d97706; --tone-bg:rgba(245,158,11,.16); }
.adm-tone-violet { --tone:#8b5cf6; --tone-bg:rgba(139,92,246,.13); }
.adm-tone-orange { --tone:#ea580c; --tone-bg:rgba(255,138,61,.16); }
.adm-tone-green  { --tone:#059669; --tone-bg:rgba(16,163,94,.13); }
.adm-tone-red    { --tone:#dc2626; --tone-bg:rgba(239,68,68,.12); }
.adm-up { color: var(--ok, #059669); } .adm-down { color: var(--danger, #dc2626); }

.adm-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 16px; }
.adm-stat { display: flex; align-items: flex-start; gap: 14px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 18px; }
.adm-stat.detail-link { cursor: pointer; }
.adm-stat-ic { flex: none; width: 46px; height: 46px; border-radius: 13px; display: grid; place-items: center; background: var(--tone-bg); color: var(--tone); }
.adm-stat-ic svg { width: 24px; height: 24px; }
.adm-stat-body { min-width: 0; }
.adm-stat-label { font-size: 13px; color: var(--muted); }
.adm-stat-val { display: block; font-size: 28px; font-weight: 800; letter-spacing: -.02em; margin: 2px 0; }
.adm-stat-sub { font-size: 12.5px; color: var(--muted); }

.adm-plan-head, .adm-plan-row { display: grid; grid-template-columns: 28px 1fr auto 130px 56px; align-items: center; gap: 12px; }
.adm-plan-head { font-size: 11px; color: var(--muted); text-transform: uppercase; padding: 6px 0; }
.adm-plan-head span:nth-child(2) { grid-column: 3; text-align: right; } .adm-plan-head span:nth-child(4) { grid-column: 5; text-align: right; }
.adm-plan-row { padding: 9px 0; border-top: 1px solid var(--line); font-size: 14px; }
.adm-plan-badge { width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; font-size: 12px; font-weight: 800; background: var(--tone-bg); color: var(--tone); }
.adm-plan-name { font-weight: 700; } .adm-plan-n { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.adm-plan-bar { height: 8px; border-radius: 999px; background: var(--soft); overflow: hidden; }
.adm-plan-bar i { display: block; height: 100%; background: var(--tone); border-radius: 999px; }
.adm-plan-pct { text-align: right; font-size: 13px; color: var(--muted-strong); font-variant-numeric: tabular-nums; }
.adm-plan-total { font-weight: 800; } .adm-plan-total .adm-plan-name, .adm-plan-total .adm-plan-n, .adm-plan-total .adm-plan-pct { color: var(--ink); }

.adm-ai-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 6px; }
.adm-ai-left { display: flex; align-items: center; gap: 12px; }
.adm-ai-badge { width: 46px; height: 46px; border-radius: 13px; display: grid; place-items: center; font-weight: 800; font-size: 15px; background: rgba(59,130,246,.13); color: #3b82f6; }
.adm-ai-units { font-size: 24px; font-weight: 800; }
.adm-donut { width: 96px; height: 96px; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; flex: none; }
.adm-donut::after { content: ""; position: absolute; inset: 13px; border-radius: 50%; background: var(--card); }
.adm-donut span { position: relative; z-index: 1; font-size: 18px; font-weight: 800; }
.adm-donut small { position: relative; z-index: 1; font-size: 10px; color: var(--muted); margin-top: -2px; }
.adm-ai-cost { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); color: var(--muted); display: flex; justify-content: space-between; }
.adm-ai-cost strong { color: var(--ink); font-size: 16px; }
.adm-ai-budget { display: flex; align-items: center; gap: 10px; margin-top: 10px; font-size: 12.5px; color: var(--muted-strong); }
.adm-ai-budget > span:first-child { flex: none; }
.adm-ai-bar { flex: 1; height: 7px; border-radius: 999px; background: var(--soft); overflow: hidden; }
.adm-ai-bar i { display: block; height: 100%; border-radius: 999px; background: #34d399; }
.adm-ai-bar i.warn { background: #f59e0b; }
.adm-ai-bar i.over { background: #ef4444; }

.adm-adtiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 4px 0 14px; }
.adm-adtile { background: var(--soft); border-radius: 12px; padding: 12px; text-align: left; }
.adm-adtile span { font-size: 11.5px; color: var(--muted); display: block; }
.adm-adtile strong { font-size: 20px; font-weight: 800; }
.adm-subh { font-size: 12px; color: var(--muted); text-transform: uppercase; margin: 8px 0 6px; }
.adm-slot-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.adm-slot-tbl th { text-align: left; font-size: 11px; color: var(--muted); text-transform: uppercase; padding: 6px 8px; }
.adm-slot-tbl td { padding: 8px; border-top: 1px solid var(--line); font-variant-numeric: tabular-nums; }
.adm-slot-tbl th:not(:first-child), .adm-slot-tbl td:not(:first-child) { text-align: right; }

.adm-rev-grid { display: grid; grid-template-columns: 1fr 1.3fr 1fr; gap: 12px; }
.adm-rev-box { border-radius: 14px; padding: 14px; }
.adm-rev-box span { font-size: 12.5px; color: var(--muted); } .adm-rev-box > strong { display: block; font-size: 22px; font-weight: 800; margin-top: 3px; }
.adm-rev-box small { font-size: 11.5px; color: var(--muted); }
.adm-rev-income { background: rgba(16,163,94,.08); cursor: pointer; }
.adm-rev-cost { background: rgba(239,68,68,.06); }
.adm-rev-cost ul { list-style: none; margin: 8px 0 0; padding: 0; font-size: 12px; color: var(--muted); }
.adm-rev-cost li { display: flex; justify-content: space-between; padding: 2px 0; } .adm-rev-cost li b { color: var(--ink); font-weight: 700; }
.adm-rev-net { background: var(--soft); }

.adm-params { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px; }
.adm-params label { display: grid; gap: 6px; font-size: 12.5px; color: var(--muted); }
.adm-inp { display: inline-flex; align-items: center; gap: 6px; }
.adm-inp input { width: 150px; height: 42px; border: 1px solid var(--line); border-radius: 12px; padding: 0 12px; background: var(--card); color: var(--ink); }
.adm-inp em { color: var(--muted); font-style: normal; }
.adm-save { height: 42px; padding: 0 22px; border: 0; border-radius: 12px; background: var(--brand-2); color: #fff; font-weight: 800; cursor: pointer; margin-left: auto; }
.adm-note { text-align: center; color: var(--muted); font-size: 12.5px; margin: 18px 0 8px; }
.adm-exp { min-height: 32px; padding: 0 12px; font-size: 12.5px; }
.adm-sim { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; align-items: end; }
.adm-sim label { display: grid; gap: 5px; font-size: 12.5px; color: var(--muted); }
.adm-sim input { height: 40px; border: 1px solid var(--line); border-radius: 10px; padding: 0 10px; background: var(--card); color: var(--ink); font-variant-numeric: tabular-nums; }
.adm-sim fieldset { grid-column: 1 / -1; border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.adm-sim fieldset legend { font-size: 12px; color: var(--muted); padding: 0 6px; }
.adm-sim-out { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 14px; }
.adm-sim-out > div { background: var(--soft); border-radius: 12px; padding: 12px 14px; }
.adm-sim-out span { font-size: 12px; color: var(--muted); display: block; }
.adm-sim-out strong { font-size: 22px; font-weight: 800; }

/* ── 独立订阅/支付页 /pay ── */
.pay-wrap { max-width: 760px; margin: 0 auto; padding: 20px 16px 48px; }
.pay-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; }
.pay-brand { display: inline-flex; align-items: center; gap: 9px; font-weight: 900; letter-spacing: .08em; font-size: 18px; color: var(--ink); }
.pay-logo { width: 30px; height: 30px; color: var(--ink); }
.pay-lang { display: inline-flex; gap: 2px; background: var(--soft); border-radius: 999px; padding: 3px; }
.pay-lang button { min-width: 34px; height: 28px; border: 0; border-radius: 999px; background: transparent; color: var(--muted-strong); font-size: 12px; font-weight: 700; cursor: pointer; }
.pay-lang button.active { background: var(--brand-2); color: #fff; }
.pay-card { background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 24px; box-shadow: 0 12px 40px rgba(15,23,42,.06); }
.pay-card h1 { font-size: 22px; font-weight: 800; margin: 0 0 4px; }
.pay-sub { color: var(--muted); margin: 0 0 16px; }
.pay-form { display: flex; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.pay-form input { flex: 1; min-width: 200px; height: 46px; border: 1px solid var(--line); border-radius: 12px; padding: 0 14px; font-size: 15px; background: var(--card); color: var(--ink); }
.pay-form button { height: 46px; padding: 0 22px; border: 0; border-radius: 12px; background: var(--brand-2); color: #fff; font-weight: 800; cursor: pointer; }
.pay-msg { color: var(--muted); font-size: 13.5px; margin: 10px 0 0; }
.pay-cycle { display: inline-flex; gap: 4px; background: var(--soft); border-radius: 999px; padding: 4px; margin: 6px 0 18px; }
.pay-cycle button { border: 0; background: transparent; color: var(--muted-strong); height: 34px; padding: 0 16px; border-radius: 999px; font-size: 13px; font-weight: 700; cursor: pointer; }
.pay-cycle button.active { background: var(--card); color: var(--ink); box-shadow: 0 1px 4px rgba(15,23,42,.12); }
.pay-plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.pay-plan { border: 1px solid var(--line); border-radius: 16px; padding: 18px; display: grid; gap: 10px; text-align: center; }
.pay-plan--gold { border-color: var(--brand-2); box-shadow: 0 0 0 1px var(--brand-2) inset; }
.pay-plan-name { font-weight: 800; font-size: 16px; }
.pay-plan-price { font-size: 24px; font-weight: 800; font-variant-numeric: tabular-nums; }
.pay-plan-price em { font-size: 12px; font-weight: 600; color: var(--muted); font-style: normal; }
.pay-plan button { height: 44px; border: 0; border-radius: 12px; background: var(--brand-grad); color: #fff; font-weight: 800; cursor: pointer; }
.pay-plan button:disabled { opacity: .6; }
.pay-link { background: none; border: 0; color: var(--muted); text-decoration: underline; cursor: pointer; margin-top: 16px; font-size: 13px; }
@media (max-width: 560px) { .pay-plans { grid-template-columns: 1fr; } }
/* PDF = 打印当前报表:隐藏导航/头部控件/登录,只留激活 pane */
@media print {
  .admin-tabs, .admin-head-right, .admin-login, .adm-note { display: none !important; }
  .admin-pane { display: block !important; }
  .admin-pane[hidden] { display: none !important; }
  .admin-wrap { padding: 0 !important; }
  .admin-card, .adm-stat { break-inside: avoid; }
}
@media (max-width: 720px) {
  .adm-stats { grid-template-columns: repeat(2, 1fr); }
  .adm-rev-grid { grid-template-columns: 1fr; }
  .adm-adtiles { grid-template-columns: repeat(2, 1fr); }
  .adm-plan-head, .adm-plan-row { grid-template-columns: 26px 1fr auto 60px 48px; gap: 8px; }
  .adm-plan-bar { display: none; }
}

/* admin analytics */
.ana-trend { display: flex; align-items: flex-end; gap: 6px; height: 80px; }
.ana-bar { display: grid; justify-items: center; gap: 4px; flex: 1; }
.ana-bar span { display: block; width: 100%; background: var(--brand-grad); border-radius: 3px 3px 0 0; }
.ana-bar small { font-size: 10px; color: var(--muted); }
.ana-hours { display: grid; grid-template-columns: repeat(24, 1fr); gap: 2px; }
.ana-hours i { display: block; height: 22px; border-radius: 2px; background: var(--brand-2); }
.ana-geo { display: inline-block; padding: 3px 8px; border-radius: 999px; background: var(--soft); margin: 2px; font-size: 13px; }
.ana-miss { margin: 0; padding-left: 18px; display: grid; gap: 4px; font-size: 13px; }
.ana-miss li { color: var(--ink); }

/* admin faq */
.admin-faq-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.faq-rule { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 8px; display: grid; gap: 4px; }
.faq-rule p { font-size: 14px; }
.faq-rule-btns { display: flex; gap: 8px; margin-top: 4px; }
.faq-rule-btns button { padding: 6px 12px; border: 0; border-radius: var(--radius-sm); background: var(--brand-grad); color: #fff; font-weight: 700; font-size: 12px; cursor: pointer; }
.faq-rule-btns button.secondary-button { background: var(--soft); color: var(--ink); }

/* admin tabs */
/* 后台导航:桌面左侧竖排侧边栏 + 右侧内容;手机回退顶部横向滚动条 */
.admin-shell { display: flex; align-items: flex-start; gap: 22px; }
.admin-tabs { display: flex; flex-direction: column; gap: 4px; flex: none; width: 150px; position: sticky; top: 16px; }
.admin-tab { padding: 9px 14px; border: 1px solid transparent; border-radius: 10px; background: transparent; color: var(--muted-strong); font-size: 14px; font-weight: 700; cursor: pointer; text-align: left; width: 100%; transition: all .15s var(--ease); }
.admin-tab:hover { background: var(--soft); }
.admin-tab.active { background: var(--brand-grad); color: #fff; border-color: transparent; box-shadow: 0 6px 16px -8px var(--brand); }
.admin-panes { flex: 1; min-width: 0; }
.admin-pane[hidden] { display: none; }
@media (max-width: 860px) {
  .admin-shell { flex-direction: column; gap: 14px; }
  .admin-tabs { flex-direction: row; width: auto; gap: 6px; position: static; overflow-x: auto; flex-wrap: nowrap; border-bottom: 1px solid var(--line); padding-bottom: 10px; -webkit-overflow-scrolling: touch; }
  .admin-tab { flex: none; width: auto; border-radius: 999px; border-color: var(--line); background: var(--card); }
  .admin-panes { width: 100%; }
}

/* 手机端(≤600px):把 admin 里所有多列网格收成单/双列、宽表可横滚,消除挤压与横向溢出 */
@media (max-width: 600px) {
  .admin-wrap { padding: 16px 12px 48px; }
  .adm-stats { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .adm-stat { padding: 13px; gap: 10px; border-radius: 14px; }
  .adm-stat-ic { width: 38px; height: 38px; border-radius: 11px; }
  .adm-stat-ic svg { width: 20px; height: 20px; }
  .adm-stat-val { font-size: 20px; }
  .adm-adtiles { grid-template-columns: repeat(2, 1fr); }
  .adm-rev-grid { grid-template-columns: 1fr; }
  .adm-plan-head, .adm-plan-row { grid-template-columns: 24px minmax(0, 1fr) auto 60px 40px; column-gap: 8px; }
  .adm-params { gap: 10px; }
  .admin-card { padding: 14px; }
  .admin-pane table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* admin cost */
.admin-cost-list { margin: 6px 0; padding-left: 18px; font-size: 13px; display: grid; gap: 2px; }
.admin-cost-edit { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.admin-cost-edit label { font-size: 12px; color: var(--muted); display: grid; gap: 2px; }
.admin-cost-edit input { width: 110px; padding: 7px 9px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--ink); }
.admin-cost-edit button { padding: 8px 14px; border: 0; border-radius: var(--radius-sm); background: var(--brand-grad); color: #fff; font-weight: 700; cursor: pointer; align-self: end; }

/* admin analytics horizontal-bar ranking */
.ana-row { display: grid; grid-template-columns: 80px 1fr 36px; align-items: center; gap: 8px; margin: 4px 0; font-size: 13px; }
.ana-row-k { color: var(--muted-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ana-row-bar { background: var(--soft); border-radius: 999px; height: 10px; overflow: hidden; }
.ana-row-bar i { display: block; height: 100%; background: var(--brand-grad); border-radius: 999px; }
.ana-row-n { text-align: right; font-weight: 700; }

/* admin detail drill-down */
.detail-link { cursor: pointer; transition: border-color .15s var(--ease), transform .1s var(--ease); }
.detail-link:hover { border-color: var(--brand-2); }
.detail-link:active { transform: scale(.99); }
/* z-index 要盖过 Leaflet 地图控件(默认 z-index:1000),否则明细弹窗会被地图透出遮挡 */
.admin-modal { position: fixed; inset: 0; background: rgba(0,0,0,.5); display: grid; place-items: center; z-index: 2000; padding: 16px; }
.admin-modal[hidden] { display: none; }
.admin-modal-card { background: var(--card); border-radius: var(--radius); width: min(560px, 100%); max-height: 80vh; overflow: auto; padding: 18px; }
.admin-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; position: sticky; top: -18px; background: var(--card); padding-top: 4px; }
.admin-modal-head button { border: 0; background: var(--soft); width: 30px; height: 30px; border-radius: 50%; cursor: pointer; color: var(--ink); font-size: 14px; }
.detail-row { padding: 9px 0; border-bottom: 1px solid var(--line); display: grid; gap: 3px; font-size: 13px; }
.detail-row:last-child { border-bottom: 0; }

/* app version footer label */
.app-version-label { text-align: center; font-size: 11px; color: var(--muted); margin-top: 0; }
.app-version-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
}

/* admin geo map */
#adminMap { height: 360px; border-radius: var(--radius-sm); overflow: hidden; background: var(--soft); }
.leaflet-popup-content { font-size: 13px; }

/* 作战室看板:暗色底 + 发光脉冲点 + 网格/扫描线/边角框 + LIVE 条 */
.wr-wrap { position: relative; height: 360px; border-radius: 12px; overflow: hidden; border: 1px solid rgba(255,87,34,.28); background: #0a0e14; }
.wr-wrap #adminMap { height: 100%; border-radius: 0; background: #0a0e14; }
.wr-grid { position: absolute; inset: 0; pointer-events: none; z-index: 450; background-image: linear-gradient(rgba(255,87,34,.07) 1px, transparent 1px), linear-gradient(90deg, rgba(255,87,34,.07) 1px, transparent 1px); background-size: 40px 40px; }
.wr-scan { position: absolute; left: 0; right: 0; top: 0; height: 2px; pointer-events: none; z-index: 999; background: linear-gradient(90deg, transparent, rgba(255,87,34,.55), transparent); animation: wrScan 5.5s linear infinite; }
@keyframes wrScan { 0% { top: 0; } 100% { top: 100%; } }
.wr-corner { position: absolute; width: 16px; height: 16px; border: 2px solid #ff5722; z-index: 1001; pointer-events: none; }
.wr-corner.tl { top: 8px; left: 8px; border-right: 0; border-bottom: 0; }
.wr-corner.tr { top: 8px; right: 8px; border-left: 0; border-bottom: 0; }
.wr-corner.bl { bottom: 8px; left: 8px; border-right: 0; border-top: 0; }
.wr-corner.br { bottom: 8px; right: 8px; border-left: 0; border-top: 0; }
.wr-head { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 1001; display: flex; gap: 8px; align-items: center; background: rgba(10,14,20,.72); border: 1px solid rgba(255,87,34,.3); border-radius: 999px; padding: 4px 12px; font: 700 12px/1 ui-monospace, "SF Mono", Menlo, monospace; color: #ffae8a; white-space: nowrap; }
.wr-live { display: flex; align-items: center; gap: 5px; color: #ff5722; }
.wr-live i { width: 7px; height: 7px; border-radius: 50%; background: #ff5722; box-shadow: 0 0 6px #ff5722; animation: wrBlink 1.2s infinite; }
@keyframes wrBlink { 50% { opacity: .25; } }
.wr-dot { display: block; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #ffb38a, #ff5722 60%); box-shadow: 0 0 14px 3px rgba(255,87,34,.65); position: relative; }
.wr-dot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; border: 1px solid rgba(255,87,34,.8); animation: wrPulse 2.2s ease-out infinite; }
@keyframes wrPulse { 0% { transform: scale(1); opacity: .85; } 100% { transform: scale(2.8); opacity: 0; } }
.wr-full { position: absolute; top: 8px; right: 8px; z-index: 1002; width: 30px; height: 30px; display: grid; place-items: center; border: 1px solid rgba(255,87,34,.3); border-radius: 8px; background: rgba(10,14,20,.72); color: #ffae8a; cursor: pointer; }
.wr-full svg { width: 16px; height: 16px; }
.wr-full:hover { background: rgba(255,87,34,.2); }
.wr-wrap:fullscreen { height: 100vh; width: 100vw; border-radius: 0; }
.wr-wrap:fullscreen #adminMap { height: 100vh; }

/* 大屏模式:全屏深色总览 */
.adm-bs { position: fixed; inset: 0; z-index: 2147483646; color: #fff; display: grid; grid-template-rows: auto auto 1fr; gap: 16px; padding: 20px 24px 24px; background: radial-gradient(80% 60% at 10% 0%, rgba(255,87,34,.1), transparent 55%), linear-gradient(160deg, #11151f, #07090f); }
.adm-bs[hidden] { display: none; }
.adm-bs-top { display: flex; align-items: center; gap: 16px; }
.adm-bs-title { font-size: 22px; font-weight: 800; letter-spacing: .04em; }
.adm-bs-clock { margin-left: auto; font: 700 15px/1 ui-monospace, "SF Mono", Menlo, monospace; color: #ffae8a; }
.adm-bs-close { width: 38px; height: 38px; border-radius: 10px; border: 1px solid rgba(255,255,255,.18); background: rgba(255,255,255,.06); color: #fff; font-size: 18px; cursor: pointer; }
.adm-bs-close:hover { background: rgba(255,87,34,.2); }
.adm-bs-stats { display: grid; grid-template-columns: repeat(8, 1fr); gap: 12px; }
@media (max-width: 1200px) { .adm-bs-stats { grid-template-columns: repeat(4, 1fr); } }
.adm-bs-empty { font-size: 12px; color: rgba(255,255,255,.5); margin: 2px 0; }
.bs-spark { width: 100%; height: 56px; display: block; }
.adm-bs-spark-cap { margin: 4px 0 0; font-size: 11px; color: rgba(255,255,255,.5); text-align: right; }
.adm-bs-warn { grid-column: 1 / -1; padding: 10px 16px; border-radius: 12px; font-size: 13px; font-weight: 700; background: rgba(245,158,11,.16); border: 1px solid rgba(245,158,11,.45); color: #fbbf24; }
.adm-bs-warn.over { background: rgba(239,68,68,.16); border-color: rgba(239,68,68,.5); color: #fca5a5; }
.adm-bs-tile { background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08); border-radius: 14px; padding: 13px 15px; display: grid; gap: 3px; }
.adm-bs-tlabel { font-size: 11.5px; color: rgba(255,255,255,.6); }
.adm-bs-tval { font-size: 25px; font-weight: 800; color: #fff; font-variant-numeric: tabular-nums; }
.adm-bs-tile small { font-size: 11px; color: rgba(255,255,255,.5); }
.adm-bs-body { display: grid; grid-template-columns: 2.2fr 1fr; gap: 16px; min-height: 0; }
.adm-bs-mapwrap { position: relative; border-radius: 16px; overflow: hidden; border: 1px solid rgba(255,87,34,.28); background: #0a0e14; min-height: 0; }
.adm-bs-mapwrap #bsMap { width: 100%; height: 100%; background: #0a0e14; }
.adm-bs-side { background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08); border-radius: 16px; padding: 16px 18px; overflow: auto; }
.adm-bs-side h4 { margin: 0 0 12px; font-size: 14px; color: #fff; }
.adm-bs-prow { display: grid; grid-template-columns: 72px 1fr 46px; align-items: center; gap: 10px; margin-bottom: 11px; }
.adm-bs-pname { font-size: 12px; font-weight: 700; color: rgba(255,255,255,.8); }
.adm-bs-pbar { height: 8px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden; }
.adm-bs-pbar i { display: block; height: 100%; border-radius: 999px; }
.adm-bs-ppct { font-size: 12px; font-weight: 700; text-align: right; color: rgba(255,255,255,.7); }
.adm-bs-kv { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 7px 0; border-bottom: 1px solid rgba(255,255,255,.07); font-size: 12.5px; }
.adm-bs-kv span { color: rgba(255,255,255,.65); }
.adm-bs-kv b { color: #fff; font-variant-numeric: tabular-nums; }
.adm-bs-kv b.adm-up { color: #34d399; }
.adm-bs-kv b.adm-down { color: #f87171; }
@media (max-width: 900px) { .adm-bs-stats { grid-template-columns: repeat(3, 1fr); } .adm-bs-body { grid-template-columns: 1fr; } }

/* Auth resolving: hide account buttons + neutralize status to avoid a
   "signed out → signed in" flash on every page load. */
body.auth-pending #accountSignIn,
body.auth-pending #accountSignOut { visibility: hidden; }
body.auth-pending #accountStatus .account-status-label { opacity: 0; }

/* legal docs (terms / privacy) */
.legal-doc { max-width: 600px; margin: 0 auto; padding: 14px 16px 80px; }
/* 嵌入 App(?embed):隐藏页面自带返回/hero,白底,由 App 的 drill 头接管 */
html.embed body { background: var(--soft); }
html.embed .legal-back, html.embed .legal-hero { display: none; }
html.embed .legal-doc { padding: 4px 16px 40px; }
.legal-back { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 10px; color: var(--muted); font-weight: 700; font-size: 13px; text-decoration: none; }
.legal-back:hover { color: var(--ink); }
/* 品牌头:App 风格(浅色居中,替掉深色 web hero) */
.legal-hero {
  display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
  padding: 6px 0 18px; margin-bottom: 14px;
  border-radius: 0; color: var(--ink-strong);
  background: none; box-shadow: none;
}
.legal-hero-brand { display: flex; align-items: center; gap: 9px; }
.legal-hero-brand .brand-mark { width: 30px; height: 30px; color: var(--brand-2); }
.legal-hero-brand .brand-mark svg { width: 100%; height: 100%; }
.legal-hero-brand strong { font-size: 15px; letter-spacing: 0.06em; color: var(--ink-strong); }
.legal-hero h1 { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.2; color: var(--ink-strong); }
.legal-updated { display: inline-block; align-self: center; font-size: 11.5px; font-weight: 700; color: var(--muted); background: var(--soft); padding: 4px 12px; border-radius: 999px; }
.legal-doc h1 { font-size: 22px; } /* fallback if no hero */
/* 条款/隐私页语言 tab:椭圆浮在透明(soft)底上,去掉白底 track 与阴影,下方留白再接正文卡片 */
.legal-lang-tabs { background: transparent; box-shadow: none; padding: 0; margin: 2px 0 16px; }
/* 卡片式分节:无边框 + 阴影(App 风格) */
.legal-doc > section { margin-bottom: 12px; padding: 16px 18px; border: 0; border-radius: var(--radius); background: var(--card); box-shadow: var(--shadow-sm); }
.legal-doc h2 { font-size: 16px; margin-bottom: 12px; color: var(--ink-strong); display: flex; align-items: center; gap: 9px; }
.legal-doc h2::before { content: ""; width: 4px; height: 17px; border-radius: 2px; background: var(--brand-grad); flex: none; }
.legal-doc h3 { font-size: 14px; font-weight: 700; margin: 14px 0 4px; color: var(--brand-2); }
.legal-doc p { font-size: 14px; line-height: 1.65; color: var(--ink); margin-bottom: 4px; }
.legal-doc section > p + h3 { margin-top: 18px; }
/* 中文段对普通(印尼)用户折叠收起,展开后内部 h3/p 沿用 legal-doc 样式 */
.legal-zh { margin-bottom: 32px; }
.legal-zh > summary { font-size: 18px; font-weight: 700; color: var(--brand-2); cursor: pointer; list-style: revert; }
.legal-zh[open] > summary { margin-bottom: 12px; }
.legal-links { text-align: center; font-size: 12px; margin-top: 12px; }
.legal-links a { color: var(--muted); }
/* 关于:法律链接 — 干净整行(图标+文字+箭头,无边框,细分隔线) */
.legal-bar { display: grid; margin-top: 8px; }
.legal-bar-item { display: flex; align-items: center; gap: 13px; padding: 14px 4px; color: var(--ink); font-weight: 600; font-size: 15px; text-decoration: none; }
.legal-bar-item + .legal-bar-item { border-top: 1px solid var(--line); }
.legal-bar-item .lb-ic { width: 21px; height: 21px; flex: none; color: var(--muted-strong); fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.legal-bar-item span { flex: 1; }
.legal-bar-item .lb-chev { width: 17px; height: 17px; flex: none; color: var(--muted); fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.legal-bar-item:active { opacity: 0.55; }

/* auth consent checkbox */
.auth-consent { display: flex; gap: 8px; align-items: flex-start; font-size: 12px; color: var(--muted-strong); margin: 4px 0 2px; line-height: 1.5; }
.auth-consent input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  margin-top: 1px;
  border: 2px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  cursor: pointer;
  position: relative;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.auth-consent input[type="checkbox"]:checked { background: var(--brand-2); border-color: var(--brand-2); }
.auth-consent input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.auth-consent a { color: var(--brand-2); font-weight: 600; }

/* native (Capacitor) platform adjustments */
body.native-app .device-float,
body.native-app .device-float-tab { display: none !important; }
body.native-app .app-header { padding-top: max(env(safe-area-inset-top), 12px); }
body.native-app .bottom-nav { padding-bottom: max(env(safe-area-inset-bottom), 10px); }
/* The composer sits ABOVE the bottom-nav, not at the screen edge — it must NOT
   add safe-area-inset-bottom (the nav already does). That double-padding left a
   big empty band below the input on devices with a tall gesture area. */
body.native-app .composer { padding-bottom: 8px; }

/* ── Segmented-tab consistency (final overrides) ─────────────────────────────
   money / reimburse / referral tabs share the EXACT look of the transactions
   filter-tabs: same track (border + soft bg + 4px gap), same button height/
   padding/weight, and the same dark-ink active pill (brand gradient in dark).
   Placed last so it wins over the per-control rules defined earlier. */
.money-tabs,
.reimburse-tabs,
.referral-tabs {
  border: 0;
  background: var(--card);
  box-shadow: var(--shadow-sm);
  gap: 4px;
}
.money-tabs button,
.reimburse-tabs button,
.referral-tabs button {
  min-height: 46px;
  padding: 0 16px;
  font-size: 15px;
  font-weight: 700;
  color: var(--muted-strong);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
/* 3级(内层)分段——报销/邀请子tab:比顶层(资金/账单)矮一号 + 首字母大写(非全大写),与收入子tab一致 */
.reimburse-tabs button,
.referral-tabs button {
  min-height: 36px;
  font-size: 13px;
  text-transform: none;
  letter-spacing: normal;
}
.money-tabs button.active,
.reimburse-tabs button.active,
.referral-tabs button.active {
  background: var(--brand-grad);
  color: #fff;
  box-shadow: 0 4px 12px rgba(var(--brand-2-rgb), 0.3);
}
:root[data-theme="dark"] .money-tabs button.active,
:root[data-theme="dark"] .reimburse-tabs button.active,
:root[data-theme="dark"] .referral-tabs button.active {
  background: var(--brand-grad);
  color: #fff;
}

/* Modal close (×) button — top-right of a modal card. */
.modal-card { position: relative; }
.modal-x {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 50%;
  background: var(--soft);
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  z-index: 1;
  display: grid;
  place-items: center;
  padding: 0;
}
.modal-x:active { background: var(--hover); }

/* Loan card footer: due date bottom-left, Edit bottom-right (symmetric). */
.paylater-footer { display: flex; align-items: center; gap: 10px; }
.paylater-due { font-size: 12px; color: var(--muted); }
.paylater-footer .card-action { margin-left: auto; }

/* Avatar reset action — full width, lighter than the upload button. */
.avatar-card #avatarReset { width: 100%; font-size: 13px; padding: 11px; }

/* Custom dropdown chevron with comfortable right spacing (native arrow hugged
   the border). Applies to all app selects. */
.finance-form select,
.input-row select,
.parse-tx-account select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23889099' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 16px;
  padding-right: 40px;
}

/* Icon + text buttons (share / use-default-avatar) — less plain than bare text. */
.btn-icon { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.btn-icon svg { width: 16px; height: 16px; flex: 0 0 auto; }
.btn-icon-accent {
  background: var(--brand-soft);
  border-color: transparent;
  color: var(--brand-2);
  font-weight: 700;
}
.btn-icon-accent:active { background: var(--hover); }

/* Loan card: monthly amount with its label, stacked top-right. */
.paylater-monthly { display: grid; justify-items: end; gap: 2px; text-align: right; }
.paylater-monthly-label { font-size: 11px; color: var(--muted); white-space: nowrap; }

/* Expected-income cards: taller + clearer hierarchy. */
.income-item { padding: 15px 16px; gap: 8px; }
.income-item .income-line-1 .paylater-name { font-size: 15px; }
.income-item .income-line-2 { margin-top: 2px; }

/* Center the checkmark in the custom checkbox (was off). */
.finance-form .check-row input[type="checkbox"]:checked::after {
  left: 6px;
  top: 2px;
  width: 5px;
  height: 9px;
}

/* Referral: points card is tappable (opens the redeem screen); redeem modal. */
.referral-hero.is-tappable { cursor: pointer; }
.referral-hero-cta {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  align-self: center;
  padding: 11px 18px;
  border-radius: var(--radius-pill);
  background: var(--brand-grad);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  box-shadow: 0 4px 12px var(--brand-soft);
}
.redeem-points { display: grid; gap: 4px; justify-items: center; text-align: center; padding: 6px 0 10px; }
.redeem-points span { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.redeem-points strong { font-size: 40px; font-weight: 800; line-height: 1; color: var(--brand-2); }
#redeemModal .redeem-option {
  width: 100%;
  padding: 14px;
  margin-top: 8px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--brand-grad);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}
/* Gold tier reads as gold so it's distinct from the Silver (brand) option. */
#redeemModal .redeem-option--gold {
  background: linear-gradient(135deg, #e3b53c 0%, #c5901a 60%, #f1c84e 100%);
  color: #2a2106;
}
/* Disabled(积分不足):彻底灰化,不让金色/品牌色透出显得可点。加锁标识。 */
#redeemModal .redeem-option:disabled {
  cursor: not-allowed;
  background: var(--soft);
  color: var(--muted);
  filter: grayscale(1);
  opacity: 0.75;
  box-shadow: none;
}
#redeemModal .redeem-option:disabled::before { content: "🔒 "; }
.redeem-plan-note {
  margin: 4px 2px 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
  text-align: center;
}

/* "Check for updates" button: refresh icon (::before survives data-i18n text) + accent tint. */
.app-version-row #checkUpdateBtn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 20px;
  border-radius: 999px;
  background: var(--brand-soft);
  border: 1px solid var(--brand-ring);
  color: var(--brand-2);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.app-version-row #checkUpdateBtn:hover { box-shadow: 0 3px 10px var(--brand-soft); }
.app-version-row #checkUpdateBtn:active { transform: scale(0.96); }
.app-version-row #checkUpdateBtn:disabled { opacity: 0.85; }
.app-version-row #checkUpdateBtn::before {
  content: "";
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12a9 9 0 1 1-2.6-6.4'/%3E%3Cpath d='M21 3v5h-5'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12a9 9 0 1 1-2.6-6.4'/%3E%3Cpath d='M21 3v5h-5'/%3E%3C/svg%3E") center/contain no-repeat;
  transition: transform var(--dur) var(--ease);
}

/* ── Pembaruan 页(参照图):hero + 版本徽章 + 更新日志 + 大按钮 + 页脚 ── */
.update-hero { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; padding: 8px 0 16px; }
.update-hero-ic { width: 92px; height: 92px; border-radius: 24px; background: var(--card); box-shadow: var(--shadow-sm); display: grid; place-items: center; margin-bottom: 4px; }
.uhi-circle { width: 60px; height: 60px; border-radius: 50%; background: var(--brand-grad); display: grid; place-items: center; box-shadow: 0 0 0 9px rgba(255, 138, 61, 0.14); }
.uhi-circle svg { width: 28px; height: 28px; }
.update-ver { display: inline-flex; align-items: center; gap: 9px; font-size: 16px; font-weight: 700; color: var(--muted-strong); }
.update-badge { font-style: normal; font-size: 12px; font-weight: 800; color: var(--brand-2); background: var(--brand-soft); border: 1px solid var(--brand-2); border-radius: 999px; padding: 2px 10px; }
.update-hero h2 { font-size: 21px; font-weight: 800; color: var(--ink-strong); margin: 6px 0 0; }
.update-hero p { font-size: 14px; color: var(--muted); margin: 0; }
.update-changelog { padding: 16px 18px; }
.ucl-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.ucl-head b { font-size: 15px; font-weight: 800; color: var(--ink-strong); }
.ucl-detail { font-size: 13px; font-weight: 700; color: var(--brand-2); cursor: pointer; }
.ucl-item { padding: 12px 0; border-bottom: 1px solid var(--line); }
.ucl-item:last-child { border-bottom: 0; padding-bottom: 0; }
.ucl-item strong { display: block; font-size: 14px; font-weight: 700; color: var(--ink-strong); }
.ucl-item small { display: block; font-size: 13px; color: var(--muted); margin-top: 2px; }
.ucl-body { padding-top: 12px; display: grid; gap: 8px; }
.ucl-body p { font-size: 13.5px; line-height: 1.5; color: var(--ink); margin: 0; }
.ucl-body .ucl-empty { color: var(--muted); }
.update-check-btn { width: 100%; height: 56px; margin-top: 4px; display: inline-flex; align-items: center; justify-content: center; gap: 10px; border: 0; border-radius: var(--radius-pill); background: var(--accent-grad); color: #fff; font-size: 16px; font-weight: 800; cursor: pointer; }
/* 无静态图标;点「检查更新」时才显示通用 .is-checking::after 圈圈 spinner */
.update-check-btn.is-checking { font-size: 0; gap: 0; }
.update-check-btn:active { transform: scale(0.99); }
.update-foot { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: 12px; font-size: 12.5px; color: var(--muted); }
.update-foot svg { flex: none; width: 15px; height: 15px; }

/* Reset confirmation: shown code + input. */
.reset-code-shown {
  text-align: center;
  font-size: 32px;
  font-weight: 800;
  letter-spacing: 8px;
  color: #ef4444;
  margin: 2px 0 6px;
  font-family: var(--font-mono, monospace);
}
#resetCodeInput {
  width: 100%;
  height: 46px;
  text-align: center;
  font-size: 20px;
  letter-spacing: 6px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--soft);
  color: var(--ink-strong);
}

.report-table-wrap { margin-top: 14px; overflow-x: auto; }
.report-table { width: 100%; border-collapse: collapse; font-size: 11px; font-variant-numeric: tabular-nums; }
.report-table .rp-prefix { font-size: .85em; margin-right: .1em; }
.report-table td:first-child, .report-table th:first-child { white-space: nowrap; } /* 月份/分类名不换行(如 2026-06) */
.report-table th, .report-table td { padding: 8px 6px; text-align: left; border-bottom: 1px solid var(--line, #e2e8f0); white-space: normal; word-break: keep-all; }
.report-table th { font-size: 10px; text-transform: uppercase; letter-spacing: .02em; color: var(--muted, #64748b); }
.report-table .num { text-align: right; white-space: nowrap; }
.report-zone-title { margin: 18px 0 6px; font-size: 14px; font-weight: 800; }
.report-zone-title.sub { font-size: 12px; opacity: .8; font-weight: 700; }
.insight-list { display: grid; gap: 6px; }
.insight-row { display: flex; justify-content: space-between; gap: 12px; padding: 7px 10px; border: 1px solid var(--line, #e2e8f0); border-radius: 10px; }
.insight-row span { color: var(--muted, #64748b); font-size: 12px; }
.delta { font-style: normal; font-weight: 700; }
.delta--up { color: var(--ok, #059669); } .delta--down { color: var(--danger, #dc2626); } .delta--flat { color: var(--muted, #94a3b8); }
.report-chart-card { background: var(--card, #161a24); border: 0; border-radius: 14px; padding: 14px; margin-top: 14px; }
.report-chart-card .chart-title { display: block; font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.report-chart-card .chart-box { position: relative; height: 200px; }
.report-chart-card .chart-box[hidden] { display: none; }
.report-chart-card .chart-note { margin-top: 10px; font-size: 12px; color: var(--muted, #64748b); }
/* 空状态:无数据时图表卡只剩标题 + 居中提示,不再撑出高大空网格 */
.report-chart-card .chart-note--empty { margin-top: 2px; padding: 16px 0 8px; text-align: center; font-size: 13px; font-weight: 600; color: var(--muted, #64748b); }

/* 首页日期:现在放进 .ovd-date 行,纯文字(药丸/圆点样式已移除,绿点只在 payday badge) */
.overview-month { line-height: 1; }

/* ===== 报表页重设计 v2(精修:层级/间距/配色) ===== */
#profileReport { --rp-soft: #f3f5f9; }
:root[data-theme="dark"] #profileReport { --rp-soft: rgba(255,255,255,.06); }

/* 页头 */
.report-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; margin:2px 0 2px; }
.report-head .report-title { font-size:23px; font-weight:800; letter-spacing:-.02em; line-height:1.15; margin:0; }
.report-head .report-sub { color:var(--muted); font-size:13px; font-weight:500; margin:4px 0 0; font-variant-numeric:tabular-nums; }
.report-ekspor { display:inline-flex; align-items:center; gap:7px; flex:none; height:38px; padding:0 16px;
  border:0; border-radius:var(--radius-pill); background:var(--ink); color:#fff; font-size:13px; font-weight:700; cursor:pointer;
  transition:opacity .15s; }
.report-ekspor:active { opacity:.85; }
.report-ekspor svg { width:15px; height:15px; }
:root[data-theme="dark"] .report-ekspor { background:var(--brand); }

/* 范围 = 分段控件(iOS 风:轨道 + 白色活动段) */
.report-seg { display:flex; gap:4px; background:var(--rp-soft); border:1px solid var(--line); border-radius:var(--radius-pill); padding:4px; margin:16px 0 4px; }
.report-seg button { flex:1; min-width:0; height:34px; padding:0 6px; border:0; background:transparent; color:var(--muted);
  font-size:13px; font-weight:600; border-radius:var(--radius-pill); cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:background .15s, color .15s; }
.report-seg button.active { background:var(--card); color:var(--ink); font-weight:700; box-shadow:0 1px 3px rgba(16,24,40,.14); }
:root[data-theme="dark"] .report-seg button.active { background:var(--brand); color:#fff; box-shadow:none; }

/* 自定义日期(仅报表,紧凑) */
#reportCustomRange { background:var(--rp-soft); border:0; border-radius:14px; padding:12px; margin-top:8px; }

/* 区块标题 */
#profileReport .report-zone-title { display:flex; align-items:baseline; justify-content:space-between; gap:10px;
  margin:24px 2px 10px; font-size:15px; font-weight:800; letter-spacing:-.01em; }
#profileReport .report-zone-title.sub { font-size:12.5px; font-weight:700; color:var(--muted); margin:20px 2px 10px; }
#profileReport .report-zone-title .tag { font-size:12px; font-weight:600; color:var(--muted); font-variant-numeric:tabular-nums; }

/* 本期收支 hero = 高级深色渐变卡(同首页 hero) */
.period-card { position:relative; background:var(--hero-bg); color:var(--hero-ink); border:0; border-radius:20px;
  padding:20px 18px 18px; box-shadow:0 14px 38px rgba(10,8,4,.42); overflow:hidden; }
.period-card::before { content:""; position:absolute; top:-55%; right:-25%; width:75%; aspect-ratio:1; border-radius:50%;
  background:radial-gradient(closest-side, var(--brand-ring), transparent 70%); pointer-events:none; }
.period-card::after { content:""; position:absolute; bottom:-45%; left:-20%; width:65%; aspect-ratio:1; border-radius:50%;
  background:radial-gradient(closest-side, rgba(34,211,238,.22), transparent 70%); pointer-events:none; }
.period-card > * { position:relative; z-index:1; }
.period-top { display:flex; align-items:center; justify-content:space-between; margin-bottom:4px; }
.period-label { font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--hero-muted); }
.period-net { font-size:34px; font-weight:800; letter-spacing:-.03em; line-height:1.05; font-variant-numeric:tabular-nums; white-space:nowrap; color:#fff; }
.period-net.pos { color:#34d399; } .period-net.neg { color:#f87171; }
.period-card .delta--up { color:#34d399; } .period-card .delta--down { color:#f87171; } .period-card .delta--flat { color:var(--hero-muted); }
.period-split { display:flex; height:7px; border-radius:999px; overflow:hidden; margin:16px 0 14px; background:rgba(255,255,255,.14); }
.period-split .in { background:#34d399; } .period-split .out { background:#f87171; }
.period-io { display:flex; gap:10px; }
.io-pill { flex:1; border-radius:14px; padding:12px 13px; background:rgba(255,255,255,.07); }
.io-pill .io-k { display:flex; align-items:center; gap:6px; font-size:10.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:var(--hero-muted); }
.io-pill .io-k i { width:8px; height:8px; border-radius:50%; flex:none; }
.io-pill.in .io-k i { background:#34d399; } .io-pill.out .io-k i { background:#f87171; }
.io-pill .io-v { display:block; font-size:16px; font-weight:800; margin-top:4px; font-variant-numeric:tabular-nums; letter-spacing:-.01em; color:#fff; }

/* 底部留白:最后的图表/表不被底部导航切 */
#profileReport { padding-bottom: 80px; }

/* 分析卡 */
.report-insights .insight-list { background:var(--card); border:1px solid var(--line); border-radius:16px; overflow:hidden; gap:0;
  box-shadow:0 1px 2px rgba(16,24,40,.04); }
.report-insights .insight-row { margin:0; padding:13px 14px; border:0; border-radius:0; box-shadow:none;
  border-bottom:1px solid var(--line); }
.report-insights .insight-row:last-child { border-bottom:0; }
.insight-row .ik { display:flex; align-items:center; gap:10px; color:var(--muted); font-size:13px; }
.insight-row .ic { width:28px; height:28px; flex:none; border-radius:9px; display:grid; place-items:center;
  background:var(--brand-soft); color:var(--brand); font-size:14px; font-weight:700; }
.insight-row strong { font-size:14px; font-weight:700; font-variant-numeric:tabular-nums; text-align:right; }
.insight-row .ik { min-width:0; }
.insight-row .over { color:var(--danger); font-weight:700; }

/* 图表卡 + 表卡:统一,留足内边距 */
#profileReport .report-chart-card { border-radius:16px; padding:16px; box-shadow:0 1px 2px rgba(16,24,40,.04); }
#profileReport .report-chart-card .chart-box { height:220px; }
#profileReport .report-table-wrap { background:var(--card); border:1px solid var(--line); border-radius:16px; padding:6px 6px 8px; margin-top:12px; box-shadow:0 1px 2px rgba(16,24,40,.04); overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch; }
#profileReport .report-table-wrap > .report-zone-title { position:sticky; left:0; } /* 标题不随表横滚 */
/* 表格标题:深色加粗(与图表卡标题一致)+ 左对齐到首列(th 左 padding 6px) */
#profileReport .report-table-wrap .report-zone-title.sub { margin:6px 6px 8px; color:var(--ink-strong); font-size:13.5px; font-weight:800; }
#profileReport .report-table th { background:var(--rp-soft); }
#profileReport .report-table th:first-child { border-top-left-radius:10px; border-bottom-left-radius:10px; }
#profileReport .report-table th:last-child { border-top-right-radius:10px; border-bottom-right-radius:10px; }
#profileReport .report-table th, #profileReport .report-table td { padding:9px 6px; border-bottom:1px solid var(--line); }
#profileReport .report-table tbody tr:last-child td { border-bottom:0; }

/* 快照卡片 2 列 */
#reportSnapshotCards.report-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
#reportSnapshotCards .report-card { background:var(--card); border:0; border-radius:14px; padding:13px 14px;
  box-shadow:0 1px 3px rgba(16,24,40,.06); }
#reportSnapshotCards .report-card span:not(.rt-ic) { font-size:11px; font-weight:700; letter-spacing:.03em; text-transform:uppercase; color:var(--muted); }
#reportSnapshotCards .report-card strong { display:block; font-size:16px; font-weight:800; margin-top:4px; font-variant-numeric:tabular-nums; letter-spacing:-.01em; }

/* ===== 报表浅色化(套全 app 浅色 + 图标tile,见图4);保留 --rp-rgb 给强调条 ===== */
#profileReport {
  --rp-rgb: var(--brand-2-rgb, 255,122,69);
  --brand: var(--brand-2);
  color: var(--ink);
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 4px 0 80px;
  overflow-x: clip; /* 图表 canvas 偶尔比容器宽几 px,夹边不产生横向滚动 */
}
/* 图表卡可收缩,canvas 不撑宽面板 */
#profileReport .report-charts, #profileReport .report-chart-card { min-width: 0; }
#profileReport .chart-box { max-width: 100%; }
/* 关键:grid 子项允许收缩,否则 date input 等最小宽度撑爆面板→内容被裁 */
#profileReport > * { min-width: 0; max-width: 100%; }
#profileReport #reportCustomRange { flex-wrap: wrap; }
#profileReport #reportCustomRange label { flex: 1 1 120px; min-width: 0; }
#profileReport #reportCustomRange input { width: 100%; min-width: 0; }
#profileReport #reportCustomRange #reportDateApply { flex: 1 1 100%; }
#profileReport .report-title { color:#fff; text-shadow: 0 0 14px rgba(var(--rp-rgb),.5); letter-spacing:.01em; }
#profileReport .report-sub { color:var(--muted); }
#profileReport .report-ekspor { background: var(--brand-2); color:#fff; font-weight:800; box-shadow: 0 0 16px rgba(var(--rp-rgb),.45); }
#profileReport .report-seg { background: rgba(var(--rp-rgb),.06); border-color: rgba(var(--rp-rgb),.18); }
#profileReport .report-seg button { color: var(--muted); }
#profileReport .report-seg button.active { background: var(--brand-grad); color:#fff; box-shadow: 0 0 16px rgba(var(--rp-rgb),.5); }
#profileReport .report-insights .insight-list,
#profileReport .report-chart-card,
#profileReport .report-table-wrap,
#profileReport #reportSnapshotCards .report-card {
  background: rgba(255,255,255,.035); border:1px solid rgba(var(--rp-rgb),.16);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.04), 0 0 14px rgba(var(--rp-rgb),.06), 0 8px 22px rgba(0,0,0,.4);
}
#profileReport #reportCustomRange { background: rgba(var(--rp-rgb),.06); }
#profileReport .period-card { border:1px solid rgba(var(--rp-rgb),.22); box-shadow: 0 0 24px rgba(var(--rp-rgb),.12), 0 14px 38px rgba(0,0,0,.5); }
#profileReport .period-net { text-shadow: 0 0 18px currentColor; }
#profileReport .period-net.pos { color:#34d399; } #profileReport .period-net.neg { color:#ff6b6b; }
#profileReport .period-card .delta--up { color:#34d399; } #profileReport .period-card .delta--down { color:#ff6b6b; }
#profileReport .report-zone-title { color:#fff; padding-left:12px; position:relative; text-shadow:0 0 10px rgba(var(--rp-rgb),.35); }
#profileReport .report-zone-title::before { content:""; position:absolute; left:2px; top:50%; transform:translateY(-50%);
  width:3px; height:15px; border-radius:2px; background:var(--brand-2); box-shadow:0 0 10px rgba(var(--rp-rgb),.85); }
#profileReport .report-zone-title.sub { padding-left:2px; color:var(--muted); text-shadow:none; }
#profileReport .report-zone-title.sub::before { display:none; }
#profileReport .report-zone-title .tag { color:var(--muted); }
#profileReport .insight-row .ic { background:rgba(var(--rp-rgb),.14); color:var(--brand-2); box-shadow:inset 0 0 0 1px rgba(var(--rp-rgb),.28), 0 0 8px rgba(var(--rp-rgb),.22); }
#profileReport .insight-row .ik { color:var(--muted); }
#profileReport .insight-row strong { color:#fff; }
#profileReport .report-table th { background:rgba(var(--rp-rgb),.07); color:#d8b8a4; }
#profileReport .report-table td { color:var(--ink); }
#profileReport #reportSnapshotCards .report-card span:not(.rt-ic) { color:var(--muted); }
#profileReport #reportSnapshotCards .report-card strong { color:#fff; }
#profileReport .period-net, #profileReport .io-pill .io-v,
#profileReport #reportSnapshotCards .report-card strong {
  font-family: ui-monospace,"SF Mono","Roboto Mono","Noto Sans Mono",monospace;
}

/* 报表 tab */
#profileReport .report-tabs { display:flex; gap:4px; background:rgba(255,255,255,.05); border:1px solid rgba(var(--rp-rgb),.18); border-radius:var(--radius-pill); padding:4px; margin:0 0 10px; }
#profileReport .report-tabs button { flex:1; height:34px; border:0; background:transparent; color:var(--muted); font-size:13px; font-weight:700; border-radius:var(--radius-pill); cursor:pointer; }
#profileReport .report-tabs button.active { background:var(--brand-grad); color:#fff; box-shadow:0 0 14px rgba(var(--rp-rgb),.45); }
/* 之最卡 */
#profileReport .sorotan-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
#profileReport .sorotan-card { display:flex; flex-direction:column; gap:3px; background:rgba(255,255,255,.035); border:1px solid rgba(var(--rp-rgb),.16); border-radius:14px; padding:13px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04), 0 0 12px rgba(var(--rp-rgb),.05); }
#profileReport .sorotan-card .sorotan-ic { width:28px; height:28px; border-radius:9px; display:grid; place-items:center; background:rgba(var(--rp-rgb),.14); color:var(--brand-2); }
#profileReport .sorotan-card .sorotan-ic svg { width:16px; height:16px; }
#profileReport .sorotan-card .sorotan-label { font-size:11px; font-weight:700; letter-spacing:.02em; text-transform:uppercase; color:var(--muted); margin-top:4px; line-height:1.3; min-height:2.6em; }
#profileReport .sorotan-card .sorotan-big { font-size:18px; font-weight:800; color:#fff; font-family:inherit; font-variant-numeric:tabular-nums; }
#profileReport .sorotan-card .sorotan-sub { font-size:11.5px; color:var(--muted); }

/* 月度趋势:月份竖排(月大·年小),首列窄,给金额更多横向空间 */
#profileReport .report-table .m-stack { display:flex; flex-direction:column; line-height:1.1; }
#profileReport .report-table .m-stack b { font-size:15px; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; }
#profileReport .report-table .m-stack i { font-size:11px; font-style:normal; color:var(--muted); }

/* ===== 报表浅色覆盖:把残留硬编码深色规则压回浅色(图4) ===== */
#profileReport .report-title { color: var(--ink); text-shadow: none; }
#profileReport .report-sub { color: var(--muted); }
/* 导出键:橙色圆圈 + 居中图标(只留图标,无文字) */
#profileReport .report-ekspor { width: 40px; height: 40px; padding: 0; gap: 0; justify-content: center; background: var(--card); color: var(--brand-2); border: 1.5px solid var(--brand-2); box-shadow: none; }
#profileReport .report-ekspor span { display: none; }
#profileReport .report-ekspor svg { width: 18px; height: 18px; }
/* 时间分段:白底容器,选中橙色(无光晕) */
#profileReport .report-seg { background: var(--card); border: 0; box-shadow: var(--shadow-sm); }
#profileReport .report-seg button { color: var(--muted); }
#profileReport .report-seg button.active { background: var(--brand-grad); color: #fff; box-shadow: none; }
#profileReport #reportCustomRange { background: var(--rp-soft); }
#profileReport .report-insights .insight-list,
#profileReport .report-chart-card,
#profileReport .report-table-wrap,
#profileReport #reportSnapshotCards .report-card {
  background: var(--card); border: 0;
  box-shadow: 0 1px 3px rgba(16, 24, 40, .06);
}
/* 报表内所有卡片去灰色描边(图表卡 / 洞察 / 表格),留淡阴影 */
#profileReport .report-chart-card,
#profileReport .report-insights .insight-list,
#profileReport .report-table-wrap {
  border: 0;
  box-shadow: 0 1px 3px rgba(16, 24, 40, .06);
}
#profileReport .report-zone-title { color: var(--ink); text-shadow: none; }
#profileReport .report-zone-title::before { background: var(--brand-2); box-shadow: none; }
#profileReport .report-zone-title.sub { color: var(--muted); }
/* 本期收支 hero → 浅色卡 */
#profileReport .period-card { background: var(--card); color: var(--ink); border: 1px solid var(--line); box-shadow: 0 1px 2px rgba(16, 24, 40, .04); }
#profileReport .period-card::before, #profileReport .period-card::after { display: none; }
#profileReport .period-label { color: var(--muted); }
#profileReport .period-net { color: var(--ink); text-shadow: none; }
#profileReport .period-net.pos { color: #10a35e; }
#profileReport .period-net.neg { color: #ef4444; }
#profileReport .period-card .delta--up { color: #10a35e; }
#profileReport .period-card .delta--down { color: #ef4444; }
#profileReport .period-card .delta--flat { color: var(--muted); }
#profileReport .period-split { background: var(--line); }
#profileReport .period-split .in { background: #10a35e; }
#profileReport .period-split .out { background: #ef4444; }
#profileReport .io-pill { background: var(--soft); }
#profileReport .io-pill .io-k { color: var(--muted); }
#profileReport .io-pill.in .io-k i { background: #10a35e; }
#profileReport .io-pill.out .io-k i { background: #ef4444; }
#profileReport .io-pill .io-v { color: var(--ink); }
/* 分析 insight */
#profileReport .insight-row .ic { background: var(--brand-soft); color: var(--brand-2); box-shadow: none; }
#profileReport .insight-row .ik { color: var(--muted); }
#profileReport .insight-row strong { color: var(--ink); }
/* 表格 */
#profileReport .report-table th { background: var(--rp-soft); color: var(--muted); }
#profileReport .report-table td { color: var(--ink); }
/* 快照卡 */
#profileReport #reportSnapshotCards .report-card span:not(.rt-ic) { color: var(--muted); }
#profileReport #reportSnapshotCards .report-card strong { color: var(--ink); }
/* 报表 tab → 白底容器,选中橙色(无光晕) */
#profileReport .report-tabs { background: var(--card); border: 0; box-shadow: var(--shadow-sm); }
#profileReport .report-tabs button { color: var(--muted); }
#profileReport .report-tabs button.active { background: var(--brand-grad); color: #fff; box-shadow: none; }
/* 之最(sorotan)卡 → 浅色 */
#profileReport .sorotan-card { background: var(--card); border: 1px solid var(--line); box-shadow: 0 1px 2px rgba(16, 24, 40, .04); }
#profileReport .sorotan-card .sorotan-ic { background: var(--brand-soft); color: var(--brand-2); }
#profileReport .sorotan-card .sorotan-big { color: var(--ink); }
#profileReport .sorotan-card .sorotan-sub { color: var(--muted); }

/* ===== 报表图4 组件:Sorotan Checko AI 卡 + 统计 tile + 省钱条 + 加密底注 ===== */
/* 总览 / 之最(Ringkasan/Sorotan)双 tab 恢复显示 */
#profileReport .report-tabs { display: flex; }
/* 5 个时间范围 tab 缩字距/字号,避免「Bulan Ini / Tahun Ini」被省略号截断 */
#profileReport .report-seg { gap: 2px; padding: 4px 3px; }
#profileReport .report-seg button { font-size: 12px; padding: 0 3px; letter-spacing: -.01em; }
/* Sorotan Checko AI 卡(peach) */
#profileReport .report-ai-card { border-radius: 18px; padding: 16px; background: linear-gradient(135deg, rgba(var(--brand-2-rgb), .12), rgba(var(--brand-2-rgb), .045)); border: 1px solid var(--brand-soft); }
#profileReport .rai-head { display: flex; align-items: center; gap: 9px; margin-bottom: 13px; }
#profileReport .rai-spark { width: 30px; height: 30px; flex: none; border-radius: 10px; display: grid; place-items: center; background: var(--brand-2); color: #fff; }
#profileReport .rai-spark svg { width: 18px; height: 18px; }
#profileReport .rai-title { font-size: 15px; font-weight: 800; color: var(--ink); }
#profileReport .rai-badge { font-size: 10px; font-weight: 800; letter-spacing: .06em; color: var(--brand-2); background: var(--card); border: 1px solid var(--brand-soft); border-radius: 999px; padding: 2px 8px; }
#profileReport .rai-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
#profileReport .rai-li { display: flex; align-items: center; gap: 10px; font-size: 13.5px; }
#profileReport .rai-ic { flex: none; width: 22px; height: 22px; display: grid; place-items: center; }
#profileReport .rai-ic svg { width: 19px; height: 19px; }
#profileReport .rai-k { color: var(--muted); }
#profileReport .rai-v { margin-left: auto; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }
#profileReport .rai-li--green .rai-ic { color: #10a35e; }
#profileReport .rai-li--red .rai-ic { color: #ef4444; }
#profileReport .rai-li--orange .rai-ic { color: #ff6a2b; }
#profileReport .rai-li--blue .rai-ic { color: #3b82f6; }
/* 统计 tile 网格(图标tile + 标签 + 大数 + 副) */
#profileReport #reportSnapshotCards.report-grid { gap: 10px; margin-top: 12px; }
/* 图标+标签一行,数值/副标题各占满整格宽 —— 大金额(如 Rp 3.000.000.000)才不撑破右边框 */
#profileReport .report-tile { display: grid; grid-template-columns: 40px minmax(0, 1fr); column-gap: 11px; row-gap: 3px; padding: 13px; }
#profileReport .report-tile .rt-ic { grid-column: 1; grid-row: 1; flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; }
#profileReport .report-tile .rt-ic svg { width: 21px; height: 21px; }
#profileReport .report-tile .rt-body { display: contents; }
#profileReport .report-tile .rt-k { grid-column: 2; grid-row: 1; align-self: center; min-width: 0; font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); line-height: 1.2; }
#profileReport .report-tile .rt-v { grid-column: 1 / -1; grid-row: 2; min-width: 0; overflow-wrap: anywhere; }
#profileReport .report-tile .rt-s { grid-column: 1 / -1; grid-row: 3; }
#profileReport .report-tile .rt-v { display: block; margin: 1px 0 0; font-family: inherit; font-size: 15.5px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -.01em; text-transform: none; }
/* 抵消快照基础规则把 tile 内 span(Rp 货币符 / 副标题)误转大写、缩小;
   并去掉等宽字体(基础 #profileReport #reportSnapshotCards .report-card strong 是 2 个 id,需同等 id 数压过) */
#profileReport #reportSnapshotCards .report-tile .rt-v { font-family: inherit; }
#profileReport .report-tile .rt-v span { font: inherit; color: inherit; letter-spacing: normal; text-transform: none; }
#profileReport .report-tile .rt-s { font-size: 11px; font-weight: 600; letter-spacing: normal; text-transform: none; color: var(--muted); }
#profileReport .rt-ic-orange { background: rgba(255, 138, 61, .16); color: #ff6a2b; }
#profileReport .rt-ic-red { background: rgba(239, 68, 68, .12); color: #ef4444; }
#profileReport .rt-ic-green { background: rgba(16, 185, 129, .13); color: #10a35e; }
#profileReport .rt-ic-purple { background: rgba(139, 92, 246, .13); color: #8b5cf6; }
#profileReport .rt-ic-blue { background: rgba(59, 130, 246, .12); color: #3b82f6; }
/* 省钱对比条 */
#profileReport .report-savings-bar { display: flex; align-items: center; gap: 11px; margin-top: 14px; padding: 13px 15px; border-radius: 16px; background: rgba(16, 185, 129, .10); border: 1px solid rgba(16, 185, 129, .22); }
#profileReport .report-savings-bar.rsb--up { background: rgba(239, 68, 68, .08); border-color: rgba(239, 68, 68, .20); }
#profileReport .report-savings-bar .rsb-ic { flex: none; width: 26px; height: 26px; display: grid; place-items: center; color: #10a35e; }
#profileReport .report-savings-bar.rsb--up .rsb-ic { color: #ef4444; }
#profileReport .report-savings-bar .rsb-ic svg { width: 20px; height: 20px; }
#profileReport .report-savings-bar p { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink); }
/* 加密底注 */
#profileReport .report-foot-note { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 22px 4px 4px; font-size: 12px; color: var(--muted); text-align: center; }
#profileReport .report-foot-note svg { width: 15px; height: 15px; flex: none; color: #10a35e; }

/* 其他▾ 底部上拉菜单 */
.sheet-backdrop { align-items: flex-end; }
.sheet-card { width: 100%; max-width: 520px; margin: 0 auto; background: var(--card); border-radius: 18px 18px 0 0;
  padding: 8px; display: flex; flex-direction: column; gap: 4px; box-shadow: 0 -8px 30px rgba(0,0,0,.25); }
.sheet-item { width: 100%; height: 52px; border: 0; background: transparent; color: var(--ink);
  font-size: 15px; font-weight: 600; border-radius: 12px; cursor: pointer; text-align: center; }
.sheet-item:active { background: var(--brand-soft); }
.sheet-cancel { color: var(--muted); font-weight: 700; }
/* 收入记录 */
/* 收入 panel 的 记录/收入记录 tab —— 复刻 money-tabs 胶囊外观(独立样式,避开 money-tabs 桌面隐藏规则) */
.income-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin: 4px 0 12px; padding: 4px;
  border-radius: var(--radius-pill); background: var(--card); box-shadow: var(--shadow-sm); border: 0; }
/* 只有 PPN 那页的分段控件要灰色描边(用户点名的那一处);其余分段控件保持原来的无边样式。 */
.income-tabs.ppn-tabs { border: 1px solid var(--line); }
.income-tabs button { display: inline-flex; align-items: center; justify-content: center; min-height: 34px; padding: 0 14px;
  border: 0; border-radius: var(--radius-pill); background: transparent; color: var(--muted-strong); font-size: 12px; font-weight: 700; cursor: pointer; }
.income-tabs button.active { background: var(--brand-grad); color: #fff; box-shadow: none; } /* 与主按钮(Foto Struk)同款鲜艳橙,暗色不再发白 */
:root[data-theme="dark"] .income-tabs button.active { background: var(--brand-grad); color: #fff; }
/* Split 页 3 个 tab(计算/记录/联系人)→ 一行三等分,缩字免换行 */
#splitPageTabs { grid-template-columns: 1fr 1fr 1fr; }
#splitPageTabs button { padding: 0 6px; font-size: 11.5px; white-space: nowrap; }
/* 分摊方式 / 付款方式选择器:加回灰描边 */
.split-mode-tabs, .split-pay-tabs { border: 1px solid var(--line); }
/* 收入面板:记录|预期收入|收入记录 三 tab */
#incomeLogTabs { grid-template-columns: 1fr 1fr 1fr; }
#incomeLogTabs button { padding: 0 8px; }
#incomeLogSearch, #reimburseSearch { width: 100%; min-height: 42px; padding: 0 14px; margin-bottom: 10px; border: 1px solid var(--line); border-radius: var(--radius-pill); color: var(--ink); font-size: 14px; position: sticky; top: 0; z-index: 15; background: rgba(255, 255, 255, 0.7); -webkit-backdrop-filter: blur(18px) saturate(160%); backdrop-filter: blur(18px) saturate(160%); }
:root[data-theme="dark"] #incomeLogSearch, :root[data-theme="dark"] #reimburseSearch { background: rgba(26, 28, 34, 0.62); }
#incomeLogSearch:focus, #reimburseSearch:focus { outline: none; border-color: var(--muted); box-shadow: none; }
.add-expected-btn { margin-top: 14px; width: 100%; height: 48px; border: 0; border-radius: var(--radius-md); background: var(--brand-grad); color: #fff; font-size: 15px; font-weight: 800; cursor: pointer; }
.add-expected-btn:active { transform: scale(0.99); }
/* 账户负余额(透支/欠款)用红色突出 */
.account-item strong.neg-balance { color: var(--danger, #dc2626); }
.income-log-cta { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
.income-log-cta p { color: var(--muted); font-size: 13px; margin: 0; }
.income-log-cta button { height: 46px; border: 0; border-radius: 12px; background: var(--brand-grad, var(--brand)); color: #fff; font-weight: 800; font-size: 15px; cursor: pointer; }
/* 网格 minmax(0,1fr) auto:强制名称列不超过可用宽(和支出流水行一样),长名换行不撑破面板 */
.income-log-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px; }
.income-log-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* 导入的流水名常含超长无空格串(WSID…),会撑破行宽→整面板横向溢出。单行截断+省略号。 */
.income-log-main strong { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.income-log-main small { color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.income-log-amt { color: #16a34a; font-variant-numeric: tabular-nums; white-space: nowrap; }
:root[data-theme="dark"] .income-log-amt { color: #34d399; }

/* 环形图自定义图例(白名称+占比第二行,更工整;报表深色 scope) */
#profileReport .chart-legend { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; margin: 14px 4px 2px; }
#profileReport .chart-legend-item { display: grid; grid-template-columns: auto 1fr; column-gap: 8px; align-items: center; min-width: 0; }
#profileReport .chart-legend-item i { grid-row: 1 / span 2; width: 12px; height: 12px; border-radius: 3px; }
#profileReport .chart-legend-item .cl-name { color: var(--ink, #0f172a); font-size: 13px; font-weight: 600; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
#profileReport .chart-legend-item .cl-pct { color: var(--muted-strong, #475569); font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }

/* 类别下拉 + 右侧"默认"勾选 */
.select-with-default { display: flex; gap: 8px; align-items: center; position: relative; min-width: 0; }
.select-with-default select { flex: 1; min-width: 0; }
/* 超长下拉项(如「Codex QA …… wallet」这种长账户名)会撑破 select → 溢出弹窗右侧。
   让 select 及其所有网格/弹性祖先都能收缩(min-width:0),超出的文字由控件截断。 */
.finance-form--tiles > label:not(.ff-row--switch),
.finance-form--tiles .ff-rowgroup > label,
.finance-form--tiles .form-row-2 > label,
.finance-form--tiles > label:not(.ff-row--switch) > .ff-body,
.finance-form--tiles .ff-rowgroup > label > .ff-body,
.finance-form--tiles .form-row-2 > label > .ff-body { min-width: 0; }
.finance-form select { text-overflow: ellipsis; }
/* ── 自定义下拉(替代原生 <select>,消除 iOS 原生淡出动画)── */
.csel-native { display: none !important; }
/* ── 输入框清除按钮(X)── */
.ff-body.has-clear { position: relative; }
.field-clear {
  position: absolute; right: 12px; bottom: 21px; top: auto; transform: translateY(50%);
  width: 22px; height: 22px; display: none; place-items: center;
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  padding: 0; z-index: 3;
}                                     /* bottom:21px+translateY(50%) → 对齐 42px 高输入框的竖直中心 */
.ff-body.has-clear input { padding-right: 34px; }
.has-clear.show-clear .field-clear { display: grid; }
.field-clear svg { width: 15px; height: 15px; }
.field-clear:active { transform: translateY(50%) scale(0.9); }
/* 金额框:.amount-field 包裹层里,X 坐在 Aa/123 键左边 */
.amount-field.has-clear { position: relative; }
.field-clear--amt { right: 54px; }
/* chat:有字时 X 顶掉麦克风,占同一位置 */
.input-wrap.has-clear { position: relative; }
.field-clear--chat { right: 4px; top: 50%; bottom: auto; transform: translateY(-50%); width: 36px; height: 36px; border-radius: 50%; }
.field-clear--chat:active { transform: translateY(-50%) scale(0.9); }
.field-clear--chat svg { width: 18px; height: 18px; }
.input-wrap.show-clear .input-voice { display: none; }
.csel-host .csel-trigger { flex: 1; min-width: 0; }
.csel-trigger {
  height: 42px; width: 100%; box-sizing: border-box;
  border: 0; border-radius: 14px;
  background: var(--soft); color: var(--ink);
  font-size: 15px; font-weight: 500; text-align: left;
  padding: 0 40px 0 14px; /* 左内边距由 JS 读原生 select 实际值覆盖(有图标 tile=58px,普通=14px);右留 chevron 位 */
  display: flex; align-items: center; position: relative; cursor: pointer;
}
.csel-host { position: relative; } /* 面板相对宿主定位(非 .select-with-default 的容器也能用) */
/* tile 表单(有左侧彩色图标)里的触发器左留 58px,和原生 select 一致;普通表单用基础 14px */
.finance-form--tiles .csel-trigger { padding-left: 58px; }
/* 设置页(货币/时区)自定义下拉触发器:整行 + 上间距 + 高度,和原 .set-select 一致 */
.set-row--select .csel-trigger { flex: 1 1 100%; margin-top: 12px; height: 46px; }
.csel-trigger:active { background: var(--hover); }
.csel-trigger .csel-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.csel-trigger .csel-chev { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--muted); transition: transform .18s var(--ease); pointer-events: none; }
.csel-trigger.is-open .csel-chev { transform: translateY(-50%) rotate(180deg); }
.csel-panel {
  /* fixed:脱离弹窗的 overflow 裁剪,浮层不会被弹窗底边截断(位置由 JS 按触发器 rect 定) */
  position: fixed; z-index: 200;
  max-height: 244px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-lg); padding: 5px;
}
.csel-panel[hidden] { display: none; }
.csel-opt {
  display: block; width: 100%; text-align: left; border: 0; background: transparent;
  color: var(--ink); font-size: 14.5px; font-weight: 500;
  padding: 10px 12px; border-radius: 9px; cursor: pointer;
}
.csel-opt:active { background: var(--soft); }
.csel-opt.is-sel { background: var(--brand-soft); color: var(--brand-2); font-weight: 700; }
.select-with-default .default-check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); white-space: nowrap; cursor: pointer; }
/* 默认勾选统一为 pill 开关(见 .default-check input[type=checkbox] 规则);此处不再设 16px 方框 */

/* 表单内危险操作链接(删除预算) */
.danger-link { width: 100%; margin-top: 8px; border: 0; background: transparent; color: var(--danger); font-size: 13px; font-weight: 700; padding: 8px; cursor: pointer; border-radius: 8px; }
.danger-link:active { background: rgba(220,38,38,.08); }
/* 删除二次确认弹窗的红色主按钮 */
.danger-btn { height: 46px; border: 0; border-radius: var(--radius-md); background: var(--danger, #dc2626); color: #fff; font-size: 15px; font-weight: 800; cursor: pointer; }
.danger-btn:active { transform: scale(0.98); }
/* 确认删除弹窗:纯图标按钮(X=取消 / 垃圾桶=删除),文字走 aria-label */
.form-actions--confirm-icons { display: flex; gap: 12px; justify-content: center; }
.form-actions--confirm-icons > button { width: 60px; height: 50px; padding: 0; border-radius: 14px; display: inline-flex; align-items: center; justify-content: center; }
.form-actions--confirm-icons > button svg { width: 22px; height: 22px; }
.form-actions--confirm-icons > .secondary-button { background: var(--soft); color: var(--muted-strong); border: 0; }
.form-actions--confirm-icons > .secondary-button:active { transform: scale(0.97); }
.form-actions--confirm-icons > .danger-btn { height: 50px; background: var(--card); border: 1.5px solid var(--danger, #dc2626); color: var(--danger, #dc2626); }
.form-actions--confirm-icons > .danger-btn:active { background: rgba(220, 38, 38, 0.08); }

/* 自定义大月历日期选择器 */
/* 隐藏原生日历指示器,统一走自定义弹窗;只读 date 输入仍可点。
   iOS WebKit 的 date input 有固有宽度,不收缩会撑破弹窗(手机端日期框溢出),
   强制占满列宽+允许收缩+去掉原生外观。 */
input[type="date"] { cursor: pointer; width: 100%; min-width: 0; box-sizing: border-box; -webkit-appearance: none; appearance: none; }
input[type="date"]::-webkit-calendar-picker-indicator { display: none; -webkit-appearance: none; }
input[type="date"]::-webkit-date-and-time-value { text-align: left; }
/* date 输入显示层:原生 type=date 显示格式受系统区域控制(可能 yyyy/mm/dd),
   这里盖一层按 App 规则格式化的文本(id/en=dd/mm/yyyy · zh=yyyy/mm/dd),输入框 .value 仍存 ISO 不变。 */
.cal-field { position: relative; display: block; }
/* -webkit-text-fill-color:安卓 WebView 对 date 输入的 color 不可靠,原生文字会透出和覆盖层叠影 */
/* ⚠️ 原生 input 必须**收不到点击**。原来靠 pointerdown 里 preventDefault() 去压制
   iOS 的日期面板,但 WKWebView 上那个面板是在激活时开的,preventDefault 压不住 ——
   点框的右上角就会同时弹出系统日历和 App 日历两层(用户实拍)。
   pointer-events:none 之后点击落到 .cal-field 包裹层上,handler 照常拿得到
   (closest('.cal-field') 找的就是它),而 iOS 根本没看见 input 被点,自然不会弹。
   键盘 Tab 聚焦那条路仍由 focusin 兜底。 */
.cal-field > input[type="date"] { color: transparent; -webkit-text-fill-color: transparent; pointer-events: none; }
.cal-field > input[type="date"]::-webkit-datetime-edit { opacity: 0; }
.cal-field > input[type="date"]::-webkit-calendar-picker-indicator { opacity: 0; }
.date-display { position: absolute; inset: 0; display: flex; align-items: center; pointer-events: none; color: var(--ink); font: inherit; line-height: normal; white-space: nowrap; overflow: hidden; }
.date-display.empty { color: var(--muted); }
.cal-card { width: 360px; max-width: 94vw; padding: 18px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.cal-head strong { font-size: 17px; font-weight: 800; letter-spacing: -.01em; }
.cal-nav { width: 40px; height: 40px; border: 0; border-radius: 50%; background: var(--soft); color: var(--ink); font-size: 22px; line-height: 1; cursor: pointer; }
.cal-nav:active { transform: scale(0.94); }
.cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 6px; }
.cal-weekdays span { text-align: center; font-size: 11px; font-weight: 700; color: var(--muted); padding: 4px 0; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-grid button { aspect-ratio: 1 / 1; border: 0; border-radius: 12px; background: transparent; color: var(--ink); font-size: 15px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.cal-grid button:hover { background: var(--hover); }
.cal-grid button.is-empty { visibility: hidden; cursor: default; }
.cal-grid button.is-today { background: var(--card); color: var(--brand-2); box-shadow: inset 0 0 0 2px var(--brand-2); font-weight: 800; }
.cal-grid button.is-selected { background: var(--brand-grad); color: #fff; font-weight: 800; }
/* 今天永远白底橙边(即使同时是选中日),压过选中的橙色填充 */
.cal-grid button.is-selected.is-today { background: var(--card); color: var(--brand-2); box-shadow: inset 0 0 0 2px var(--brand-2); }
/* 结束日模式:选中日标红+「结束」小字,其后的日子变暗(不再计费) */
.cal-grid button.is-end { position: relative; background: var(--brand-grad); color: #fff; font-weight: 800; }
/* 选中日期不再写 Selesai 小字(用户嫌多余);data-end-label 已在 JS 去掉,::after 也移除 */
#calConfirm { display: inline-flex; align-items: center; justify-content: center; }
#calConfirm svg { width: 21px; height: 21px; }
.cal-grid button.is-after-end { opacity: .3; }
/* 禁选日(如实际记录禁未来):变灰不可点 */
.cal-grid button.is-disabled, .cal-grid button:disabled { opacity: .28; cursor: not-allowed; pointer-events: none; }
.cal-foot { display: flex; gap: 8px; margin-top: 16px; }
#calConfirm { background: var(--brand-grad); color: #fff; border: 0; }
.cal-foot button { flex: 1 1 0; min-width: 0; height: 44px; border-radius: var(--radius-md); font-size: 15px; font-weight: 700; white-space: nowrap; cursor: pointer; }
/* X 按钮的 .icon-x 默认锁死 48px → 日历底部改成和其它两个等宽 */
.cal-foot button.icon-x { width: auto !important; min-width: 0; }

/* ── Split Bill 分摊弹窗 ── */
.split-card { width: 420px; max-width: 94vw; max-height: 88vh; overflow-y: auto; overflow-x: hidden; box-sizing: border-box; }
/* 分摊表单坐落在白卡上(soft 灰输入框在白底上才有对比,不糊进灰页面) */
#splitReview { background: var(--card); border-radius: var(--radius); padding: 14px 16px 16px; box-shadow: var(--shadow-sm); margin-top: 4px; }
/* 手机端防溢出:所有 label 列布局,input 占满列宽且允许收缩(原生 input 有固有最小宽度) */
#splitReview label { display: grid; gap: 5px; min-width: 0; font-size: 13px; color: var(--muted-strong); }
#splitReview input, #splitReview select { width: 100%; min-width: 0; box-sizing: border-box; }
.split-mode-tabs button, .split-pay-tabs button { min-width: 0; padding: 0 6px; white-space: normal; line-height: 1.2; }
.split-source { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 4px; position: relative; }
/* file input 不用 hidden(display:none 会让 iOS 文件菜单没锚点飘到屏幕中间)——
   改成盖在「Foto Struk」按钮上的隐形锚点,菜单就从按钮位置出来,不乱飞 */
#splitPhotoInput { position: absolute; left: 16px; top: 14px; width: 44px; height: 44px; opacity: 0; pointer-events: none; z-index: 0; }
.split-photo-btn { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; height: 52px; border: 0; border-radius: var(--radius-md); background: var(--brand-grad); color: #fff; font-size: 15px; font-weight: 800; cursor: pointer; }
.split-photo-btn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.split-source .secondary-button { width: 100%; height: 52px; padding: 0 16px; border-radius: var(--radius-md); cursor: pointer; }
.split-parsing { margin: 10px 0 0; font-size: 13px; color: var(--muted); text-align: center; display: flex; align-items: center; justify-content: center; gap: 8px; }
.split-parsing::before { content: ""; width: 18px; height: 18px; flex: none; border: 2px solid var(--soft); border-top-color: var(--brand-2, #ff6a2b); border-radius: 50%; animation: authspin 0.7s linear infinite; }
@keyframes splitSpin { to { transform: rotate(360deg); } }
/* 分摊页对齐 app:所有输入框统一用 app 输入样式(原来不在 .finance-form 里,样式不一致) */
#splitReview input { height: 42px; width: 100%; min-width: 0; padding: 0 12px; border: 0; border-radius: var(--radius-sm); background: var(--soft); color: var(--ink); font-size: 14px; font-weight: 500; transition: background var(--dur) var(--ease); }
#splitReview input:focus { outline: none; border: 0; background: var(--hover); box-shadow: none; }
#splitReview label span { font-size: 12px; color: var(--muted-strong); font-weight: 600; }
#splitReview .form-row-2 label, #splitReview .split-fees label { display: grid; gap: 6px; }
.split-sub { display: block; font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--muted-strong); margin: 16px 0 8px; }
.split-items { display: flex; flex-direction: column; gap: 10px; }
/* 每个品项 = 一张小卡片(名称+价格+删除,人头 chip 收在卡内),和 app 卡片观感一致 */
.split-item { display: grid; grid-template-columns: minmax(0,1fr) 116px 26px; gap: 8px; align-items: center; padding: 0; border: 0; border-radius: 0; background: transparent; }
#splitItems .split-item input { height: 44px; border: 1px solid var(--line); border-radius: 12px; background: var(--card); padding: 0 12px; font-size: 14px; font-weight: 600; color: var(--ink); min-width: 0; }
#splitItems .split-item input:focus { outline: none; border-color: var(--brand-2); box-shadow: none; }
/* 价格框:Rp 前缀 + 右对齐数字,边框在外层 wrapper */
#splitItems .split-item .si-price { display: flex; align-items: center; gap: 4px; height: 44px; border: 1px solid var(--line); border-radius: 12px; background: var(--card); padding: 0 12px; }
#splitItems .split-item .si-price:focus-within { border-color: var(--brand-2); }
#splitItems .split-item .si-price .si-rp { flex: none; font-size: 12px; font-weight: 700; color: var(--muted); }
#splitItems .split-item .si-price input { height: auto; border: 0; border-radius: 0; background: transparent; padding: 0; text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.split-item .si-del { border: 0; background: transparent; color: var(--muted); font-size: 19px; cursor: pointer; padding: 0; justify-self: center; }
.split-item-chips { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 0; }
.split-item-chips button { min-height: 28px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--muted-strong); font-size: 12px; font-weight: 700; cursor: pointer; }
.split-item-chips button.on { background: var(--brand-grad); border-color: transparent; color: #fff; }
.split-fees { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
.split-fees label span { font-size: 12px; }
.split-fees input { min-height: 38px; }
.split-people { display: flex; flex-wrap: wrap; gap: 6px; }
.split-people button { min-height: 32px; padding: 0 13px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--muted-strong); font-size: 13px; font-weight: 700; cursor: pointer; }
.split-people button.on { background: var(--brand-grad); border-color: transparent; color: #fff; }
.split-people-hint { display: block; margin-top: 6px; font-size: 11px; color: var(--muted); }
.split-add-person { display: flex; gap: 8px; margin-top: 8px; }
.split-add-person input { flex: 1; min-height: 38px; }
.split-add-person button { flex: 0 0 auto; width: 44px; border-radius: var(--radius-md); font-size: 18px; cursor: pointer; }
/* Tambah nama 输入框:放大镜在框内靠左,点击开选人弹窗 */
.split-add-person .sap-field { position: relative; flex: 1; min-width: 0; }
.split-add-person .sap-field input#splitPersonInput { width: 100%; padding-left: 44px; }
.sap-search { position: absolute; left: 4px; top: 50%; transform: translateY(-50%); width: 34px; height: 34px; display: grid; place-items: center; border: 0; border-radius: 9px; background: transparent; color: var(--brand-2); cursor: pointer; }
.sap-search svg { width: 19px; height: 19px; }
.sap-search:active { background: var(--brand-soft); }
/* 选人搜索弹窗 */
.split-pick-search { display: flex; align-items: center; gap: 8px; height: 46px; border: 1px solid var(--line); border-radius: 14px; background: var(--card); padding: 0 14px; margin-bottom: 12px; }
.split-pick-search svg { flex: none; width: 18px; height: 18px; color: var(--muted); }
.split-pick-search input { flex: 1; min-width: 0; border: 0; background: transparent; font-size: 14px; color: var(--ink); outline: none; }
.split-pick-list { display: grid; gap: 6px; max-height: 46vh; overflow-y: auto; }
.split-pick-item { display: flex; align-items: center; gap: 12px; width: 100%; padding: 9px 12px; border: 1px solid var(--line); border-radius: 12px; background: var(--card); cursor: pointer; text-align: left; }
.split-pick-item.on { border-color: var(--brand-2); background: var(--brand-soft); }
.split-pick-item .spk-ic { flex: none; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: var(--brand-soft); color: var(--brand-2); font-weight: 800; font-size: 14px; }
.split-pick-item .spk-name { flex: 1; min-width: 0; font-size: 14px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.split-pick-item .spk-check { flex: none; width: 22px; height: 22px; color: var(--brand-2); }
.split-pick-item .spk-check svg { width: 22px; height: 22px; }
.split-mode-tabs, .split-pay-tabs { margin-top: 14px; }
.split-result { margin-top: 12px; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.split-result .sr-row { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: 14px; }
.split-result .sr-row:last-child { border-bottom: 0; }
.split-result .sr-row b { font-variant-numeric: tabular-nums; }
.split-result .sr-row.me { background: var(--soft); }
.split-result .sr-note { padding: 8px 14px; font-size: 11px; color: var(--muted); }
.split-result .sr-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.split-result .sr-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }
.split-result .sr-send { display: inline-flex; gap: 4px; }
.split-result .sr-ic { width: 30px; height: 30px; padding: 0; border: 0; border-radius: 8px; display: grid; place-items: center; cursor: pointer; transition: background var(--dur) var(--ease); }
.split-result .sr-ic svg { width: 17px; height: 17px; }
.split-result .sr-wa { background: rgba(37, 211, 102, 0.16); color: #25d366; }
.split-result .sr-wa:hover { background: rgba(37, 211, 102, 0.3); }
.split-result .sr-mail { background: var(--soft); color: var(--ink); }
.split-result .sr-mail:hover { background: var(--hover, var(--soft)); }
.sr-share-all { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 46px; border: 0; border-top: 1px solid var(--line); background: #25d366; color: #fff; font-weight: 800; font-size: 14px; cursor: pointer; transition: background var(--dur) var(--ease); }
.sr-share-all svg { width: 19px; height: 19px; }
.sr-share-all:hover { background: #20bd5a; }
.sr-email-all { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 46px; margin-top: 8px; border: 0; border-radius: 12px; background: var(--brand-grad); color: #fff; font-weight: 800; font-size: 14px; cursor: pointer; transition: filter var(--dur) var(--ease); }
.sr-email-all svg { width: 19px; height: 19px; }
.sr-email-all:active { filter: brightness(.95); }
.split-result .sr-email-all { border-top: 1px solid var(--line); border-radius: 0; margin-top: 0; background: var(--card); color: var(--brand-2); }
.split-detail-body .sr-email-all { margin-top: 8px; }
/* 历史明细弹窗里的「发给朋友」(WA/邮件)+ 整单分享 */
.split-detail-body .sd-share-row { align-items: center; }
.split-detail-body .sr-right { display: inline-flex; align-items: center; gap: 8px; flex: none; }
.split-detail-body .sr-send { display: inline-flex; gap: 4px; }
.split-detail-body .sr-ic { width: 30px; height: 30px; padding: 0; border: 0; border-radius: 8px; display: grid; place-items: center; cursor: pointer; transition: background var(--dur) var(--ease); }
.split-detail-body .sr-ic svg { width: 17px; height: 17px; }
.split-detail-body .sr-wa { background: rgba(37, 211, 102, 0.16); color: #25d366; }
.split-detail-body .sr-wa:hover { background: rgba(37, 211, 102, 0.3); }
.split-detail-body .sr-mail { background: var(--soft); color: var(--ink); }
.split-detail-body .sr-share-all { margin-top: 14px; border-top: 0; border-radius: 12px; }
.sd-close-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.sd-close-btn svg { width: 18px; height: 18px; }
/* 联系人 tab:+ 添加按钮 + 列表(新增/编辑走弹窗) */
/* 联系人弹窗:每字段 = 彩色图标 tile(齐左满高)+ 输入框 */
.contact-fields { display: grid; gap: 15px; margin-bottom: 6px; }
.cf-group { display: grid; gap: 8px; }
.cf-label { font-size: 12px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--muted-strong); padding-left: 2px; }
.cf-box { display: flex; align-items: stretch; border: 1px solid var(--line); border-radius: 16px; background: var(--card); overflow: hidden; box-shadow: var(--shadow-sm); }
.cf-box:focus-within { border-color: var(--brand-2); }
.cf-ic { flex: none; width: 56px; display: grid; place-items: center; }
.cf-ic svg { width: 24px; height: 24px; }
.cf-ic-name { background: var(--brand-soft); color: var(--brand-2); }
.cf-ic-wa { background: rgba(37, 211, 102, .14); color: #25d366; }
.cf-ic-mail { background: rgba(59, 130, 246, .12); color: #3b82f6; }
.cf-box input { flex: 1; min-width: 0; height: 56px; border: 0; background: transparent; padding: 0 14px; font-size: 15px; font-weight: 600; color: var(--ink); }
.cf-box input:focus { outline: none; box-shadow: none; }
.cf-hint { margin: 12px 2px 0; font-size: 11.5px; line-height: 1.4; color: var(--muted); }
/* 债务录入页内联利息提示:实际还款总额(红)/ 利息·每月·月息率。空内容自动收起,不占位。 */
/* 独立整行,左缩进对齐输入框(图标 46 + gap 14 = 60),负 margin 贴近上方字段;空则收起不占行 */
.debt-hint { display: block; padding-left: 2px; margin: -8px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--muted); font-variant-numeric: tabular-nums; }
.debt-hint:empty { display: none; }
.debt-hint-red { color: var(--danger, #dc2626); font-weight: 700; }
.contact-modal-actions { display: flex; gap: 10px; margin-top: 12px; }
.contact-save-btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 52px; border: 0; border-radius: 14px; background: var(--brand-grad); color: #fff; font-size: 15px; font-weight: 800; cursor: pointer; }
.contact-save-btn svg { width: 20px; height: 20px; }
.contact-save-btn:active { filter: brightness(.96); }
.contact-cancel-btn { flex: none; width: 60px; min-height: 52px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 14px; background: var(--card); color: var(--ink); cursor: pointer; }
.contact-cancel-btn svg { width: 20px; height: 20px; }
.contact-cancel-btn:active { background: var(--soft); }
/* 联系人:右上角圆形 + 按钮 */
.contact-tab-head { display: flex; justify-content: flex-end; margin-bottom: 10px; }
.contact-add-fab { width: 44px; height: 44px; flex: none; display: grid; place-items: center; border: 0; border-radius: 50%; background: var(--brand-grad); color: #fff; cursor: pointer; box-shadow: var(--shadow-sm); }
.contact-add-fab svg { width: 22px; height: 22px; }
.contact-add-fab:active { filter: brightness(.96); }
.contact-list { display: grid; gap: 8px; }
.contact-item { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: var(--card); border-radius: 14px; box-shadow: var(--shadow-sm); cursor: pointer; text-align: left; }
.contact-item:active { background: var(--soft); }
.contact-ic { flex: none; width: 40px; height: 40px; border-radius: 50%; background: var(--brand-soft); color: var(--brand-2); display: grid; place-items: center; font-weight: 800; font-size: 16px; }
.contact-main { flex: 1; min-width: 0; display: grid; gap: 2px; }
.contact-main b { font-size: 14px; font-weight: 700; color: var(--ink-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-item--me .contact-main b { display: flex; align-items: center; gap: 6px; overflow: visible; }
.contact-you { flex: none; font-size: 10px; font-weight: 800; letter-spacing: .02em; color: var(--brand-2); background: var(--brand-soft); border-radius: 6px; padding: 1px 6px; }
.contact-item--me { box-shadow: var(--shadow-sm), inset 0 0 0 1.5px var(--brand-soft); }
.contact-main small { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-main small .ci-mini { width: 13px; height: 13px; vertical-align: -2px; margin-right: 3px; opacity: .85; }
.contact-main .contact-empty { color: var(--muted); opacity: .7; }
.contact-acts { flex: none; display: flex; align-items: center; gap: 6px; }
.contact-acts .sr-ic { width: 32px; height: 32px; padding: 0; border: 0; border-radius: 9px; display: grid; place-items: center; cursor: pointer; }
.contact-acts .sr-ic svg { width: 16px; height: 16px; }
.contact-acts .sr-wa { background: rgba(37, 211, 102, 0.16); color: #25d366; }
.contact-acts .sr-mail { background: var(--soft); color: var(--ink); }
.contact-edit, .contact-del { flex: none; width: 32px; height: 32px; border: 0; border-radius: 9px; background: var(--soft); color: var(--muted); display: grid; place-items: center; cursor: pointer; }
.contact-edit svg { width: 15px; height: 15px; }
.contact-del { font-size: 18px; line-height: 1; }

/* ── 工具面板(我→资料→工具):Split Bill + 税计算器手风琴 ── */
.tool-list { border: 0; border-radius: var(--radius); overflow: hidden; background: var(--card); box-shadow: var(--shadow-sm); }
.tool-row { position: relative; display: grid; grid-template-columns: 56px 1fr auto; align-items: center; gap: 15px; width: 100%; padding: 16px 18px; border: 0; background: transparent; color: var(--ink); cursor: pointer; text-align: left; }
/* 行间内缩分隔线(从图标右侧标题处起) */
.tool-row:not(:last-of-type)::after { content: ""; position: absolute; left: 89px; right: 18px; bottom: 0; height: 1px; background: var(--line); }
.tool-row .tool-ic { display: grid; place-items: center; width: 56px; height: 56px; border-radius: 16px; flex: none; }
.tool-row .tool-ic svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.tool-ic-purple { background: rgba(139, 92, 246, 0.13); color: #8b5cf6; }
.tool-ic-green  { background: rgba(16, 185, 129, 0.13); color: #10a35e; }
.tool-ic-red    { background: rgba(239, 68, 68, 0.12); color: #ef4444; }
.tool-ic-blue   { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.tool-ic-orange { background: rgba(255, 138, 61, 0.16); color: #ff6a2b; }
/* 工具有 7 个而原来只有 5 色(紫/绿各重复一次)。补两色,做到一工具一色。 */
.tool-ic-teal   { background: rgba(20, 184, 166, 0.13); color: #0d9488; }
.tool-ic-pink   { background: rgba(236, 72, 153, 0.12); color: #db2777; }
.tool-text { min-width: 0; }
.tool-text b { display: block; font-size: 17px; font-weight: 800; letter-spacing: -0.01em; }
.tool-text small { display: block; margin-top: 3px; font-size: 13px; font-weight: 500; color: var(--muted); line-height: 1.35; }
.tool-row .tool-chev { width: 20px; height: 20px; flex: none; color: var(--muted); fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.tool-row:active { background: var(--soft); }
.tool-acc { padding: 4px 16px 16px; border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 10px; }
.tool-acc label { display: flex; flex-direction: column; gap: 5px; font-size: 13px; color: var(--muted-strong); }
.tool-acc input, .tool-acc select { min-height: 40px; }
.tool-result { border: 0; border-radius: var(--radius-sm); overflow: hidden; background: var(--soft); }
.tool-result .tr-row { display: flex; justify-content: space-between; gap: 12px; padding: 11px 14px; border-bottom: 1px solid var(--card); font-size: 14px; color: var(--ink); }
.tool-result .tr-row:last-child { border-bottom: 0; }
.tool-result .tr-row b { font-variant-numeric: tabular-nums; }
.tool-result .tr-row.hl { background: var(--brand-soft); font-weight: 800; color: var(--ink-strong); }
.tool-result:empty { display: none; }
.tool-disclaimer { margin-top: 10px; font-size: 11px; color: var(--muted); text-align: center; }
/* 分摊记录列表 */
.split-history { display: flex; flex-direction: column; gap: 12px; }
.sh-item { border: 0; border-radius: var(--radius); padding: 16px; background: var(--card); box-shadow: var(--shadow-sm); cursor: pointer; transition: background var(--dur) var(--ease); }
.sh-item:hover, .sh-item:focus-visible { background: var(--soft); outline: none; }
.sh-item .sh-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.sh-item .sh-top strong { flex: 1 1 auto; font-size: 16px; font-weight: 800; color: var(--ink-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.sh-item .sh-top b { flex: none; font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink-strong); }
.sh-item .sh-sub { display: block; margin-top: 6px; color: var(--muted); font-size: 12.5px; }
/* 分摊明细:横向分栏(每人一栏:圆点+名字 / 金额),上方分隔线 + 栏间竖线 */
.sh-item .sh-shares { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 14px; margin-top: 13px; padding-top: 14px; border-top: 1px solid var(--line); }
.sh-share { display: grid; gap: 5px; padding: 0 12px; min-width: 0; border-left: 1px solid var(--line); }
.sh-share:nth-child(3n+1) { border-left: 0; padding-left: 0; }
.sh-share-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sh-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.sh-share-name { font-size: 14px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-share-amt { font-size: 13.5px; font-weight: 600; color: var(--muted-strong); font-variant-numeric: tabular-nums; }
/* 超过 3 人:第 3 栏「+N 其他」 */
.sh-share--more { align-content: center; gap: 1px; }
.sh-more-n { font-size: 15px; font-weight: 800; color: var(--brand-2); }
.sh-more-lab { font-size: 11px; color: var(--muted); }
.sh-badge { font-style: normal; font-size: 10px; font-weight: 800; padding: 1px 7px; border-radius: 999px; background: rgba(52,211,153,.14); color: #34d399; }
/* 分摊明细弹窗 */
.split-detail-body { display: grid; gap: 10px; }
/* 灰底弹窗 + 白色模块卡(无描边),间距露出灰底做分区 */
.split-detail-body .sd-card { background: var(--card); border: 0; border-radius: 16px; padding: 4px 16px; box-shadow: var(--shadow-sm); }
.split-detail-body .sd-card-head { font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding: 12px 0 2px; }
/* 滚动条收细、低调 */
#splitDetailModal .split-detail-body::-webkit-scrollbar { width: 5px; }
#splitDetailModal .split-detail-body::-webkit-scrollbar-thumb { background: var(--line); border-radius: 99px; }
#splitDetailModal .split-detail-body::-webkit-scrollbar-track { background: transparent; }
/* 弹窗整体灰底,模块白卡;X、记账区也跟随 */
#splitDetailModal .modal-card { background: var(--bg); }
#splitDetailModal .modal-x { background: var(--card); box-shadow: var(--shadow-sm); }
#splitDetailModal .sd-record { background: var(--card); border-radius: 16px; padding: 14px 16px; box-shadow: var(--shadow-sm); }
.split-detail-body .txd-row { border-bottom: 0; padding: 9px 0; }
.split-detail-body .sd-total > b { font-size: 20px; font-weight: 800; color: var(--brand-2); }
.split-detail-body .sd-dish { padding: 8px 0; border-bottom: 0; }
.split-detail-body .sd-dish-top { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; font-weight: 700; }
.split-detail-body .sd-dish small { display: block; margin-top: 2px; font-size: 12px; color: var(--muted); }
/* 明细弹窗内容过长 → 可滚动(原来撑爆视口看不到下面) */
#splitDetailModal .modal-card { max-height: 88vh; max-height: 88dvh; }
#splitDetailModal .split-detail-body { max-height: 56vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
/* 记账区:未记账两个按钮,已记账状态+取消 */
.sd-record { display: grid; gap: 8px; }
.sd-rec-hint { font-size: 12px; color: var(--muted); font-weight: 600; }
/* 记账方式:两个清晰按钮(主橙填充 + 描边),不是开关 */
.sd-rec-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.sd-rec-btns button { min-height: 46px; border-radius: var(--radius-md); font-size: 14px; font-weight: 800; cursor: pointer; }
.sd-rec-btns .sd-rec-primary { border: 0; background: var(--brand-grad); color: #fff; }
.sd-rec-btns .sd-rec-primary:active { filter: brightness(.96); }
.sd-rec-btns .secondary-button:active { transform: scale(0.99); }
/* Simpan Gambar:橙色描边 */
.sd-foot-actions { display: flex; align-items: stretch; gap: 10px; }
.sd-foot-actions .sd-saveimg-btn { flex: 1 1 auto; width: auto; min-height: 48px; border-radius: var(--radius-md); font-size: 15px; font-weight: 800; cursor: pointer; }
/* 主按钮=分享(饱和橙填充);次按钮=存相册(描边) */
.sd-saveimg-btn { border: 0; background: var(--accent-grad); color: #fff; }
.sd-saveimg-btn:active { transform: scale(0.99); }
.sd-saveimg-btn--ghost { border: 1.5px solid var(--brand-2); background: var(--card); color: var(--brand-2); }
.sd-saveimg-btn--ghost:active { background: var(--brand-soft); transform: none; }
.sd-foot-actions .sd-saveimg-btn--icon { flex: 0 0 auto; width: 48px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.sd-saveimg-btn--icon svg { width: 21px; height: 21px; }
.sd-cancel-btn { flex: 0 0 auto; width: 48px; min-height: 48px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 1.5px solid var(--line); border-radius: var(--radius-md); background: var(--card); color: var(--muted, #64748b); cursor: pointer; }
.sd-cancel-btn svg { width: 20px; height: 20px; }
.sd-cancel-btn:active { background: var(--soft); }
.sd-rec-status { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 800; color: var(--ok, #16a34a); }
.sd-rec-status svg { width: 18px; height: 18px; }
/* 撤销记账:红色调按钮(轻提示这是撤销,非主操作) */
.sd-rec-undo { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 46px; margin-top: 10px; border: 0; border-radius: var(--radius-md); background: rgba(220, 38, 38, .10); color: var(--danger, #dc2626); font-size: 14px; font-weight: 800; cursor: pointer; }
.sd-rec-undo svg { width: 18px; height: 18px; }
.sd-rec-undo:active { background: rgba(220, 38, 38, .16); }
/* 只读自动字段(小计):看得出是算出来的,不是手填 */
.split-fees input.is-auto { opacity: .85; cursor: default; }
.sh-badge.calc { background: var(--soft); color: var(--muted-strong); }
/* 工具子页面表单 + 分摊页 */
/* 工具计算页:白卡容器 + 无边框 soft 输入 + 大写小标签(与全 App 一致) */
.tool-page-form { display: flex; flex-direction: column; gap: 14px; background: var(--card); border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow-sm); }
.tool-page-form label { display: grid; gap: 6px; min-width: 0; }
.tool-page-form label > span { font-size: 12px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); }
/* Salin Cepat:字段行 = 标签 | 可编辑值 | 复制按钮。容器复用 tool-page-form 卡片 */
.salin-fields { display: grid; gap: 10px; }
.salin-row { display: grid; grid-template-columns: 84px minmax(0, 1fr) 40px; gap: 10px; align-items: center; }
.salin-row label { font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); }
/* 逐字段复制:方形图标按钮,tinted 品牌色(同 tool-ic 语言),点后变绿打勾 */
.salin-row .salin-copy {
  width: 40px; height: 40px; flex: none; padding: 0; display: grid; place-items: center;
  border: 0; border-radius: var(--radius-sm); cursor: pointer;
  background: var(--brand-soft); color: var(--brand-2);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.salin-row .salin-copy svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.salin-row .salin-copy:active { transform: scale(.92); }
.salin-copy.copied { background: rgba(16, 185, 129, .16); color: #10a35e; }
/* Salin Semua:整块工整信息一键复制,主行动按钮,排字段下面 */
.salin-copy-all {
  margin-top: 4px; width: 100%; height: 46px; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1.5px solid var(--brand-2); border-radius: var(--radius-sm); cursor: pointer;
  background: var(--brand-soft); color: var(--brand-2); font-size: 14px; font-weight: 700;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.salin-copy-all svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.salin-copy-all:active { transform: scale(.98); }
.salin-copy-all.copied { background: rgba(16, 185, 129, .16); border-color: #10a35e; color: #10a35e; }
#toolSalinPanel textarea { width: 100%; min-height: 96px; resize: vertical; box-sizing: border-box; border: 0; border-radius: var(--radius-sm); background: var(--soft); color: var(--ink); font-size: 15px; padding: 12px 14px; font-family: inherit; }
.tool-page-form input, .tool-page-form select { width: 100%; min-width: 0; box-sizing: border-box; height: 44px; border: 0; border-radius: var(--radius-sm); background: var(--soft); color: var(--ink); font-size: 15px; padding: 0 14px; transition: background var(--dur) var(--ease); }
.tool-page-form input:focus, .tool-page-form select:focus { outline: none; background: var(--hover); }
/* 贷款计算器:tab 描边 + 表单内统一间距(含费用→结果)+ 费用 Rp/% 切换 */
.loan-tabs, .loan-rate-tabs { border: 1px solid var(--line); }
#loanFormInterest, #loanFormInstallment { display: flex; flex-direction: column; gap: 14px; }
.loan-fee-row { display: flex; gap: 8px; align-items: center; }
.loan-fee-row > input { flex: 1; min-width: 0; }
.loan-fee-unit { flex: none; display: flex; gap: 2px; height: 44px; padding: 4px; box-sizing: border-box; border-radius: var(--radius-sm); background: var(--soft); }
.loan-fee-unit button { min-width: 42px; border: 0; border-radius: calc(var(--radius-sm) - 3px); background: transparent; color: var(--muted-strong); font-size: 14px; font-weight: 700; cursor: pointer; }
.loan-fee-unit button.active { background: var(--brand-grad); color: #fff; }
.split-add-item { width: 100%; min-height: 42px; margin-top: 8px; border: 0; border-radius: var(--radius-md); background: var(--brand-soft); color: var(--brand-2); font-weight: 800; font-size: 14px; cursor: pointer; }
.split-add-item:active { background: rgba(255, 87, 34, .16); }
/* 聊天"正在输入"点点点 */
.typing-bubble { display: inline-flex; align-items: center; gap: 5px; min-height: 18px; }
.typing-bubble .tdot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); animation: tdot 1.2s ease-in-out infinite; }
.typing-bubble .tdot:nth-child(2) { animation-delay: .18s; }
.typing-bubble .tdot:nth-child(3) { animation-delay: .36s; }
@keyframes tdot { 0%, 60%, 100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }
/* App 内报表预览 overlay */
.report-preview-overlay { position: fixed; inset: 0; z-index: 1300; background: var(--bg, #0d0e13); display: flex; flex-direction: column; }
.report-preview-overlay[hidden] { display: none; }
.rp-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: calc(env(safe-area-inset-top, 0px) + 10px) 14px 10px; }
.rp-head strong { font-size: 16px; }
.rp-head .secondary-button { min-height: 36px; padding: 0 16px; border-radius: var(--radius-md); cursor: pointer; }
#reportPreviewFrame { flex: 1; width: 100%; border: 0; background: #fff; }
.ppn-tabs { margin: 2px 0 0; }


/* ══ 原生端性能:关掉剩余的 backdrop-filter ═══════════════════════════
   真机反馈「所有动效都卡」。根因不是某一个动画写得差,是**整页的合成成本**:
   backdrop-filter 会把元素提成独立合成层,并且**背景内容一变就要重新采样重算**
   —— 页面任何地方动一下,屏幕上所有毛玻璃层全部重算。常驻可见的有七八个,
   于是每个动画都在跟它们抢帧。iOS WKWebView 上 blur(18px)+saturate(160%) 尤其贵。

   已在上面直接删掉的是「本来就看不见」的那几处(背景不透明 / 背后是平滑渐变)。
   这里剩下的确实盖在滚动文字上,模糊肉眼可见,所以只在**原生**关闭,网页版保留。
   关闭后底色统一提到 0.94 —— 原来 0.7 是靠模糊补不透明度的,不提就会透出文字。

   若日后想恢复毛玻璃,删掉这一整块即可,其余样式没被改动。 */
body.native-app .ov-search-bar,
body.native-app .transaction-search input,
body.native-app .transaction-search .tx-export-btn,
body.native-app .composer-bar,
body.native-app .savings-goal-stats > span,
body.native-app #incomeLogSearch,
body.native-app #reimburseSearch,
body.native-app .app-view:has(.split-workspace.drill-open) .drillable-head,
body.native-app .ota-ready {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
body.native-app .ov-search-bar,
body.native-app .transaction-search input,
body.native-app .transaction-search .tx-export-btn,
body.native-app .composer-bar,
body.native-app .savings-goal-stats > span,
body.native-app #incomeLogSearch,
body.native-app #reimburseSearch { background: rgba(255, 255, 255, 0.94); }
:root[data-theme="dark"] body.native-app .ov-search-bar,
:root[data-theme="dark"] body.native-app .transaction-search input,
:root[data-theme="dark"] body.native-app .transaction-search .tx-export-btn,
:root[data-theme="dark"] body.native-app .composer-bar,
:root[data-theme="dark"] body.native-app .savings-goal-stats > span,
:root[data-theme="dark"] body.native-app #incomeLogSearch,
:root[data-theme="dark"] body.native-app #reimburseSearch { background: rgba(17, 26, 46, 0.94); }
body.native-app .ota-ready { background: rgba(8, 10, 16, 0.92); }

/* 底栏的 will-change 只在键盘进出那 250ms 需要。常驻的话等于永久多一个合成层,
   而底栏是全 App 一直在的元素 —— 白白占着显存和合成预算。 */
body.native-app.kb-open .bottom-nav,
body.native-app .bottom-nav:hover { will-change: transform; }


/* ── 展开/收缩的过程动画 ────────────────────────────────────────────
   高度是 auto,没法直接 transition。grid-template-rows: 0fr → 1fr 是目前唯一
   能「过渡到自动高度」的纯 CSS 手段(不用 JS 量高度、不用写死 max-height ——
   max-height 那套要猜一个足够大的值,收起时会先空跑一段,看着就是延迟)。
   内层必须 overflow:hidden + min-height:0,否则内容不会被裁,高度动画看不出来。 */
.bal-collapse-wrap {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  /* 前后对称的加速/减速。原来那条前重(前 32% 时间走完 72% 行程),
     单段 transition 上的表现就是「猛开一下,剩下慢慢爬」。 */
  transition: grid-template-rows 340ms cubic-bezier(.45, .05, .25, 1),
              opacity 240ms cubic-bezier(.45, .05, .25, 1);
}
.bal-collapse-wrap.open { grid-template-rows: 1fr; opacity: 1; }
.bal-collapse-wrap > div { overflow: hidden; min-height: 0; }
@media (prefers-reduced-motion: reduce) {
  .bal-collapse-wrap { transition: none; }
}


/* ══ 键盘接管(配合 capacitor.config.ts 的 resize: none) ═══════════
   resize:none 之后 WebView 不再自动避让键盘,**布局全靠 --kb-h**。
   这里的分工是整套方案的关键:

     布局(尺寸)—— 一次到位,**不加 transition**。
                    动画尺寸=每帧重排,那正是原来卡的原因。
     动画(位移)—— 只用 transform,走合成器,才可能满帧。见 app.js 的 FLIP。

   --kb-h 默认 0px,所以网页端 / 键盘收起时这些 calc 全部退化成原值,零影响。 */
:root { --kb-h: 0px; }

/* 主界面:可用高度直接减掉键盘。顶栏留在原位,内容区(1fr)自动压缩,
   输入条正好落在键盘上沿 —— 这就是 ChatGPT 那个位置关系。
   ⚠️⚠️ 基准**不能**用 height:100% —— 那正是「键盘弹出后输入框不见了」的真凶。
   百分比高度要求父级高度是**确定值**,而这条链上全是不确定的:
       body            没有确定高度(只有 min-height)
       .app-shell      height:100%  → 父级不确定 ⇒ 退化成 auto
       .phone-app      calc(100% - var(--kb-h)) → 同样退化成 auto
   退化之后 .phone-app 由 .app-shell(display:grid; place-items:stretch;
   min-height:100dvh)拉满,高度压根不是自己算的,--kb-h 写得再对也没人用。
   真机实测:takeover=true、--kb-h=328px 都正常,phoneAppH 却仍是 667px(=innerH),
   输入条 bottom=667 正好被 328px 高的键盘盖住。
   也不能改用 100dvh:同文件里 .modal-card 那段注释记着 iOS 的 dvh 自己会扣键盘,
   再减一次就是减两次。所以改用 JS 写入的确定像素值(见 app.js setAppHeightVar),
   彻底绕开百分比链和视口单位语义。--app-h 没写入时退回 100dvh,与原行为等价。 */
body.native-app .phone-app {
  height: calc(var(--app-h, 100dvh) - var(--kb-h));
  /* ⚠️⚠️ 这一行才是关键。上面 @media (max-width:540px) 里有
       .phone-app { min-height: 100vh }
     手机宽度必然命中,而 min-height **优先于 height** —— 无论 height 算成多少,
     元素都会被顶回整屏高。真机实测:--app-h/--kb-h 全对、height 也算出 339px,
     但 min-height 是 667px,最终用的还是 667px,输入条照样被键盘盖住。
     height 已经是确定值,min-height 没有存在意义,清零。 */
  min-height: 0;
}

/* 弹窗是 position:fixed;inset:0 的居中容器。不收底的话「居中」是按整屏算的,
   键盘一起来卡片就有一半在键盘后面。把可用区底边抬到键盘上沿,居中自然正确。 */
body.native-app .modal-backdrop { bottom: var(--kb-h); }
/* ⚠️ 卡片自己的限高也必须减键盘。.modal-card 原本是 calc(100dvh - 40px),
   而 100dvh 始终是**整屏**高度、不随键盘变 —— 只抬遮罩底边的话,卡片仍然按整屏
   算限高,于是比可用区还高,底部被裁掉(真机上表现为 Simpan 按钮只剩一半)。 */
/* ⚠️ 这里必须用 vh 不能用 dvh。iOS 上 dvh 是「动态视口」,键盘弹出时**它自己就会
   缩掉一个键盘的高度** —— 再减 var(--kb-h) 就是**减了两次**,卡片被压成只剩标题
   那一条(真机实拍就是这个样子)。vh 是「大视口」,不随键盘变,才是这里要的基准。
   注意 .phone-app 用的是 100%(相对 .app-shell),不走 dvh,所以外层布局一直是对的
   —— 表现就是输入条正常贴着键盘、唯独卡片被压扁,当时正是这个线索指到这里。 */
body.native-app .modal-card { max-height: calc(100vh - 40px - var(--kb-h)); }
/* 另外两处自带限高的卡片。#splitDetailModal 那条权重是 (0,1,1)+id=110,**压过**
   上面的 body.native-app .modal-card(20),不单独写就仍然按整屏算 → 照样被裁。
   (.admin-modal-card 不在这里 —— admin 是网页后台,不跑原生壳。) */
body.native-app #splitDetailModal .modal-card { max-height: calc(88vh - var(--kb-h)); }
body.native-app .ad-modal-card { max-height: calc(88vh - var(--kb-h)); }

/* FLIP 的动画段:只在键盘进出的那 250ms 挂 transition,平时不挂 ——
   常驻 transition 会让别处任何 transform 改动都被动画,出意外位移。
   曲线是 iOS 键盘私有曲线(UIViewAnimationCurve 7)的通用近似。 */
/* ⚠️ 名单里**不含** .app-view —— 它的顶边不该动。用 transform 把它推下去再拉回,
   起手那一帧会在顶栏底下露出一条空隙。而它真正变化的是**底边**(高度),
   transform 根本表达不了尺寸。所以内容区一次性重排,由紧贴键盘的输入条承担动画感。 */
/* 时长和曲线都由 JS 写入,来源是 iOS 通知里的**实测值**(见 KeyboardInfoBridge.swift)。
   写死 250ms 只是常见值 —— 分屏、外接键盘、辅助功能都会改它;曲线更是私有的
   curve 7,公开 API 里没有。跟不跟手,差就差在这两个数对不对。
   兜底值保留:老壳没有那个插件时,退回原来的近似。 */
/* 只剩弹窗卡片 —— 聊天区(.composer / #messages)已从 FLIP 名单移除,改为瞬时到位。
   原因见 app.js 的 _kbFlipTargets 注释:#messages 位置没动只是变矮,平移它会把整块
   聊天内容推出可视区(键盘一弹内容消失再飞回);而只平移输入条又和消息区错位=闪动。 */
body.native-app.kb-animating .modal-card {
  transition: transform var(--kb-dur, 250ms) var(--kb-ease, cubic-bezier(.38, .7, .125, 1));
}
@media (prefers-reduced-motion: reduce) {
  body.native-app.kb-animating .modal-card { transition: none; }
}


/* ══ 开关的彩色填充层(对齐 iOS 飞行模式) ══════════════════════════
   实拍 iOS 关闭动画:绿色不是「淡出」,是**整块向内收缩**(白圈从外往里长,
   绿色越缩越小),最后滑块落位成圆。全程约 330ms。

   而原来的写法有个硬伤:
     关 background: var(--line-strong)  → 纯色 = background-color
     开 background: var(--brand-grad)   → 渐变 = background-image
   background-image 在 none 与渐变之间**不可插值**,浏览器只能瞬间切换。
   于是滑块滑 320ms、轨道颜色啪一下就变 —— 一半动画是跳的,这就是「不够顺滑」。

   改法:彩色移到 ::before 独立一层,用 transform+opacity 做收缩/展开
   (两者都走合成器,可插值也不触发重排)。::before 天然画在 ::after(滑块)
   下面,层序正确,不用 z-index。 */
.switch-row input[type="checkbox"]::before,
.default-check input[type="checkbox"]::before,
.income-monthly-switch input[type="checkbox"]::before,
input.pill-switch[type="checkbox"]::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--brand-grad);
  transform: scale(.5);
  opacity: 0;
  /* 提层:这层是渐变填充,不提层的话每一帧都要按新尺寸重新栅格化渐变。
     提层后渐变只栅格一次,动画期间只有合成器在做变换。
     常驻(而非动画时才加)是因为开关状态随时会被点,加/摘 will-change 本身
     也会触发一次图层重建 —— 44x26 的小图层,常驻的内存代价可以忽略。 */
  will-change: transform, opacity;
  /* 单段 transition,曲线整段生效,可以直接用 bezier。
     换成前后对称的加速/减速(原来那条前重,和滑块的节奏对不上)。 */
  transition: transform 340ms cubic-bezier(.45, .05, .25, 1),
              opacity 240ms cubic-bezier(.45, .05, .25, 1);
}
.switch-row input[type="checkbox"]:checked::before,
.default-check input[type="checkbox"]:checked::before,
.income-monthly-switch input[type="checkbox"]:checked::before,
input.pill-switch[type="checkbox"]:checked::before {
  transform: scale(1);
  opacity: 1;
}
/* 轨道自身只留「关」态底色 —— 彩色交给上面那层,否则两者叠加,
   收缩动画会被底下的渐变盖住看不见。 */
.switch-row input[type="checkbox"]:checked,
.default-check input[type="checkbox"]:checked,
.income-monthly-switch input[type="checkbox"]:checked,
input.pill-switch[type="checkbox"]:checked { background: var(--line-strong); }

@media (prefers-reduced-motion: reduce) {
  .switch-row input[type="checkbox"]::before,
  .default-check input[type="checkbox"]::before,
  .income-monthly-switch input[type="checkbox"]::before,
  input.pill-switch[type="checkbox"]::before { transition: none; }
}
