/* redesign-78 · 8b-2＋P2＋P3（第 67 批，補丁式合入 77e）*/
/* 養成家 — 手機優先、大按鈕 */

/* Nunito 自架（可變字重 400–800，僅英數；中文走系統蘋方／正黑）
   取代原 Google Fonts CDN（2026-07-24 定案：不外連）。
   第 65 批（Tom 2026-08-28 拍板「補 400」）：字檔本來就是完整可變字型，
   當年宣告鎖 600 起跳才讓數字永遠比中文粗——放寬到 400 即根治，零新檔案。 */
@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/nunito-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Token v2 — 名稱不變、值系統化；新增別名皆向下相容 */
  --bg: #f4f8f7;
  --bg-blur: rgba(244, 248, 247, 0.92);  /* = --bg @ 92%，貼頂毛玻璃條專用 */
  --bg-accent: #e8f1ef;
  --surface: #ffffff;
  --surface-2: #eef3f3;
  --ink: #24313f;
  --ink-muted: #5b6b7b;
  /* 2026-08-01：原本 #93a1ae 在白底只有 2.64:1、在 --surface-2 更低到 2.36，
     而它用在 0.75rem 的小字上（WCAG AA 要 4.5:1）。壓深到三種底色都過關。 */
  --ink-soft: #5f6d78;
  --line: #e6ecea;
  --brand: #0d7377;
  --brand-dark: #095c5f;
  /* --brand-soft 只用於背景（淺）；框線一律用 --brand-border */
  --brand-soft: #e2f3f0;
  --brand-border: #b8ddd9;
  --accent: #e8a838;
  --accent-ink: #8a5a10;
  --accent-soft: #fdf5e6;
  --danger: #c45c5c;
  --danger-ink: #a94040;
  --danger-soft: #f9ecec;
  --ok: #2d8a6e;
  --ok-ink: #1f6b54;
  --ok-soft: #e3f2ec;
  /* 股票漲跌（台股紅漲綠跌）；與成功／危險分開，可各自微調 */
  --up: #c94f4f;
  --down: #2d8a6e;
  --radius: 20px;
  --r-ctl: 12px;
  --shadow: 0 1px 2px rgba(13, 52, 49, 0.05), 0 8px 24px rgba(13, 52, 49, 0.07);
  --tab-h: 64px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --font: "Nunito", "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", sans-serif;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 17px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font);
  color: var(--ink);
  background:
    radial-gradient(ellipse 120% 80% at 10% -10%, var(--bg-accent), transparent 55%),
    radial-gradient(ellipse 90% 60% at 100% 0%, #f3efe4, transparent 50%),
    var(--bg);
  line-height: 1.45;
}

a {
  color: var(--brand);
  text-decoration: none;
}

.app-shell {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  padding-bottom: calc(var(--tab-h) + var(--safe-bottom) + 1rem);
}

.app-header {
  padding: max(0.75rem, env(safe-area-inset-top)) 1.1rem 0.55rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  min-width: 0;
}

.brand-mark {
  /* 約等於標題＋副標總高，避免圖太小、字太大 */
  width: 52px;
  height: 52px;
  flex: 0 0 auto;
  border-radius: var(--r-ctl);
  object-fit: cover;
  display: block;
}

.brand {
  font-weight: 800;
  font-size: var(--t-num);
  letter-spacing: 0.02em;
  color: var(--brand-dark);
  line-height: var(--lh-tight);
}

.brand-sub {
  display: block;
font-weight: var(--w-body);
  color: var(--ink-muted);
  margin-top: 0.1rem;
  letter-spacing: 0.01em;
}

.header-meta {
  font-size: var(--t-sub);
  color: var(--ink-muted);
  text-align: right;
}

.header-meta a {
  color: var(--ink-muted);
  font-weight: var(--w-body);
}

.header-user-name {
  font-weight: 700;
  color: var(--ink);
}

.header-links {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.35rem;
  margin-top: 0.15rem;
  flex-wrap: wrap;
}

.header-sep {
  opacity: 0.55;
}

.header-view-switch {
  position: relative;
  display: inline-block;
}

.header-view-switch > summary {
  list-style: none;
  cursor: pointer;
  font-weight: var(--w-strong);
  font-size: var(--t-sub);
  color: var(--brand-dark);
  text-decoration: underline;
  text-underline-offset: 2px;
  user-select: none;
}

.header-view-switch > summary::-webkit-details-marker {
  display: none;
}

.header-view-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 0.4rem);
  z-index: 50;
  min-width: 10rem;
  background: #fff;
  border-radius: var(--r-ctl);
  box-shadow: var(--shadow);
  padding: 0.35rem;
  text-align: left;
}

.header-view-menu form {
  margin: 0;
}

.header-view-menu button {
  display: block;
  width: 100%;
  border: none;
  background: transparent;
  text-align: left;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  padding: 0.5rem 0.6rem;
  border-radius: var(--r-ctl);
  cursor: pointer;
}

.header-view-menu button:hover,
.header-view-menu button:focus-visible {
  background: var(--brand-soft);
}

main {
  padding: 0.5rem 1.1rem 1rem;
}

.page-title {
  font-size: var(--t-num);
  font-weight: 800;
  line-height: var(--lh-tight); /* 波8b：與 .brand 統一（原繼承 1.45） */
  margin: 0 0 0.35rem;
}

.page-lead {
  margin: 0 0 1.1rem;
  color: var(--ink-muted);
  font-size: var(--t-body);
}

.card-soft {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--sp-4); /* 8b-2:上下左右歸一(原 1.1/1.15 差 0.85px) */
  margin-bottom: var(--sp-3);
}

.muted {
  font-weight: var(--w-body); /* 波8b：說明字自己擁有字重，不看容器臉色 */
  color: var(--ink-muted);
}

.flash-list {
  list-style: none;
  padding: 0;
  margin: 0 0 0.85rem;
}

.flash {
  padding: 0.7rem 0.9rem;
  border-radius: var(--r-ctl);
  margin-bottom: 0.45rem;
  font-weight: var(--w-body);
}

.flash-success { background: #d9f0e7; color: #1d5c48; }
.flash-warning { background: #fff1d6; color: #8a5a10; }
.flash-danger  { background: #f8e0e0; color: #8a3030; }
.flash-info    { background: #dceff0; color: #0d5558; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: 48px;
  padding: 0.7rem 1.15rem;
  border: none;
  border-radius: var(--r-ctl);
  font-family: inherit;
  font-weight: 700;
  line-height: 1.3; /* 波8b：兩行按鈕（原 normal≈1.2 中文糊在一起） */
  cursor: pointer;
  text-align: center;
}

a.btn { text-decoration: none; }

.btn-primary {
  background: var(--brand);
  color: #fff;
  width: 100%;
}

.btn-primary:hover { background: var(--brand-dark); }

.btn:disabled,
.btn[disabled] {
  opacity: 0.65;
  cursor: wait;
}

.field {
  margin-bottom: 0.9rem;
}

.field-row {
  display: grid;
  /* minmax(0,…)：date/time input 有固有最小寬，不壓會在窄機爆版 */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
}

.field-row .field input {
  min-width: 0;
}

.field-row .field {
  margin-bottom: 0.9rem;
}

.field label {
  display: block;
  font-weight: 700;
  margin-bottom: 0.35rem;
}

/* 勾選類要排除，否則 radio／checkbox 會被撐成整行輸入框 */
.field input:not([type="radio"]):not([type="checkbox"]),
.field select,
.field textarea {
  width: 100%;
  min-height: 48px;
  padding: 0.65rem 0.85rem;
  border: 2px solid var(--brand-border);
  border-radius: var(--r-ctl);
  font-family: inherit;
  font-size: var(--t-body);
  background: #fff;
  color: var(--ink);
}

.field input[type="radio"],
.field input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--brand);
  flex: none;
}

/* 選項膠囊：文字與圓鈕同一行 */
.chip-row label.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brand);
}

.login-wrap {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 1.75rem 1.25rem 2rem;
  max-width: 420px;
  margin: 0 auto;
}

.remember-row {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  margin: 0 0 0.55rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
}

.remember-row input {
  margin-top: 0.2rem;
  flex: 0 0 auto;
}

.login-remember-tip {
  margin: 0 0 1rem;
  font-size: var(--t-sub);
}

.login-brand {
  text-align: center;
  margin: 0 0 2.25rem;
}

.login-mark {
  display: block;
  width: 112px;
  height: 112px;
  margin: 0 auto 0.85rem;
  object-fit: contain;
  border-radius: var(--radius);
  animation: login-rise 0.55s ease-out both;
}

.login-brand .brand {
  margin: 0;
  font-size: 2.7rem; /* 圖形尺寸，不算字階 */
  font-weight: 800;
  letter-spacing: 0.06em;
  animation: login-rise 0.55s ease-out 0.06s both;
}

.login-brand .brand-sub {
  margin: 0.55rem 0 0;
  font-size: var(--t-body);
  font-weight: var(--w-body);
  color: var(--ink-muted);
  letter-spacing: 0.02em;
  animation: login-rise 0.55s ease-out 0.12s both;
}

.login-card {
  animation: login-rise 0.5s ease-out 0.14s both;
}

.login-tip {
  text-align: center;
  margin: 1.15rem 0 0;
}

@keyframes login-rise {
  from {
    opacity: 0;
    transform: translateY(0.45rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .login-mark,
  .login-brand .brand,
  .login-brand .brand-sub,
  .login-card {
    animation: none;
  }
}

.member-list {
  display: flex;
  flex-direction: column;
}

.member-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.65rem 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--bg-accent);
}

.member-row:last-child { border-bottom: none; }

.member-row.is-deleted {
  opacity: 0.55;
}

.member-info {
  flex: 1 1 12rem;
  min-width: 0;
}

.member-name {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.5rem;
}

.member-user {
}

.member-user::before {
  content: "(";
}

.member-user::after {
  content: ")";
}

.member-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.4rem;
}

.member-tag {
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-muted);
}

.member-actions {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
  margin-left: auto;
}

.member-actions form {
  display: inline;
  margin: 0;
}

.member-reset {
  position: relative;
}

.member-reset > summary {
  list-style: none;
  cursor: pointer;
}

.member-reset > summary::-webkit-details-marker { display: none; }

.member-reset-form {
  display: block !important;
  position: absolute;
  right: 0;
  top: calc(100% + 0.35rem);
  z-index: 5;
  min-width: 12rem;
  padding: 0.75rem;
  background: var(--surface);
  border-radius: var(--r-ctl);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

.chip.chip-compact {
  /* 44px：手機觸控最小命中區（危險操作更要點得準） */
  min-height: 44px;
  padding: 0.3rem 0.75rem;
white-space: nowrap;
}

.chip.chip-danger {
  color: var(--danger);
  border-color: #e4b4b4;
  background: var(--danger-soft);
}

.badge {
  display: inline-block;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: var(--t-meta);
  font-weight: 700;
  background: var(--surface-2); /* P2:角色 badge 一律中性,文字已講完角色 */
  color: var(--ink-muted);
}

.badge-liberation { background: var(--cal-liberation-soft); color: var(--cal-liberation-ink); }
.badge-school { background: var(--cal-school-soft); color: var(--cal-school-ink); }
.badge-cram { background: var(--cal-cram-soft); color: var(--cal-cram-ink); }
.badge-review { background: var(--cal-review-soft); color: var(--cal-review-ink); }
/* 狀態 badge：達成＝成功綠；待審＝星星金（非行事曆色） */
.badge-ok { background: var(--ok-soft); color: var(--ok-ink); }
.badge-pending { background: var(--accent-soft); color: var(--accent-ink); }

/* —— 行事曆（議程＋月曆，參考 Google／Apple） —— */
/* 行程色徽刻意避開紅／綠，才不會與股票漲跌、成功／危險訊息混淆 */
:root {
  --cal-school: #3e7cb1;
  --cal-school-soft: #e3edf7;
  --cal-school-ink: #2d5f8a;
  --cal-cram: #7c5cbf;
  --cal-cram-soft: #ece5f7;
  --cal-cram-ink: #5d3f99;
  --cal-review: #d97b29;
  --cal-review-soft: #f9ead9;
  --cal-review-ink: #9c5316;
  --cal-family: #5a6675;
  --cal-family-soft: #e8ebef;
  --cal-family-ink: #3f4a58;
  --cal-liberation: #d35c93;
  --cal-liberation-soft: #f9edf3;
  --cal-liberation-ink: #a93e6f;
}

.cal-actions { margin-bottom: 0.75rem; }

.cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem 0.85rem;
  margin: 0 0 0.85rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.cal-legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.dot {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ink-muted);
}
.dot.school { background: var(--cal-school); }
.dot.cram { background: var(--cal-cram); }
.dot.review { background: var(--cal-review); }
.dot.family { background: var(--cal-family); }
.dot.liberation { background: var(--cal-liberation); }
.dot.more { background: var(--ink-muted); opacity: 0.45; }

.cal-month {
  padding: 0.85rem 0.75rem 1rem;
  margin-bottom: 0.85rem;
}
.cal-month-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.45rem;
  margin-bottom: 0.55rem;
}
.cal-month-title {
  font-weight: var(--w-strong);
  font-size: var(--t-title);
  margin: 0;
  text-align: center;
  flex: 1;
  color: var(--brand-dark);
}
.cal-weekdays,
.cal-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.15rem;
  text-align: center;
}
.cal-weekdays {
  margin-bottom: 0.35rem;
font-weight: var(--w-strong);
  color: var(--ink-muted);
}
.cal-week + .cal-week {
  margin-top: 0.12rem;
}
.cal-section-title {
  margin: 0.35rem 0 0.25rem;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--brand-dark);
}
.cal-week-detail {
  margin-top: 0.25rem;
}
.cal-cell {
  min-height: 3rem;
  padding: 0.2rem 0.1rem 0.3rem;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
}
a.cal-cell-link {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
a.cal-cell-link:active {
  background: rgba(13, 115, 119, 0.1);
}
.cal-cell.focus:not(.today) {
  box-shadow: inset 0 0 0 2px rgba(13, 115, 119, 0.28);
}
.cal-cell.out .cal-daynum { opacity: 0.28; }
.cal-cell.today {
  background: var(--brand-soft);
  box-shadow: inset 0 0 0 1.5px var(--brand);
}
.cal-cell.today .cal-daynum {
  background: var(--brand);
  color: #fff;
  width: 1.55rem;
  height: 1.55rem;
  display: inline-flex; align-items: center; justify-content: center; /* 波8b：原 line-height:1.55rem 是在做垂直置中 */
  border-radius: 50%;
}
.cal-daynum {
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
}
.spend-cal {
  margin-bottom: 0.85rem;
}
.spend-cal-cell {
  min-height: 3.1rem;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 0.15rem;
  padding: 0.25rem 0.1rem 0.35rem;
}
.spend-cal-amt {
  display: block;
font-weight: var(--w-strong);
  color: var(--brand-dark);
  line-height: 1.15;
  text-align: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spend-cal-cell.out .spend-cal-amt { opacity: 0.35; }
.spend-cal-day { margin-top: 0.65rem; }
.spend-cal-modal-body { padding: 0; }
/* 月格：色點改色條（類別可辨、點觸面積更大） */
.cal-dots {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 0.45rem;
  width: 100%;
  padding: 0 3px;
}
.cal-dots .dot {
  width: 100%;
  height: 3px;
  border-radius: 2px;
}
.cal-dots .dot.more {
  opacity: 0.4;
}

.cal-plan-bar { margin-bottom: 0.75rem; }

.cal-day {
  margin-bottom: 1.1rem;
}
.cal-day-head {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 0.35rem 0.15rem 0.45rem;
  background: linear-gradient(180deg, var(--bg) 70%, transparent);
}
.cal-day-numwrap {
  display: flex;
  align-items: center;
  gap: 0.65rem;
}
.cal-day-big {
  font-size: var(--t-display);
  font-weight: var(--w-strong);
  line-height: 1;
  min-width: 2.2rem;
  color: var(--ink);
}
.cal-day.is-today .cal-day-big {
  color: var(--brand-dark);
}
.cal-day-meta {
  display: flex;
  flex-direction: column;
  font-weight: 700;
  gap: 0.05rem;
}
.cal-day-body {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.cal-event {
  display: grid;
  grid-template-columns: 3.4rem 1fr;
  gap: 0.55rem;
  background: var(--surface);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 0.65rem 0.7rem 0.7rem 0.55rem;
  border-left: 4px solid var(--ink-muted);
  position: relative;
}
.cal-event.kind-school { border-left-color: var(--cal-school); }
.cal-event.kind-cram { border-left-color: var(--cal-cram); }
.cal-event.kind-review { border-left-color: var(--cal-review); }
.cal-event.kind-family { border-left-color: var(--cal-family); }
.cal-event.kind-liberation { border-left-color: var(--cal-liberation); }
.cal-event.is-done {
  opacity: 0.72;
}
.cal-event.is-done .cal-event-title {
  text-decoration: line-through;
}

.cal-event-time {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
font-weight: var(--w-strong);
  color: var(--ink-muted);
  padding-top: 0.15rem;
  line-height: var(--lh-tight);
}
.cal-event-time .t-start { color: var(--ink); }
.cal-event-time .t-end { font-weight: var(--w-body); opacity: 0.85; }
.cal-event-time .t-all {  }

.cal-event-title {
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  margin-bottom: 0.2rem;
  line-height: var(--lh-tight);
}
.cal-event-sub {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.55rem;
  font-size: var(--t-sub);
  color: var(--ink-muted);
  font-weight: var(--w-body);
}
.cal-pill {
  display: inline-block;
  padding: 0.08rem 0.45rem;
  border-radius: 999px;
font-weight: var(--w-strong);
  background: var(--bg-accent);
  color: var(--brand-dark);
}
.kind-school .cal-pill { background: var(--cal-school-soft); color: var(--cal-school-ink); }
.kind-cram .cal-pill { background: var(--cal-cram-soft); color: var(--cal-cram-ink); }
.kind-review .cal-pill { background: var(--cal-review-soft); color: var(--cal-review-ink); }
.kind-family .cal-pill { background: var(--cal-family-soft); color: var(--cal-family-ink); }
.kind-liberation .cal-pill { background: var(--cal-liberation-soft); color: var(--cal-liberation-ink); }

.ok-text { color: var(--ok); font-weight: var(--w-strong); }



.tab-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(var(--tab-h) + var(--safe-bottom));
  padding-bottom: var(--safe-bottom);
  /* **不要放回 backdrop-filter**（Tom 2026-08-02）：iOS PWA 下毛玻璃疊在
     position:fixed 上，模糊層跟不上捲動，整條導航列看起來會慢半拍地漂。
     而原本的底色本來就是 94% 白——疊在頁面底色 #f4f8f7 上算出來是
     rgb(254,255,255)，跟純白只差 1/255，模糊只作用在那看不見的 6%。
     代價幾乎是零，飄移的來源卻整個消失。 */
  background: var(--surface);
  border-top: 1px solid var(--brand-border);
  /* Tom 2026-08-30 回報底欄仍會偶發位移——這就是 2026-08-02 那則註解預告的
     「下一步」：強制拉獨立合成層，iOS 捲動/重繪時 fixed 層不再被拖著走。 */
  transform: translateZ(0);
  display: flex;
  max-width: 480px;
  margin: 0 auto;
  z-index: 50;
}

.tab-bar a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  color: var(--ink-muted);
font-weight: 700;
}

.tab-bar a.active {
  color: var(--brand-dark);
}

.tab-icon {
  line-height: 0;
}

.tab-icon svg {
  width: 24px;
  height: 24px;
  display: block;
}

.tab-bar a.active .tab-icon svg {
  stroke-width: 2.4;
}

.empty-hint {
  font-weight: var(--w-body); /* 波8b：說明字自己擁有字重，不看容器臉色 */
  text-align: center;
  padding: 1.5rem 0.5rem;
  color: var(--ink-muted);
}

.link-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.link-row a {
  font-weight: 700;
}

.liberation-banner {
  background: linear-gradient(135deg, var(--cal-liberation), #b83280);
  color: #fff;
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  margin-bottom: 0.85rem;
  font-weight: var(--w-strong);
  box-shadow: var(--shadow);
}

.preview-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.65rem;
  background: #1a3a4a;
  color: #f4f7f8;
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin-bottom: 0.85rem;
  font-weight: 700;
}
.preview-banner-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
}
.preview-switch-label {
  font-size: var(--t-sub);
  opacity: 0.85;
}
.preview-switch-form {
  display: inline;
  margin: 0;
}

.wallet-seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.35rem;
  margin: 0 0 0.85rem;
  padding: 0.25rem;
  background: var(--surface-2);
  border-radius: var(--r-ctl);
}
.wallet-seg-item {
  text-align: center;
  text-decoration: none;
  font-weight: var(--w-strong);
  padding: 0.55rem 0.75rem;
  border-radius: 9px; /* 內圈=外圈 12 − 內距 */
  color: var(--ink-muted);
}
.wallet-seg-item.is-active {
  background: #fff;
  color: var(--brand);
  box-shadow: 0 1px 4px rgba(13, 115, 119, 0.12);
}


.quest-bar-card {
  margin-bottom: 0.85rem;
}

.quest-bar-meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.45rem;
  font-weight: var(--w-strong);
}

.quest-bar-meta .hint {
  font-size: var(--t-sub);
  color: var(--ink-muted);
  font-weight: 700;
}

.progress-track {
  height: 14px;
  background: var(--bg-accent);
  border-radius: 999px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: var(--brand);
  border-radius: 999px;
  transition: width 0.35s ease;
  min-width: 0;
}

.task-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.task-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 52px;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--bg-accent);
  cursor: pointer;
  font-weight: 700;
  user-select: none;
}

.task-item:last-child { border-bottom: none; }

.task-item.done {
  color: var(--ink-muted);
  text-decoration: line-through;
}

/* 整列都是那顆送出鍵（2026-08-01）：原本只有 .task-check 那個 28px 方框
   可點，文字點了沒反應。小孩每天按最多次的地方不該是全站最小的目標。 */
.task-row {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 52px;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.task-row-title { min-width: 0; }

.task-check {
  width: 28px;
  height: 28px;
  border: 3px solid var(--brand);
  border-radius: var(--r-ctl);
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  transition: background 0.2s, transform 0.15s;
  padding: 0;
  font-family: inherit;
  font-weight: var(--w-strong);
  color: #fff;
  cursor: pointer;
}

.task-item.done .task-check {
  background: var(--brand);
  color: #fff;
  transform: scale(1.05);
}

.celebrate {
  background: #d9f0e7;
  color: #1d5c48;
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  font-weight: var(--w-strong);
  margin-bottom: 0.85rem;
  text-align: center;
}

.section-label {
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  color: var(--ink-muted);
  margin: var(--sp-3) 0 var(--sp-1); /* 8b-2:15 處模板 inline margin 拔掉後吃這裡 */
}

.habit-admin-row {
  align-items: center;
  gap: 0.65rem;
}

.habit-admin-info {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1 1 auto;
}

.habit-admin-title {
  font-weight: var(--w-strong);
}

.habit-admin-actions {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.35rem;
  flex: 0 0 auto;
}

.habit-admin-actions .chip:disabled,
.habit-admin-actions .chip[disabled] {
  opacity: 0.35;
  cursor: not-allowed;
}

.habit-admin-block {
  border-bottom: 1px solid var(--brand-border);
  padding-bottom: 0.75rem;
  margin-bottom: 0.65rem;
}

.habit-admin-block:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.habit-assignees-form {
  margin: 0 0 0.15rem;
}

/* 第 57 批（減法，2026-08-09）：`.section-sort-head`／`.block-sort-actions`
   已刪——區塊排序 UI 第 25 批下架、`_partials/block_sort_controls.html`
   （唯一使用者）本批一併刪除，全 repo 零引用。取代它的是 `.pending-head`。 */

.chore-row {
  display: flex;
  justify-content: space-between;
  padding: 0.55rem 0;
  font-weight: 700;
  border-bottom: 1px solid var(--bg-accent);
}

.action-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem;
  margin-top: 0.5rem;
}

.action-grid .btn {
  min-height: 52px;
  font-size: var(--t-body);
  background: var(--brand-soft);
  color: var(--brand-dark);
  width: 100%;
  border-radius: var(--r-ctl);
}

.action-grid .btn:hover {
  filter: brightness(0.96);
}

/* 快速動作色磚（家長今天頁）；用 .btn.tile-* 壓過 .action-grid .btn */
.btn.tile-cash { background: var(--brand); color: #fff; }
.btn.tile-cash:hover { background: var(--brand-dark); filter: none; }
.btn.tile-star { background: var(--accent); color: #5c3d06; }
.btn.tile-penalty { background: var(--cal-family); color: #fff; }
.btn.tile-chore { background: var(--cal-cram); color: #fff; }
.btn.tile-work { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--line); }
.btn.tile-liberation { background: var(--cal-liberation-soft); color: var(--cal-liberation-ink); }

.kid-progress-row {
  margin-bottom: 0.85rem;
}


.habit-mini-list {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0;
  font-size: var(--t-sub);
  color: var(--ink-muted);
}

.habit-mini-list li {
  padding: 0.12rem 0;
}

.habit-mini-list li.is-done {
  color: var(--ink);
  font-weight: var(--w-body);
}

.pending-item {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--bg-accent);
  font-weight: 700;
}

.receipt-pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin-top: 0.25rem;
}

.receipt-pick {
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.receipt-pick input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

.field-label {
  display: block;
  font-weight: 700;
  margin-bottom: 0.25rem;
}

.sparkline-wrap {
  margin: 0.2rem 0 0.45rem;
}

.sparkline {
  display: block;
  max-width: 100%;
  height: auto;
}

.sparkline-candle {
  width: 100%;
  max-width: 22rem;
}

.invest-buy-form .invest-quick-row {
  margin-top: 0;
}

.rate-line {
  color: var(--ink-muted);
  font-weight: 700;
  margin: 0.35rem 0 0.65rem;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0.65rem 0;
}

.chip {
  min-height: 44px;
  padding: 0.45rem 0.85rem;
  border-radius: var(--r-ctl);
  border: 2px solid var(--brand-border);
  background: #fff;
  font-family: inherit;
  font-weight: var(--w-strong);
  line-height: 1.3; /* 波8b：兩行 chip */
  color: var(--brand-dark);
  cursor: pointer;
}

.chip:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.dual-preview {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem;
  margin-top: 0.65rem;
}

.dual-preview .opt {
  background: var(--bg);
  border-radius: var(--r-ctl);
  padding: 0.75rem;
  text-align: center;
  font-weight: 700;
}

.dual-preview .opt strong {
  display: block;
  font-size: var(--t-num);
  color: var(--brand-dark);
  margin-top: 0.25rem;
}


.chore-card {
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--bg-accent);
}

.chore-card:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.chore-card .btn {
  margin-top: 0.35rem;
}

.status-wait {
  margin: 0.35rem 0 0;
  font-weight: var(--w-strong);
  color: var(--accent-ink); /* P2+§4.5:硬編色→token */
  background: var(--accent-soft);
  padding: 0.55rem 0.75rem;
  border-radius: 999px; /* P2:badge 一律 pill */
  font-size: var(--t-sub);
}

.pending-chore {
  padding: 0.5rem 0 0.75rem;
  border-bottom: 1px solid var(--bg-accent);
}

.pending-chore:last-child {
  border-bottom: none;
}

.chip-ok {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}

.action-grid a.btn {
  text-decoration: none;
}

.approve-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem;
}

.stars-label {
  font-weight: 700;
  font-size: var(--t-sub);
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.stars-input {
  width: 3.2rem;
  min-height: 44px;
  padding: 0.35rem;
  border: 2px solid var(--brand-border);
  border-radius: var(--r-ctl);
  font-family: inherit;
  font-weight: var(--w-strong);
  font-size: var(--t-body);
  text-align: center;
}


/* 明細頁主角：現價＋當日漲跌（Tom 2026-08-02——跟市場同語言，損益退第二行） */
.stock-now {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0 0 0.45rem;
}
.stock-now-price {
  font-size: var(--t-display);
  font-weight: var(--w-strong);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  line-height: var(--lh-tight);
}
.stock-now-day { font-size: var(--t-body); font-weight: var(--w-strong); }
.stock-now-when { font-size: var(--t-sub); color: var(--ink-muted); margin-left: auto; }

/* 投資卡漲跌：台股紅漲綠跌 */
.pnl-up {
  color: var(--up);
  font-weight: var(--w-strong);
}

.pnl-down {
  color: var(--down);
  font-weight: var(--w-strong);
}

.candle-detail {
  margin: 0.15rem 0 0;
font-weight: 700;
  min-height: 1.1em;
}

.candle-hit {
  touch-action: manipulation;
}

.pattern-card {
  border-left: 4px solid var(--brand);
}

.pattern-line {
  margin: 0;
  font-weight: 700;
  font-size: var(--t-body);
  color: var(--brand-dark);
}

.pattern-line-gap {
  margin-bottom: 0.45rem;
}

.week-strip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.35rem;
}

.week-cell {
  text-align: center;
  padding: 0.4rem 0.15rem;
  border-radius: var(--r-ctl);
  background: var(--bg-accent);
font-weight: 700;
  color: var(--ink-muted);
}

.week-cell-label {
  display: block;
}

.week-cell-date {
  display: block;
  font-weight: var(--w-body);
  opacity: 0.85;
}

.week-cell-score {
  display: block;
  margin-top: 0.2rem;
  font-size: var(--t-sub);
  color: var(--ink);
}

.week-cell.is-today {
  outline: 2px solid var(--brand);
}

.week-cell.is-full {
  /* 全勤是週軌跡唯一的視覺訊號，用較深的 --brand-border 保住對比 */
  background: var(--brand-border);
  color: var(--brand-dark);
}

.week-cell.is-future {
  opacity: 0.45;
}

/* —— 星星雙池英雄卡（小孩錢包） —— */
.star-hero {
  background: linear-gradient(135deg, var(--brand) 0%, #084c4e 100%);
  color: #fff;
}

.star-hero-note {
  font-size: var(--t-meta);
  color: rgba(255, 255, 255, 0.75);
}

.star-pools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.35rem 0;
}

.star-pool {
  flex: 1;
  text-align: center;
}

.star-pool-divider {
  width: 1px;
  align-self: stretch;
  background: rgba(255, 255, 255, 0.22);
}

.star-pool-label {
  display: block;
  font-size: var(--t-sub);
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 0.2rem;
}

.star-pool-num {
  display: block;
  font-size: var(--t-display);
  font-weight: var(--w-strong);
  color: var(--accent);
  line-height: var(--lh-tight);
}

/* （第 7 批）殘留 lime 規則已移除（第 6 批已改白 .star-pool-saved） */

.star-pool-sub {
  display: block;
color: rgba(255, 255, 255, 0.7);
  margin-top: 0.15rem;
}

.star-hero-tier {
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.65rem;
  background: rgba(255, 255, 255, 0.12);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-ctl) var(--r-ctl) 0;
  font-size: var(--t-sub);
  font-weight: 700;
}

/* —— 現金四池 —— */
.pool-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem;
}

.pool-cell {
  background: var(--bg);
  border-radius: 12px;
  border-left: 4px solid var(--brand);
  padding: 0.6rem 0.7rem;
}
a.pool-cell {
  display: block;
  color: inherit;
  text-decoration: none;
}
a.pool-cell:hover,
a.pool-cell:focus-visible {
  outline: 2px solid var(--brand-border);
  outline-offset: 2px;
}

.pool-label {
  display: block;
  font-size: var(--t-meta);
  color: var(--ink-muted);
  margin-bottom: 0.15rem;
}

.pool-num {
  display: block;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--ink);
}

.pool-sub {
  display: block;
  margin-top: 0.2rem;
font-weight: 700;
  color: var(--ink-muted);
}




/* —— 內嵌建倉列 —— */
.invest-quick-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.35rem;
}

.invest-quick-row .invest-symbol {
  flex: 1;
  min-width: 0;
}

.invest-quick-row .invest-amount {
  width: 6rem;
  flex: none;
}

.invest-quick-row input {
  min-height: 44px;
  padding: 0.5rem 0.65rem;
  border: 2px solid var(--brand-border);
  border-radius: var(--r-ctl);
  font-family: inherit;
  font-size: var(--t-body);
}

.invest-quick-row .chip {
  flex: none;
}

.pool-free { border-left-color: var(--brand); }
.pool-invest { border-left-color: var(--cal-school); }
#invest { scroll-margin-top: 4.5rem; }
.pool-goal { border-left-color: var(--ok); }
.pool-earmark { border-left-color: var(--cal-family); }

/* —— 待審卡（今天頁第一層） —— */
.review-alert {
  background: var(--surface);
}

.num-badge {
  font-weight: var(--w-strong);
  font-size: var(--t-title);
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
}

/* —— 快速動作圖示 —— */
.action-grid .btn {
  flex-direction: column;
  gap: 0.2rem;
  min-height: 72px;
  line-height: 1.3;
}

.btn-icon {
  line-height: 1;
}

.btn-icon svg {
  width: 22px;
  height: 22px;
  display: block;
}

.btn-accent {
  background: var(--accent-soft);
  border: 2px solid var(--accent);
  color: #8a5a10;
}

/* —— Modal（底部抽屜）——
   無 JS 時 [hidden] 生效、按鈕退回一般連結，功能不受影響。 */
.modal[hidden] {
  display: none;
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(15, 23, 42, 0.55);
}

.modal-content {
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 1.1rem 1.1rem calc(1.1rem + var(--safe-bottom));
  box-shadow: 0 -10px 25px rgba(0, 0, 0, 0.12);
  animation: modal-rise 0.22s ease-out;
}

@keyframes modal-rise {
  from { transform: translateY(12%); opacity: 0.6; }
  to { transform: translateY(0); opacity: 1; }
}

.modal-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--brand-dark);
  margin-bottom: 0.85rem;
}

.modal-close {
  border: none;
  background: transparent;
  font-size: 1.6rem; /* 圖形尺寸，不算字階 */
  line-height: 1;
  min-width: 44px;
  min-height: 44px;
  color: var(--ink-muted);
  cursor: pointer;
}

/* —— 卡片標題列（標題＋右側動作） —— */
.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.card-head-title {
  margin: 0;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--ink);
}

/* 獨立卡片標題（無右側動作時用；帶下邊距） */
.card-title {
  margin: 0 0 0.5rem;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--ink);
}

/* —— 通用小工具（收斂樣板 inline style 用） —— */
.m0 { margin: 0; }
.note-sm {
  font-weight: var(--w-body); /* 波8b：說明字自己擁有字重，不看容器臉色 */
  font-size: var(--t-sub);
  color: var(--ink-muted);
}
.chore-row.row-flush { border-bottom: none; }
.divider-top {
  border-top: 1px solid var(--line);
  padding-top: 0.65rem;
  margin-top: 0.85rem;
}

/* chip 也常作連結使用：外觀與 button 版一致 */
a.chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

/* 頁尾／頁首文字連結：撐足 44px 觸控命中（視覺不變、熱區變大） */
.link-row a,
.header-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* 等寬工具列：N 顆按鈕平分一行、同重量（樣式一致才均衡） */
.chip-row-even {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0.45rem;
}
.chip-row-even form { display: contents; }
.chip-row-even .chip {
  width: 100%;
  justify-content: center;
  white-space: nowrap;
}

/* 第 57 批：區塊排序 ↑↓ 的緊湊版樣式已刪（見上面 .chore-row 前的註解）。 */

/* radio 膠囊：選中亮品牌色；disabled 淡出 */
label.chip-radio { cursor: pointer; gap: 0.4rem; }
label.chip-radio:has(input:checked) {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand-dark);
}
label.chip-radio:has(input:disabled) {
  opacity: 0.45;
  cursor: not-allowed;
}

/* —— 設定清單列 —— */
.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.6rem 0;
  border-bottom: 1px solid rgba(13, 115, 119, 0.08);
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
}

/* 設定列右側：現況副標＋箭頭 */
.setting-end {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: none;
}

.setting-sub {
  color: var(--ink-muted);
  font-size: var(--t-sub);
  font-weight: var(--w-body);
  white-space: nowrap;
}

.setting-row:last-child {
  border-bottom: none;
}

.setting-arrow {
  color: var(--ink-muted);
  font-size: 1.2rem; /* 圖形尺寸，不算字階 */
  font-weight: var(--w-body);
}

.help-list {
  margin: 0;
  padding-left: 1.25rem;
  font-weight: var(--w-body);
}
.help-list li + li {
  margin-top: 0.45rem;
}
.help-list strong {
  font-weight: var(--w-strong);
}

/* 月軌跡：沿用 week-cell，縮小成月格 */
.month-head {
  margin-bottom: 0.25rem;
}

.month-head-cell {
  text-align: center;
font-weight: 700;
  color: var(--ink-muted);
}

.month-row {
  margin-bottom: 0.25rem;
  gap: 0.25rem;
}

.month-cell {
  padding: 0.25rem 0.1rem;
  border-radius: var(--r-ctl);
}

.month-cell .week-cell-score {
  margin-top: 0.05rem;
}

.month-cell.out-month {
  background: transparent;
  opacity: 0.3;
}

.assign-alert {
  border-left: 4px solid var(--accent);
}

/* 下拉重新整理提示條 */
.ptr-tip {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1200;
  padding: 0.55rem 1rem;
  padding-top: max(0.55rem, env(safe-area-inset-top));
  text-align: center;
  font-size: var(--t-sub);
  font-weight: 700;
  color: #fff;
  background: rgba(13, 115, 119, 0.92);
  pointer-events: none;
  letter-spacing: 0.02em;
}

.ptr-tip.is-ready {
  background: rgba(13, 115, 119, 1);
}

.ptr-tip.is-busy {
  background: rgba(8, 80, 84, 0.96);
}

.media-lightbox .media-lightbox-content {
  max-width: min(96vw, 520px);
  padding-bottom: 1rem;
}

.media-lightbox-img {
  display: block;
  width: 100%;
  max-height: min(72vh, 640px);
  object-fit: contain;
  margin: 0.35rem auto 0;
  border-radius: var(--r-ctl);
  background: #0a0a0a;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


.remembered-field {
  position: relative;
}

.remembered-suggest {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0.25rem;
  max-height: 11rem;
  overflow-y: auto;
  border-radius: var(--r-ctl);
  background: #fff;
  box-shadow: 0 4px 14px rgba(8, 60, 64, 0.1);
}

.remembered-suggest[hidden] {
  display: none !important;
}

.remembered-suggest-item {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  padding: 0.55rem 0.7rem;
  border-radius: 9px; /* 內圈=外圈 12 − 內距 */
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
}

.remembered-suggest-item:active,
.remembered-suggest-item:hover {
  background: rgba(13, 115, 119, 0.1);
}



.holding-lot {
  padding-left: 0.25rem;
  border-left: 3px solid var(--brand-border);
  margin: 0.35rem 0 0.55rem 0.15rem;
  padding-left: 0.55rem;
}

/* —— Token v2 追加：數字排版與摺疊段 —— */
/* —— Token v2 追加：數字排版與摺疊段 —— */
.num-badge,
.pool-num,
.star-pool-num,
.week-cell-score,
.spend-cal-amt,
.cal-day-big {
  font-variant-numeric: tabular-nums;
}

/* 摺疊段（<details>，無 JS 原生）：標題列帶摘要數字 */
.fold {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 0.85rem;
}

.fold > summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 56px;
  padding: 0.85rem 1.15rem;
  font-weight: var(--w-strong);
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.fold > summary::-webkit-details-marker { display: none; }

.fold-sum {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
  text-align: right;
}

.fold-sum::after {
  content: "▸";
  font-size: var(--t-sub);
  color: var(--ink-soft);
  transition: transform 0.15s ease;
}

.fold[open] > .fold-body { border-top: 1px solid var(--line); }
.fold[open] > summary .fold-sum::after { transform: rotate(90deg); }

.fold-body {
  padding: 0.85rem 1.15rem 1rem;
}

.fold-body > .card-soft,
.fold-body > .spend-cal {
  box-shadow: none;
  background: transparent;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 0.5rem;
}

/* 卡片內的輕量摺疊（家長錢包等） */
.fold-inline {
  margin-top: 0.55rem;
  padding-top: 0.45rem;
  border-top: 1px solid var(--line);
}

.fold-inline > summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 44px;
  font-weight: var(--w-strong);
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.fold-inline > summary::-webkit-details-marker { display: none; }
.fold-inline[open] > summary .fold-sum::after { transform: rotate(90deg); }
.fold-inline > .fold-body { padding: 0.35rem 0 0; }

/* 錢視角總資產卡（沿用 star-hero 底） */
.cash-hero-label {
  display: block;
  font-size: var(--t-sub);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.8);
}

.cash-hero-num {
  display: block;
  font-size: 2.1rem;
  font-weight: var(--w-strong);
  color: #fff;
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
}

.cash-hero-sub {
  display: block;
  margin-top: 0.2rem;
color: rgba(255, 255, 255, 0.72);
}



/* ═══ 品牌暖色層（新芽芽 icon 同調）＋小孩版遊戲化 ═══ */
:root {
  --warm: #fdf0df;        /* 芽芽 icon 的暖米底 */
  --warm-deep: #f7e2c4;
  --warm-ink: #8a5a10;
}

/* —— 登入頁：暖色英雄舞台 —— */
.login-wrap {
  background:
    radial-gradient(120% 90% at 50% 0%, var(--warm) 0%, var(--warm-deep) 55%, var(--bg) 100%);
}

.login-mark {
  filter: drop-shadow(0 10px 22px rgba(184, 127, 31, 0.28));
  animation: mark-float 3.6s ease-in-out infinite;
}

@keyframes mark-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}

@media (prefers-reduced-motion: reduce) {
  .login-mark { animation: none; }
}

.login-brand .brand-sub { color: var(--warm-ink); }

/* —— 空狀態：芽芽陪伴 —— */
.empty-hint::before {
  content: "";
  display: block;
  width: 52px;
  height: 52px;
  margin: 0 auto 0.5rem;
  background: url("../img/icon.png") center/contain no-repeat;
  opacity: 0.9;
}


/* 打卡勾：完成時彈跳＋轉金 */
.task-item.done .task-check {
  background: var(--accent);
  color: #5c3d06;
  border-color: var(--accent);
  animation: check-pop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes check-pop {
  0% { transform: scale(0.6); }
  60% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .task-item.done .task-check { animation: none; }
}

/* 全完成慶祝卡：暖金＋芽芽 */
.celebrate {
  background: linear-gradient(135deg, var(--warm) 0%, #fbe6bf 100%);
  color: var(--warm-ink);
  box-shadow: inset 0 0 0 1.5px rgba(232, 168, 56, 0.45);
  display: flex;
  align-items: center;
  gap: 0.65rem;
}

.celebrate::before {
  content: "";
  flex: 0 0 44px;
  height: 44px;
  background: url("../img/icon.png") center/contain no-repeat;
}

/* 小孩錢包英雄卡：青綠 → 帶一抹暖金光 */
.star-hero {
  background:
    radial-gradient(90% 120% at 100% 100%, rgba(232, 168, 56, 0.35) 0%, rgba(232, 168, 56, 0) 55%),
    linear-gradient(135deg, var(--brand) 0%, #084c4e 100%);
}


/* ═══ 第 3 批：審核綜覽分類跳轉＋家庭規則分組 ═══ */
.jump-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0 0 0.85rem;
}



/* 家庭規則：長表單分組（分隔線＋跳轉錨點） */
.rule-sec {
  border-top: 1px solid var(--line);
  padding-top: 1.1rem;
  margin-top: 1.35rem;
  scroll-margin-top: 0.75rem;
}

.rule-sec:first-of-type {
  border-top: none;
  padding-top: 0;
  margin-top: 0;
}


/* ═══ 第 4 批：紀錄與設定全區 ═══ */
/* 每孩摘要：文字列 → 數據 pills */
.stat-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0 0 0.7rem;
}

.stat-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.28rem;
  background: var(--bg);
  border-radius: 999px;
  padding: 0.28rem 0.7rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}

.stat-pill strong {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.stat-pill.warn { background: var(--danger-soft); color: var(--danger-ink); }
.stat-pill.warn strong { color: var(--danger-ink); }
.stat-pill.hint { background: var(--accent-soft); color: var(--accent-ink); }

/* 週格升級：全勤格上色、今天描邊 */
.week-strip { gap: 0.3rem; }

.week-cell {
  border-radius: var(--r-ctl);
  background: var(--bg);
  padding: 0.42rem 0 0.4rem;
}

.week-cell.is-full { background: var(--brand-soft); }
.week-cell.is-full .week-cell-score { color: var(--brand-dark); }
.week-cell.is-today { box-shadow: inset 0 0 0 1.5px var(--brand); }
.week-cell.is-future { opacity: 0.45; }

/* 設定清單：入口圖示 */
.setting-row { gap: 0.65rem; }

.setting-ico {
  flex: 0 0 34px;
  height: 34px;
  border-radius: var(--r-ctl);
  background: var(--brand-soft);
  color: var(--brand-dark);
  display: flex;
  align-items: center;
  justify-content: center;
}

.setting-ico svg { width: 18px; height: 18px; }

.setting-name { flex: 1; min-width: 0; }

/* 成員列：字首頭像 */
.member-avatar {
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-weight: var(--w-strong);
  font-size: var(--t-body);
  display: flex;
  align-items: center;
  justify-content: center;
}

.member-row .member-avatar { align-self: center; }
.member-row.is-deleted .member-avatar { background: var(--cal-family-soft); color: var(--cal-family-ink); }

/* 家庭規則：儲存鈕 sticky（長表單不用捲到底才存） */
/* 第 74 批（Tom 2026-09-05 截圖：儲存鈕卡在兩張小孩卡中間「亂動」）：
   77d 把捲動搬進 .app-shell 之後，sticky-bottom 的參考框變成表單本身，
   位置就跟著內容跑。改 fixed 釘視窗——文件不捲了，fixed 跟底欄一樣穩。
   寬度對齊 .app-shell 的 480px 內容欄；表單底部留 5rem 讓最後一排輸入框不被蓋。 */
.rules-save {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  width: min(480px - 2rem, calc(100% - 2rem));
  bottom: calc(var(--tab-h) + var(--safe-bottom) + 0.9rem);
  z-index: 5;
  box-shadow: 0 8px 20px rgba(13, 52, 49, 0.28);
}
.rules-form { padding-bottom: 5rem; }
/* 同批：設定頁字太小（Tom）。這頁是全站最密的表單，說明／單位／欄名全站用
   --t-sub（14.45px）在別頁夠，在這頁對著一排排數字看就吃力——只在這頁升到 --t-body。 */
.rules-form .rule-card-sub,
.rules-form .rule-row-unit,
.rules-form .rule-preview,
.rules-form .rule-off-note,
.rules-form .per-kid label,
.rules-form .note-sm,
.rules-form .muted { font-size: var(--t-body); }


/* —— 第 4 批（下層頁） —— */
/* 勾選 chip：每日任務「適用小孩」 */
.check-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--bg);
  border-radius: 999px;
  padding: 0.45rem 0.85rem;
  font-weight: 700;
  font-size: var(--t-sub);
  cursor: pointer;
  margin: 0.15rem 0.4rem 0.15rem 0;
}

.check-chip input { accent-color: var(--brand); margin: 0; }

.check-chip:has(input:checked) {
  background: var(--brand-soft);
  color: var(--brand-dark);
  box-shadow: inset 0 0 0 1.5px var(--brand-border);
}

/* 表單欄位並排（時間起訖、生效起訖） */
/* （.field-row 已於前段統一定義；此處原重複定義已移除） */

/* 家模式 pattern 卡（trail/kid）：暖色、芽芽同框 */
.pattern-card {
  background: linear-gradient(135deg, var(--warm) 0%, #fbe6bf 100%);
  box-shadow: inset 0 0 0 1.5px rgba(232, 168, 56, 0.35);
}

.pattern-card .pattern-line { color: var(--warm-ink); font-weight: 700; }

/* 月軌跡格：更緊湊（沿用週格上色） */
.month-cell { border-radius: var(--r-ctl); padding: 0.3rem 0 0.28rem; }


/* ═══ 第 5 批：視覺語言定調（規則層，2026-07-24） ═══ */
/* —— 題 1：按鈕四層 ——
   L1 主要動作  .chip-ok / .btn-primary  實心品牌青，一個區塊最多 1 顆
   L2 次要動作  .chip                    白底＋品牌框線（現值不變）
   L3 危險動作  .chip-danger             danger-soft 底＋深紅字（由「紅字外框」改為軟底，
                                          與 L2 形狀區隔、又不搶過 L1）
   L4 低調工具  .chip-ghost（新）        無底無框、灰字：拒絕／取消類——永遠伴隨 L1 出現、
                                          不該與 L1 爭視覺重量
   尺寸修飾（與層級正交）：.chip-compact 緊湊；.chip-row-even 等寬工具列 */
.chip.chip-danger {
  background: var(--danger-soft);
  border-color: var(--danger-soft);
  color: var(--danger-ink);
}

.chip.chip-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--ink-muted);
}

.chip.chip-ghost:hover { background: var(--bg); }

/* —— 題 2：頁尾返回導航 ——
   規格：p.link-row = 頁尾導航元件（頁內月份切換等用 div.link-row，不受影響）。
   置中、髮絲線與內容區隔、每連結膠囊熱區（44px 高沿用稽核修正）、最多 3 顆。 */
p.link-row {
  justify-content: center;
  gap: 0.3rem;
  margin-top: 1.15rem;
  padding-top: 0.55rem;
  border-top: 1px solid var(--line);
}

p.link-row a {
  color: var(--ink-muted);
  font-weight: 700;
  padding: 0.55rem 0.9rem;
  border-radius: 999px;
  text-decoration: none;
}

p.link-row a:hover {
  background: var(--bg);
  color: var(--brand-dark);
}

/* —— 題 3：雙月格統一 ——
   骨架同一套：格＝.cal-cell（min-height 3rem、圓角 10、今天＝brand-soft 底＋
   1.5px 描邊＋實心日號），格內資訊各說各的話——行事曆用 .cal-dots 色條（類別）、
   花用月曆用 .spend-cal-amt 金額（量）。以下抹平殘差。 */
.spend-cal-cell {
  min-height: 3rem;
  padding: 0.2rem 0.1rem 0.3rem;
}

.spend-cal-amt { color: var(--ink-muted); }

.spend-cal-cell.today .spend-cal-amt { color: var(--brand-dark); }

/* ═══ 第 6 批：真資料驗證輪（2026-07-24 實機截圖 25 張） ═══ */
/* 6-1 流水列金額不再被長標題擠斷行：
   左欄可收縮＋外文長字可斷（TAIWAN SEMICONDUCTOR…），右欄金額整塊不換行 */
.chore-row { gap: 0.6rem; }

.chore-row > span:first-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

.chore-row > span:last-child {
  flex: none;
  white-space: nowrap;
}

/* 6-2 家長今天「已勾任務」清單：一行一項太長 → 兩欄，頁面縮半屏以上 */
.habit-mini-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 0.9rem;
}

.habit-mini-list li { min-width: 0; overflow-wrap: anywhere; }

/* 6-3 小孩今天：已完成項降視覺重量（次要資訊縮排擠，未完成項維持原尺寸） */
.task-item.done { padding-top: 0.45rem; padding-bottom: 0.45rem; }

.task-item.done .task-check { width: 24px; height: 24px; }

/* 6-4 星星英雄卡：撲滿數字 lime（#a3e635）不在色票 → 改白，
   與口袋的星星金以「金＝可立即用、白＝存著」區隔，同卡不再出現第三色相 */
.star-pool-saved { color: #ffffff; }

/* 6-5 行事曆圖例：圓點 → 色條，跟月格內的表意一致 */
.cal-legend .dot {
  width: 14px;
  height: 4px;
  border-radius: 2px;
}

/* 6-6 表單頁（家庭規則等長表單）：欄位說明貼近欄位、段距回收 */
.field .muted, .field + .muted { margin-top: 0.3rem; margin-bottom: 0; }


/* ═══ 第 7 批：收尾終檢（focus／色彩宣告／空狀態統一） ═══ */
/* 7-1 宣告全站為淺色介面：避免瀏覽器/WebView 強制深色時反轉色票 */
:root { color-scheme: light; }

/* 7-2 鍵盤焦點環：原 outline 用 --brand-border 太淡（對白底對比不足），升為品牌色 */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* 7-3 表單欄位 focus：border 變色之外補一圈柔性 ring，觸控/鍵盤都看得見 */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}

/* 7-4 chip 膠囊內是隱藏 radio/checkbox，鍵盤聚焦時外框要亮 */
.chip-row label.chip:focus-within {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* 7-5 空狀態統一：empty-hint 定稿樣式（模板已把純空狀態的 .muted 換成 .empty-hint） */
.empty-hint {
  text-align: center;
  padding: 1.1rem 0.5rem;
  color: var(--ink-muted);
  font-size: var(--t-sub);
}
.empty-hint a { font-weight: 700; }

/* ═══ 第 8 批：互動回饋（v1.1-1）— 純 CSS 追加，無模板異動 ═══ */
/* 8-1 flash 升級 toast 體感：進場下滑；success 3.5 秒後自動收合（其餘類別留在畫面） */
.flash {
  animation: flash-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.flash-success {
  animation: flash-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) both,
             flash-out 0.45s ease-in 3.5s forwards;
  overflow: hidden;
}
.flash-success::before {
  content: "✓ ";
  font-weight: var(--w-strong);
}
@keyframes flash-in {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: none; }
}
@keyframes flash-out {
  to { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0; margin-bottom: 0; }
}
.flash-success { max-height: 8rem; } /* flash-out 需要起始 max-height */

/* 8-2 按壓回饋：全站按鈕／chip 按下時輕縮，手機上「有按到」的手感 */
.btn, .chip, a.chip, a.btn {
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.1s ease, filter 0.1s ease;
}
.btn:active, .chip:active, a.chip:active, a.btn:active {
  transform: scale(0.96);
  filter: brightness(0.96);
}

/* 8-3 減少動態偏好：全部回饋動效停用 */
@media (prefers-reduced-motion: reduce) {
  .flash, .flash-success { animation: none; }
  .btn:active, .chip:active, a.chip:active, a.btn:active { transform: none; }
}

/* ═══ 第 9 批：等待回饋（v1.1-2）— 搭配 static/js/loading.js ═══ */
/* 9-1 頂部進度條：html.nav-busy 時顯示（由 loading.js 掛class） */
html.nav-busy::before {
  content: "";
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  z-index: 9999;
  background: linear-gradient(90deg, var(--brand), var(--accent), var(--brand));
  background-size: 200% 100%;
  animation: navbar-slide 1s linear infinite;
}
@keyframes navbar-slide { to { background-position: -200% 0; } }

/* 9-2 送出鈕等待態：轉圈＋降透明＋鎖點擊（防重複 POST） */
.btn-busy {
  pointer-events: none;
  opacity: 0.75;
}
.btn-busy::after {
  content: "";
  width: 1em; height: 1em;
  flex: none;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  margin-left: 0.35rem;
  animation: btn-spin 0.7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  html.nav-busy::before { animation: none; background: var(--brand); }
  .btn-busy::after { animation-duration: 1.6s; }
}

/* ═══ 第 10 批：小孩錢包縱向導航（v1.2-1） ═══ */
/* 10-1 錢｜星星分段條 sticky：捲到哪都能一鍵切視角 */
.wallet-seg {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
  margin-top: -0.35rem;
}
/* 10-2 頁內跳段 chips（錢視角專用，橫向可捲） */
.wallet-jump {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin: 0 0 0.85rem;
  padding-bottom: 2px;
}
.wallet-jump::-webkit-scrollbar { display: none; }
.wallet-jump a {
  flex: none;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.35rem 0.8rem;
  text-decoration: none;
}
.wallet-jump a:active { background: var(--brand-soft); color: var(--brand-dark); }
/* 10-3 跳段落點不被 sticky 分段條蓋住 */
.wallet-block, .card-soft[id] { scroll-margin-top: 3.6rem; }

/* ═══ 10-B：用錢流向視覺化（cash/flow） ═══ */
/* 進來/花掉雙條：寬度用模板現有變數以 calc 換算，無新後端欄位 */
.flow-bars {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0.5rem 0 0.85rem;
}
.flow-bar {
  height: 12px;
  border-radius: 999px;
  min-width: 12px;
  max-width: 100%;
}
.flow-bar-in { background: linear-gradient(90deg, var(--brand), var(--brand-dark)); }
.flow-bar-out { background: var(--warm-deep); box-shadow: inset 0 0 0 1px rgba(138, 90, 16, 0.18); }
.flow-bar-label {
  display: flex;
  justify-content: space-between;
font-weight: 700;
  color: var(--ink-muted);
}


/* ═══ 10-C（Code 端）：PWA 打磨（2026-07-25） ═══ */
/* iPhone 橫向：底部 Tab 讓出左右瀏海 safe-area */
.tab-bar {
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
}

/* ═══ Code 端 bug 批：需求彙整 🔴 修正（2026-07-25；原誤標「第 11 批」與 design 第 11 批撞名） ═══ */
/* ④ 送出鈕「請稍候」轉圈被壓成直線：偽元素在非 flex 按鈕裡是 inline、
   寬高失效——補 inline-block（flex 按鈕不受影響，flex item 行為不變） */
.btn-busy::after {
  display: inline-block;
  vertical-align: -0.15em;
  margin-left: 0.5rem;
}

/* ② 內容不足一屏時底部 Tab 跑位：100vh 在 iOS 是「大視口」高，短頁被撐出
   假捲動、URL 列收合過程 fixed 元素跟著跳；改 100dvh 貼齊即時可視高度
   （不支援 dvh 的舊瀏覽器忽略此行、沿用上方 100vh）。
   ── 第 73 批 b（Tom 2026-08-30 實測 PWA 捲動時底欄仍飄）：**結構翻新——
   文件不捲，.app-shell 當唯一捲動容器**。77b 的 translateZ 治不了 WKWebView
   「文件捲動 × fixed」的合成延遲；文件一旦不捲，fixed 底欄就沒有可以慢半拍的
   對象。牽連兩處已同批處理：①下拉刷新 JS 的頁頂判斷改讀 .app-shell.scrollTop
   （base.html）；②站內 sticky（.wallet-seg／.cal-day-head／.rules-save）改為
   相對這個捲動容器，行為不變。舊瀏覽器不吃 dvh → 整段失效、退回文件捲動，
   是刻意的優雅降級。⚠️ .app-shell 永遠不可加 transform/filter——那會把
   fixed 底欄改成相對它定位，整個修法就反過來壞掉。 */
body { min-height: 100dvh; height: 100dvh; overflow: hidden; }
.app-shell {
  min-height: 100dvh;
  height: 100dvh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: none; /* 回彈現在發生在這個容器上（77b 那條管文件層） */
}
.login-wrap { min-height: 100dvh; }

/* ② 續（Tom 2026-08-30，底欄偶發位移）：iOS 頂/底過捲的橡皮筋回彈會把
   fixed 底欄一起拖出畫面再彈回來。PWA 裡沒有下拉刷新、也沒有網址列，
   回彈只剩「把底欄拉走」這一個效果——關掉（iOS 16+ 支援，舊機忽略無害）。 */
html, body { overscroll-behavior-y: none; }

/* ② 同因（錢包頁標題被狀態列蓋住）：sticky 分段條貼 top:0，
   PWA 全螢幕（viewport-fit=cover）會鑽進狀態列底下 */
.wallet-seg { top: env(safe-area-inset-top, 0px); }

/* ═══ 需求彙整第 1 波（Code 端）：⑭ 家況摘要列（2026-07-25） ═══ */
.fam-sum-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  color: var(--ink);
  text-decoration: none;
}
.fam-sum-n { color: var(--danger); }
.fam-sum-kids {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.fam-sum-kid {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--t-sub);
}
.fam-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand-dark);
  display: grid;
  place-items: center;
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  flex: none;
}
.fam-sum-name { font-weight: var(--w-strong); }
.fam-sum-ok { color: var(--brand-dark); font-weight: 700; }
.fam-sum-todo { color: var(--ink-muted); }
.fam-sum-meal {
  display: block;
  font-size: var(--t-sub);
  color: var(--ink-muted);
  text-decoration: none;   /* 2026-08-02 起是連到帳本的連結 */
}
.fam-sum .divider-top { padding-top: 0.5rem; }
/* ═══ 第 11 批：換上網時間改版 ⑤⑥＋派工待領取 ⑧（基準 redesign-19 → 20） ═══ */

/* —— 11-1 時間小罐（常駐於換算器頂上） —— */
.time-jar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.5rem;
  background: var(--warm);
  border: 1px solid var(--warm-deep);
  border-radius: var(--r-ctl);
  padding: 0.5rem 0.75rem;
  margin: 0.5rem 0 0.85rem;
}

/* —— 11-2 15 分鐘加減器 —— */
/* 加減器（.stepper*）已於 2026-08-01 移除：那是 type="button" ＋ hidden input，
   JS 沒跑就完全點不動。改成原生 radio 的 .minute-pick，見 points/kid.html。 */
.minute-pick { margin: 0.35rem 0 0.9rem; }
.minute-pick .chip { flex: 1 1 auto; justify-content: center; min-height: 48px; }

/* —— 11-3 兩池價格卡（並排、點選即選池；不預設推薦） —— */
.pool-pick {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  margin-bottom: 0.85rem;
}
.pool-card {
  text-align: left;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  padding: 0.7rem 0.75rem;
  cursor: pointer;
  font: inherit;
}
.pool-card:has(input:checked) {
  border-color: var(--brand);
  background: var(--brand-soft);
}
.pool-card-pool {
  display: block;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.pool-card-stars {
  display: block;
  font-size: var(--t-num);
  font-weight: var(--w-strong);
  color: var(--ink);
  margin: 0.15rem 0;
}
.pool-card-note {
  display: block;
  color: var(--ink-muted);
}
.pool-card:has(input:disabled) { opacity: 0.45; pointer-events: none; }

/* —— 11-4 裝置 chips（沿用 chip 底，加選中態容器） —— */
.device-row {
  display: flex;
  gap: 0.45rem;
  flex-wrap: wrap;
  margin-bottom: 0.9rem;
}
.device-row .chip { flex: 1 1 auto; justify-content: center; min-height: 44px; }
.device-row .chip:has(input:checked) {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand-dark);
  font-weight: var(--w-strong);
}

/* —— 11-5 換整天大獎卡（動用積蓄，視覺與一般換算區隔） —— */
.day-pass {
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  margin-top: 1rem;
  color: #fff;
  background:
    radial-gradient(120% 140% at 100% 0%, rgba(232, 168, 56, 0.5) 0%, rgba(232, 168, 56, 0) 55%),
    linear-gradient(135deg, var(--brand-dark) 0%, #063d3f 100%);
}
.day-pass-title {
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  margin: 0 0 0.15rem;
}
.day-pass-sub {
  font-size: var(--t-sub);
  color: rgba(255, 255, 255, 0.8);
  margin: 0 0 0.65rem;
}
.day-pass-btn {
  width: 100%;
  min-height: 52px;
  border: none;
  border-radius: var(--r-ctl);
  background: var(--accent);
  color: var(--accent-ink);
  font: inherit;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  cursor: pointer;
}
.day-pass-btn:disabled { opacity: 0.5; pointer-events: none; }
.day-pass-meta {
  margin: 0.5rem 0 0;
  font-size: var(--t-meta);
  text-align: center;
  color: rgba(255, 255, 255, 0.7);
}

/* —— 11-6 待領取卡 ⑧（小孩今日頁最頂） —— */
.claim-card {
  position: relative;
  border-radius: var(--radius);
  padding: 1rem;
  margin-bottom: 0.9rem;
  color: #fff;
  background:
    radial-gradient(90% 120% at 100% 100%, rgba(232, 168, 56, 0.4) 0%, rgba(232, 168, 56, 0) 55%),
    linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
}
.claim-card::after {
  content: "";
  position: absolute;
  top: 0.8rem;
  right: 0.9rem;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
}
.claim-kicker {
  font-size: var(--t-sub);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  margin: 0;
}
.claim-title {
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  margin: 0.2rem 0 0.75rem;
}
.claim-choices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}
.claim-btn {
  min-height: 58px;
  border-radius: var(--r-ctl);
  font: inherit;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  cursor: pointer;
  border: none;
  background: #fff;
  color: var(--brand-dark);
}
.claim-btn.claim-btn-star {
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.6);
  color: #fff;
}
.claim-note {
  margin: 0.6rem 0 0;
  font-size: var(--t-meta);
  text-align: center;
  color: rgba(255, 255, 255, 0.75);
}

/* Code 端補（第 11 批落地）：claim 兩鈕各包在獨立 form，讓按鈕直接當 grid item */
.claim-choices form { display: contents; }

/* ═══ 第 12 批：⑭ 家況摘要列視覺微調（基準 redesign-20 現況，3 條） ═══ */

/* 12-1（已刪 2026-07-25）：nth 交錯配色由 ① 個人主色 .avatar-c-* 取代 */

/* 12-2 「等你處理」是本卡唯一可點，補按壓態＋右緣視覺餘裕，手感像入口而非標題 */
.fam-sum-head {
  border-radius: var(--r-ctl);
  margin: -0.25rem -0.35rem 0;
  padding: 0; /* 8b-2:卡頭吃卡片自己的內距 */
}
.fam-sum-head:active { background: var(--surface-2); }

/* 12-3 待補照片是可行動事項，與純資訊的餐費金額拉開一階 */
.fam-sum-meal strong,
.fam-sum-meal .fam-sum-warn {
  color: var(--warm-ink);
  font-weight: 700;
}

/* ═══ Code 端第 2 波：⑨ 持倉兩層化（2026-07-25） ═══ */
/* 第一層總結欄：一眼看整體 */
.invest-sum {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  font-weight: var(--w-strong);
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--line);
  margin-bottom: 0.35rem;
}
/* 每檔兩行一組：整列可點進明細 */
.holding-line {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  min-height: 56px;
  padding: 0.5rem 0.2rem;
  border-bottom: 1px solid var(--bg-accent);
  color: var(--ink);
  text-decoration: none;
  border-radius: var(--r-ctl);
}
.holding-line:active { background: var(--surface-2); }
.holding-line-main { display: flex; flex-direction: column; gap: 0.1rem; }
.holding-line-sub { font-size: var(--t-sub); color: var(--ink-muted); }
.holding-line-pct {
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  white-space: nowrap;
}

/* ═══ Code 端第 2 波：① 全員自訂頭像＋個人主色（2026-07-25） ═══ */
/* 六色個人主色（沿用既有 token，避開紅綠）；行事曆／核准列標記色後續照 design 清單套用 */
.avatar-c-teal   { background: var(--brand-soft);         color: var(--brand-dark); }
.avatar-c-gold   { background: var(--accent-soft);        color: var(--accent-ink); }
.avatar-c-blue   { background: var(--cal-school-soft);    color: var(--cal-school-ink); }
.avatar-c-purple { background: var(--cal-cram-soft);      color: var(--cal-cram-ink); }
.avatar-c-orange { background: var(--cal-review-soft);    color: var(--cal-review-ink); }
.avatar-c-pink   { background: var(--cal-liberation-soft); color: var(--cal-liberation-ink); }

/* 頭像照片：圓形裁切（object-fit 置中） */
.fam-avatar,
.member-avatar {
  overflow: hidden;
}
.fam-avatar img,
.member-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

/* 主色選擇 chips：底色即所選色 */
.chip.chip-radio.avatar-pick { border-width: 2px; }
.chip.chip-radio.avatar-pick:has(input:checked) {
  border-color: currentColor;
  font-weight: var(--w-strong);
}
/* 勾選時保住各自主色（蓋過 label.chip-radio:has(checked) 的品牌色底） */
label.chip-radio.avatar-pick.avatar-c-teal:has(input:checked)   { background: var(--brand-soft);          border-color: var(--brand-dark);      color: var(--brand-dark); }
label.chip-radio.avatar-pick.avatar-c-gold:has(input:checked)   { background: var(--accent-soft);         border-color: var(--accent-ink);      color: var(--accent-ink); }
label.chip-radio.avatar-pick.avatar-c-blue:has(input:checked)   { background: var(--cal-school-soft);     border-color: var(--cal-school-ink);  color: var(--cal-school-ink); }
label.chip-radio.avatar-pick.avatar-c-purple:has(input:checked) { background: var(--cal-cram-soft);       border-color: var(--cal-cram-ink);    color: var(--cal-cram-ink); }
label.chip-radio.avatar-pick.avatar-c-orange:has(input:checked) { background: var(--cal-review-soft);     border-color: var(--cal-review-ink);  color: var(--cal-review-ink); }
label.chip-radio.avatar-pick.avatar-c-pink:has(input:checked)   { background: var(--cal-liberation-soft); border-color: var(--cal-liberation-ink); color: var(--cal-liberation-ink); }

/* ═══ Code 端第 2 波：⑫ 等爸媽中三段進度（2026-07-25） ═══ */
.wait-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  min-height: 44px;
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--bg-accent);
  font-size: var(--t-sub);
}
.wait-row:last-of-type { border-bottom: none; }
.wait-label { flex: 1 1 auto; min-width: 0; }
.wait-steps { display: flex; align-items: center; gap: 0.2rem; flex: none; }
.wait-step {
font-weight: 700;
  color: var(--ink-muted);
  padding: 0.1rem 0.35rem;
  border-radius: 999px;
  background: var(--bg-accent);
}
.wait-step.is-on { background: var(--brand-soft); color: var(--brand-dark); }
.wait-bar { width: 12px; height: 2px; background: var(--line); border-radius: 1px; }
.wait-bar.is-on { background: var(--brand); }

/* ═══ 第 13 批：登入頁品牌升級（新版 3D 芽芽圖示，純 CSS，基準 redesign-22） ═══ */

/* 13-1 新圖自帶奶油底圓角磚＋立體陰影——拿掉 CSS 端的重複圓角與硬陰影，
   放大當舞台主角（112 → 136px） */
.login-mark {
  width: 136px;
  height: 136px;
  border-radius: 0;
  filter: drop-shadow(0 16px 30px rgba(184, 127, 31, 0.30));
}

/* 13-2 主角後面加一圈柔光暈（暖金 → 透明），圖示從背景「浮」出來 */
.login-brand { position: relative; }
.login-brand::before {
  content: "";
  position: absolute;
  top: -28px;
  left: 50%;
  transform: translateX(-50%);
  width: 240px;
  height: 240px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(232, 168, 56, 0.30) 0%, rgba(232, 168, 56, 0) 68%);
  pointer-events: none;
}
.login-brand > * { position: relative; }

/* 13-3 浮動改「呼吸」：上下 4px＋微傾 1deg，比單純上下更有生命感 */
@keyframes mark-breathe {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-5px) rotate(1deg); }
}
.login-mark { animation: mark-breathe 4.2s ease-in-out infinite; }

/* 13-4 副標與登入卡之間的舞台收尾：brand 字色壓深一階，襯暖底 */
.login-brand .brand { color: var(--brand-dark); }

@media (prefers-reduced-motion: reduce) {
  .login-mark { animation: none; }
}

/* ═══ 第 14 批：① 個人主色全站套用（基準 redesign-23 現況） ═══ */

/* 14-1 通用小頭圈（26px，家況摘要列同規格）——套用清單各處共用 */
.avatar-sm {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: inline-grid;
  place-items: center;
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  flex: none;
  vertical-align: -0.45em;
  overflow: hidden;
}
.avatar-sm img { width: 100%; height: 100%; object-fit: cover; }

/* 14-2 名字色帶（行內元素難放頭圈時的輕量替代：左緣 3px 主色條） */
.kid-tint {
  border-left: 3px solid transparent;
  padding-left: 0.5rem;
}
.kid-tint.avatar-c-teal   { border-left-color: var(--brand); background: none; }
.kid-tint.avatar-c-gold   { border-left-color: var(--accent); background: none; }
.kid-tint.avatar-c-blue   { border-left-color: var(--cal-school-ink); background: none; }
.kid-tint.avatar-c-purple { border-left-color: var(--cal-cram-ink); background: none; }
.kid-tint.avatar-c-orange { border-left-color: var(--cal-review-ink); background: none; }
.kid-tint.avatar-c-pink   { border-left-color: var(--cal-liberation-ink); background: none; }

/* 14-3 行事曆明細列：小孩名字披主色 pill（行程五色不動——kind 色管「事」，主色管「人」） */
.cal-event-sub .kid-pill {
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  font-size: var(--t-meta);
  font-weight: 700;
}

/* ═══ 第 15 批：⑬ 明天的鉤子（小孩今日頁，今日全完成後顯示；基準 redesign-25） ═══ */

/* 15-1 streak 慶祝卡：today/kid 既有慶祝卡同語言（品牌青漸層＋暖金光） */
.streak-card {
  border-radius: var(--radius);
  padding: 1.05rem 1rem;
  margin-bottom: 0.9rem;
  text-align: center;
  color: #fff;
  background:
    radial-gradient(90% 120% at 100% 0%, rgba(232, 168, 56, 0.4) 0%, rgba(232, 168, 56, 0) 55%),
    linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
}
.streak-flame { font-size: 1.9rem; /* 圖形尺寸，不算字階 */ line-height: 1; display: block; margin-bottom: 0.25rem; }
.streak-title { font-size: var(--t-num); font-weight: var(--w-strong); margin: 0; }
.streak-sub {
  margin: 0.3rem 0 0;
  font-size: var(--t-sub);
  color: rgba(255, 255, 255, 0.85);
}

/* 15-2 芽芽成長卡：等級＝星星累積總量，只升不降 */
.sprout-card {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8rem 0.9rem;
  border-radius: var(--radius);
  background: var(--warm);
  border: 1px solid var(--warm-deep);
  margin-bottom: 0.9rem;
}
.sprout-img { width: 52px; height: 52px; flex: none; }
.sprout-img img { width: 100%; height: 100%; object-fit: contain; }
.sprout-main { flex: 1; min-width: 0; }
.sprout-lv { font-weight: var(--w-strong); font-size: var(--t-body); color: var(--warm-ink); }
.sprout-next {color: var(--accent-ink); font-weight: var(--w-body); }
.sprout-track {
  height: 8px;
  border-radius: 999px;
  background: rgba(138, 90, 16, 0.15);
  margin-top: 0.35rem;
  overflow: hidden;
}
.sprout-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
}

/* 15-3 明天預告列 */
/* 第 57 批（減法，2026-08-09）：`.tomorrow-line`（明天預告列）已刪——
   模板第 49 批就拿掉了，CSS 留著沒有任何 markup 用得到。 */

/* ═══ 第 16 批：⑪ 數字翻譯層（基準 redesign-25） ═══ */

/* 16-1 分鐘比喻行（換上網時間加減器下方） */
.mins-analogy {
  text-align: center;
font-weight: 700;
  color: var(--accent-ink);
  margin: -0.5rem 0 0.9rem;
}

/* 16-2 目標倒數行（存錢目標進度條下方） */
.goal-eta {
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--warm-ink);
  margin: 0.25rem 0 0;
}
.goal-eta.goal-eta-none { color: var(--ink-soft); font-weight: var(--w-body); }

/* ═══ 第 17 批：⑰ 異常浮卡＋⑱ 週報卡（基準 redesign-27） ═══ */

/* 17-1 異常浮卡：暖色提醒（不是警報），家長今日頁 fam-sum 之後 */
.nudge-card {
  background: var(--warm);
  border-radius: var(--radius);
  padding: var(--sp-4);
  margin-bottom: var(--sp-3);
}
.nudge-title {
  margin: 0;
  font-weight: var(--w-strong);
  color: var(--warm-ink);
}
.nudge-sub {
  margin: 0.15rem 0 0;
color: var(--accent-ink);
}
/* 底部可選的小動作列（如「去看看」連結），沿用 a.chip */
.nudge-card .chip { margin-top: 0.5rem; }

/* 17-2 週報卡：家長今日頁週日起顯示一週（或 /trail 常駐本週段） */
.weekly-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem;
  margin-bottom: 0.9rem;
}
.weekly-kicker {
  margin: 0;
font-weight: 700;
  color: var(--ink-soft);
  letter-spacing: 0.03em;
}
.weekly-title {
  margin: 0.15rem 0 0.6rem;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
}
.weekly-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  color: var(--ink-muted);
}
.weekly-list strong { color: var(--ink); }
.weekly-talk {
  margin-top: 0.6rem;
  padding: 0.6rem 0.7rem;
  border-radius: var(--r-ctl);
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-weight: 700;
}

/* ═══ 第 18 批「家人現在」橫排 → 第 49 批下架模板 → 第 57 批刪 CSS ═══
   `.family-now`／`.family-now-item`／`.family-now-name`／`.family-now-stat`
   全部移除：第 49 批把那排頭像從 today/kid 拿掉（理由＝把「別人做完幾項」
   放在自己的成就旁邊會變成比較），CSS 從此零 markup 使用。 */

/* Code 端補（讀書計畫卡）：快速排入專用格線——日期＋時間一列、標題與按鈕整行，不爆卡 */
.study-quick {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.45rem;
  margin-top: 0.2rem;
}
.study-quick input {
  min-height: 44px;
  padding: 0.45rem 0.65rem;
  border: 2px solid var(--brand-border);
  border-radius: var(--r-ctl);
  font: inherit;
  min-width: 0;
  box-sizing: border-box;
}
.study-quick .study-quick-title,
.study-quick .btn {
  grid-column: 1 / -1;
}
/* 快速排入欄位小標（Tom：時間欄要有提示，不點不知道是什麼） */
.study-quick label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-muted);
  min-width: 0;
}
.study-quick label input { width: 100%; }

/* ══ 第 20 批：全站頂部返回（redesign-32）═══════════════════════════
   新增規則，未改動任何既有 class。搭配 _partials/back_link.html。 */

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-height: 44px;                 /* 觸擊區下限 */
  padding: 0 0.7rem 0 0.25rem;
  margin: 0 0 0.1rem -0.25rem;      /* 負邊距讓箭頭視覺對齊 page-title 左緣 */
  font-weight: var(--w-strong);
  font-size: var(--t-body);               /* 刻意低於 page-title 的視覺重量 */
  color: var(--brand);
}

.back-link:active {
  color: var(--brand-dark);
}

.back-link-arrow {
  font-size: 1.25rem; /* 圖形尺寸，不算字階 */
  line-height: 1;
  margin-top: -0.08em;
}

/* 長表單專用：捲動時貼頂。只用於 cash/book、schedule/slots、admin/rules。 */
.back-sticky {
  position: sticky;
  /* PWA 全螢幕（viewport-fit=cover）時 top:0 會鑽到狀態列底下，
     跟 .wallet-seg 同一個病（GPT 走查低 3） */
  top: env(safe-area-inset-top, 0px);
  z-index: 5;
  display: flex;
  width: 100%;
  margin: 0 0 0.35rem;
  padding: 0 0.7rem 0 0.25rem;
  /* 這個 partial 目前刻意不輸出（見 _partials/back_link.html），所以這段是備用的。
     **要收回來的話先把毛玻璃拿掉**——理由同 .tab-bar，iOS 上黏頂＋模糊會跟不上捲動。 */
  background: var(--bg-blur);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.back-sticky-page {
  margin-left: auto;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-soft);
}

/* ══ 大頭像卡（Tom 2026-07-26：比照 Google，一個大頭圖點進去就換）══════ */
.avatar-hero-card { text-align: center; }
.avatar-hero-form { margin: 0; }

/* 點整塊都算「換頭像」；input 藏起來但保留可聚焦 */
.avatar-hero {
  position: relative;
  display: inline-block;
  cursor: pointer;
  margin: 0.1rem 0 0.55rem;
}

.avatar-hero-ring {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px currentColor;
  font-size: 2.4rem; /* 圖形尺寸，不算字階 */
  font-weight: var(--w-strong);
}

.avatar-hero-ring img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

.avatar-hero-initial { line-height: 1; }

/* 相機徽章：疊在右下，白底讓它在任何照片上都看得見 */
.avatar-hero-cam {
  position: absolute;
  right: -2px;
  bottom: -2px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--surface);
  color: var(--brand);
  box-shadow: var(--shadow);
}
.avatar-hero-cam svg { width: 19px; height: 19px; }
.avatar-hero:active .avatar-hero-cam { background: var(--brand-soft); }

/* 藏 file input：不能用 display:none（鍵盤要能聚焦到 label） */
.avatar-hero-file {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.avatar-hero-name {
  margin: 0;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
}
.avatar-hero-hint { margin: 0.15rem 0 0; }

.avatar-hero-more { margin-top: 0.75rem; text-align: left; }

.avatar-color-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* ══ 第 21 批：字級地板與收斂（redesign-33）═════════════════════════
   全部是既有 class 的 font-size 覆寫，append 到 app.css 尾端即可生效。
   不新增 class、不改動任何其他屬性、不動任何模板。

   三階制：
     0.85rem (14.4px) 決策資訊——換算率、金額、進度、說明句
     0.80rem (13.6px) 次要資訊——副標、時間、來源
     0.75rem (12.8px) 純標籤——badge、星期列、legend（下限，不再有更小的）
   體檢前有 11 個值（0.62–0.85）塞在 10.5–14.4px 這 4px 區間內。 */

/* ── ① 地板：原本 ≤12.2px、但小孩要拿來做決定的 ───────────────── */

/* 「1 星＝5 分」——換上網時間比兩池划算度的關鍵數字。12.2px → 14.4px */
.star-pool-sub { font-size: var(--t-sub); }

/* 「投入 X · 市值 Y」——投資池盈虧線索。12.2px → 13.6px */
.pool-sub { font-size: var(--t-sub); }

/* 送出／看到／通過三段。給小孩的情緒安撫件。11.6px → 13.6px */
.wait-step { font-size: var(--t-sub); }

/* 第 57 批：`.family-now-stat`／`.family-now-name` 的字級覆寫已刪（本體也刪了）。 */

/* 本週七天格的星期與完成數。12.2px → 13.3px
   （格寬固定，只提 1px；再大會擠） */
.week-cell { font-size: var(--t-meta); }

/* 月軌跡格。11.6／11.2px → 13.3px */
.month-cell { font-size: var(--t-meta); }
.month-cell .week-cell-score { font-size: var(--t-meta); }

/* 花用月曆格內金額——全站最小字，卻是「我今天花多少」的答案。
   10.5px → 12.2px。格子窄，只提到標籤級；再大要先加格高。 */
.spend-cal-amt { font-size: 0.72rem; /* 量過的例外：花用月曆格寬（波8b 不動，見 SPEC §1 註）*/ }

/* ── ② 收斂：0.82 / 0.78 / 0.76 / 0.70 / 0.68 併入三階 ─────────── */

/* → 0.85rem 決策資訊 */
.chip.chip-compact { font-size: var(--t-sub); }
.nudge-sub { font-size: var(--t-sub); }
.mins-analogy { font-size: var(--t-sub); }

/* → 0.8rem 次要資訊 */
.cal-event-time { font-size: var(--t-sub); }
.candle-detail { font-size: var(--t-sub); }
.cash-hero-sub { font-size: var(--t-sub); }
.flow-bar-label { font-size: var(--t-sub); }
.login-tip { font-size: var(--t-sub); }
.sprout-next { font-size: var(--t-sub); }
.tab-bar a { font-size: var(--t-sub); }
.weekly-kicker { font-size: var(--t-sub); }
.pool-card-note { font-size: var(--t-sub); }

/* → 0.75rem 純標籤下限 */
.brand-sub { font-size: var(--t-meta); }
.month-head-cell { font-size: var(--t-meta); }
.cal-weekdays { font-size: var(--t-meta); }
.cal-pill { font-size: var(--t-meta); }
/* .badge 0.75rem 維持不動——純標籤，不含資訊量 */

/* ══ 第 26–33 批（redesign-37）══════════════════════════════════════
   四個分頁全面檢討。全部新增規則或既有 class 的覆寫，append 到 app.css 尾端。
   未刪除、未改寫任何既有規則。 */

/* ── 第 28 批：快速動作六格改 emoji＋淺彩底 ─────────────────────
   emoji 不能改顏色，原本的飽和底色會撞色（⭐ 放金底幾乎看不見）。
   改用各色的 -soft 淡底，讓 emoji 自己當顏色來源。 */

.btn.tile-cash       { background: var(--brand-soft);          color: var(--brand-dark); }
.btn.tile-cash:hover { background: var(--brand-border);        filter: none; }
.btn.tile-star       { background: var(--accent-soft);         color: var(--accent-ink); }
.btn.tile-penalty    { background: var(--cal-family-soft);     color: var(--cal-family-ink); }
.btn.tile-chore      { background: var(--cal-cram-soft);       color: var(--cal-cram-ink); }
.btn.tile-work       { background: var(--surface-2);           color: var(--ink); box-shadow: none; }
.btn.tile-liberation { background: var(--cal-liberation-soft); color: var(--cal-liberation-ink); }

/* emoji 要比線圖大一點才清楚（線圖 1.35rem → emoji 1.6rem） */
.action-grid .btn-icon {
  font-size: 1.6rem; /* 圖形尺寸，不算字階 */
  line-height: 1;
  /* 疊字避免某些系統把 emoji 渲染成細線字 */
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}

/* ── 第 29 批：行事曆行程小方塊（B 案）─────────────────────────
   cal-event 由 grid(3.4rem 1fr) 改成 flex 三段：時間／內容／勾選或刪除。 */

.cal-event {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  grid-template-columns: none;          /* 覆寫原 grid */
  border-radius: 14px;
  padding: 0.6rem 0.5rem 0.6rem 0.65rem;
  border-left-width: 5px;
}

.cal-event-time {
  width: 3.1rem;
  flex: none;
  align-items: flex-end;
  padding-top: 0;
  line-height: var(--lh-tight);
}

/* 開始時間是掃視行程時第一個要讀的，放大並吃 tabular-nums */
.cal-event-time .t-start {
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.cal-event-time .t-end {
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-soft);
  opacity: 1;
  font-variant-numeric: tabular-nums;
}

.cal-event-time .t-all {
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  color: var(--ink-muted);
}

.cal-event-main { flex: 1; min-width: 0; }

.cal-event-title {
  font-size: var(--t-body);
  margin-bottom: 0.15rem;
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.cal-event-sub { gap: 0.25rem 0.45rem; margin-top: 0; }

/* 勾選圈：沿用「今天」頁 task-check 的 28px 方框＋3px 品牌色邊。
   44px 外框保證觸擊區，內圈才是視覺。 */
.cal-event-check {
  width: 44px;
  height: 44px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
}

.cal-event-check > span {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  border: 3px solid var(--brand);
  background: #fff;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  line-height: 1;
}

.cal-event.is-done .cal-event-check > span {
  background: var(--brand);
}

/* 手足的讀書時段：只能看 */
.cal-event-check[disabled] { cursor: default; }
.cal-event-check[disabled] > span {
  border-color: var(--brand-border);
  background: var(--surface-2);
  color: var(--ink-soft);
}

/* 刪除：44px danger ✕，只給沒有勾選圈的行程 */
.cal-event-del {
  min-width: 44px;
  min-height: 44px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--r-ctl);
  background: var(--danger-soft);
  color: var(--danger-ink);
  font: inherit;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  cursor: pointer;
}

/* 讀書計畫進度併成一張卡後，條子細一點 */
.cal-plan-bar .progress-track { height: 10px; }
.cal-plan-bar .quest-bar-meta { margin-bottom: 0.35rem; }

/* ── 第 30 批：小孩錢包 ─────────────────────────────────────── */

/* 純顯示的池格（投資存、存目標待分配）：不是連結，不要 hover／active 假訊號 */
div.pool-cell { cursor: default; }

/* 可點的池格加右上角 ›，跟純顯示格區隔 */
a.pool-cell { position: relative; }
a.pool-cell::after {
  content: "›";
  position: absolute;
  top: 0.35rem;
  right: 0.5rem;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  color: var(--brand);
}

/* 投資存格的漲跌百分比：跟金額同一行、baseline 對齊 */
.pool-num-row {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  flex-wrap: wrap;
}
.pool-num-row .pool-pct { font-size: var(--t-sub); font-weight: var(--w-strong); }

/* 兩池匯率兩行（換時間／換錢或不能換錢） */
.star-pool-sub {  }

/* 持倉列迷你 K 棒 */
.holding-line { min-height: 64px; }
.holding-spark {
  flex: none;
  width: 68px;
  height: 34px;
  display: block;
}
.holding-spark svg { display: block; width: 100%; height: 100%; }
/* 成本均價虛線 */
.holding-spark .spark-avg {
  stroke: var(--ink-soft);
  stroke-width: 1;
  stroke-dasharray: 3 2;
}
/* 建倉未滿 3 天 */
.holding-spark-new {
  flex: none;
  width: 68px;
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-soft);
  text-align: center;
}

/* ── 第 31 批：家長錢包 ─────────────────────────────────────── */

/* 每孩卡的兩格大數字（自由花用／專款） */
.kid-money-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem;
  margin-bottom: 0.65rem;
}
.kid-money-grid .pool-num { font-size: var(--t-num); }

/* 摺疊列（投資明細／待分配／花用月曆）：跟 setting-row 同高，但無圖示 */
.kid-fold-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.55rem 0;
  border-top: 1px solid var(--bg-accent);
  font-weight: 700;
}
.kid-fold-row .fold-sum { font-size: var(--t-sub); }

/* ── 第 32／33 批：紀錄設定 ─────────────────────────────────── */

/* 每孩週卡內的用錢列＋該孩流向連結 */
.kid-cash-more {
  margin: 0.55rem 0 0;
  font-size: var(--t-sub);
  font-weight: 700;
}


/* —— 第 35 批：家長錢包星星視角 ——
   .star-pool-sub 是小孩深綠 hero 卡專用（白字）；家長頁是淺底，需要另一個。
   第 31 批誤用前者，家長端兩行匯率整個看不見。 */
.pool-rate {
  display: block;
  font-size: var(--t-sub);
  margin-top: 0.2rem;
  color: var(--ink-muted);
  font-weight: var(--w-body);
}

/* 兩池規則不同（口袋不能換錢、撲滿可以）→ 顏色就把差別講完 */
.pool-pocket { border-left-color: var(--cal-family); }
.pool-piggy {
  background: var(--accent-soft);
  border-left-color: var(--accent);
}
.pool-piggy .pool-label,
.pool-piggy .pool-num,
.pool-piggy .pool-rate { color: var(--accent-ink); }


/* —— 第 36 批：家庭規則七張主題卡（基準 v36） —— */

.rule-card-title {
  display: block;
  margin: 0;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  color: var(--ink);
}
.rule-card-sub {
  display: block;
  margin: 0.15rem 0 0.75rem;
  font-size: var(--t-sub);
  color: var(--ink-muted);
}

/* 一行一個設定：左標題、右小輸入框、右單位 */
.rule-row {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--bg-accent);
}
.rule-row:last-of-type { border-bottom: none; }
.rule-row-label {
  flex: 1;
  min-width: 0;
  font-size: var(--t-body);
  font-weight: 700;
}
.rule-row-input {
  flex: none;
  width: 74px;
  min-height: 44px;
  text-align: center;
  font-weight: 700;
}
.rule-row-unit {
  flex: none;
  min-width: 28px;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}

/* 即時預覽：淺綠藥丸，比灰字更像「結果」 */
.rule-preview {
  margin: 0.6rem 0 0;
  padding: 0.55rem 0.7rem;
  border-radius: var(--r-ctl);
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-size: var(--t-sub);
  font-weight: 700;
}
.rule-preview:empty { display: none; }

/* 換整天開關 */
.rule-toggle-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
}
.rule-toggle-text { flex: 1; min-width: 0; }
.switch { flex: none; display: inline-flex; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track {
  width: 52px;
  height: 31px;
  border-radius: 999px;
  background: var(--line);
  padding: 3px;
  display: flex;
  align-items: center;
  transition: background 0.18s ease;
}
.switch-track::before {
  content: "";
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(13, 52, 49, 0.2);
  transition: transform 0.18s ease;
}
.switch input:checked + .switch-track { background: var(--brand); }
.switch input:checked + .switch-track::before { transform: translateX(21px); }
.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--brand-border);
  outline-offset: 2px;
}

.rule-dim { opacity: 0.42; }
.rule-off-note {
  margin: 0.5rem 0 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--accent-ink);
}

/* 各小孩：一孩一張小卡、三格並排 */
.per-kid-card {
  padding: 0.7rem;
  border-radius: var(--radius);
  background: var(--bg);
  margin-bottom: 0.55rem;
}
.per-kid-card:last-child { margin-bottom: 0; }
.per-kid-name {
  margin: 0 0 0.5rem;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
}
.per-kid-grid {
  display: grid;
  /* 三級上限上線後每孩 4 欄（任務入星／平日／假日／解放日）：固定 3 欄的話
     第 4 格會自己擠到下一行、單獨佔第 1 欄，改成自動換行不寫死欄數
     （Tom 2026-09-05 三級批） */
  grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
  gap: 0.45rem;
}
.per-kid-grid .field { margin-bottom: 0; }
.per-kid-grid label {
  color: var(--ink-muted);
}
.per-kid-grid input { min-height: 44px; text-align: center; }

/* ══ 第 37 批：待審卡兩級呈現（加分逐筆留首頁，其餘四類收成一行）══════════ */

/* 類別標題列：左小標、右批次鈕。取代名不符實的 .section-sort-head
   （那個名字是區塊排序時代留下的，第 25 批把排序 UI 拿掉後裝的是批次鈕）。
   第 57 批查證：`.section-sort-head` 全 repo 零引用，已刪。 */
.pending-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.9rem 0 0.45rem;
  font-size: var(--t-sub);
  color: var(--ink-muted);
  border-bottom: 0;
}
.pending-head:first-of-type { margin-top: 0.35rem; }

/* 一行式待審：整行可點，右邊 › 沿用 setting-row 的語彙 */
.pending-jump {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 52px;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--bg-accent);
  font-size: var(--t-body);
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
}
.pending-jump:last-of-type { border-bottom: none; }
.pending-jump-text { flex: 1; min-width: 0; }
.pending-jump .setting-arrow { flex: none; }
.pending-jump:active { background: var(--bg); }

/* ══ 第 38 批：家人今日進度卡（螢幕改進度條並排第一）══════════════════ */

.kid-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.8rem;
}
.kid-head-name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  letter-spacing: 0.01em;
}

/* 標籤左、數字右，三個孩子的數字對齊成一直排 */
.stat-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.3rem;
}
.stat-label {
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
  letter-spacing: 0.02em;
}
.stat-val {
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.stat-val strong {
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  color: var(--ink);
}

.stat-sub {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.35rem;
  font-size: var(--t-sub);
  font-weight: 700;
}
.stat-sub-key { color: var(--accent-ink); }
.stat-sub-soft { color: var(--ink-soft); }

/* 螢幕條：比任務條細、金色（--accent＝全站「錢與獎勵」的語彙） */
.progress-track-sm { height: 10px; }
.progress-fill-screen { background: var(--accent); }

/* 覆寫前面只有 margin-bottom 的舊定義：孩子與孩子之間拉開並加分隔線 */
.kid-progress-row {
  padding-bottom: 1rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--bg-accent);
}
.kid-progress-row:last-of-type { border-bottom: none; margin-bottom: 0.35rem; }

/* 清單：✓ 綠、○ 灰，已完成加底線暗示可點（它其實是 button.linkish） */
.habit-mini-list li { min-height: 34px;  }
.habit-mini-list .mini-mark {
  display: inline-block;
  width: 14px;
  text-align: center;
  font-weight: var(--w-strong);
}
.habit-mini-list li.is-done .mini-mark { color: var(--brand); }
.habit-mini-list li:not(.is-done) .mini-mark { color: var(--ink-soft); }
.habit-mini-list .linkish {
  text-decoration: underline;
  text-decoration-color: var(--brand-border);
  text-underline-offset: 3px;
}
/* 0.75rem＝純標籤下限（第 21 批「不再有更小的」）。交付原本指定 0.7rem，
   是為了不把行撐高，但 li 已有 min-height:34px 撐著，不需要破下限。 */
.habit-mini-list .badge-review { font-size: var(--t-meta); padding: 0.1rem 0.5rem; }

.uncheck-hint {
  margin: 0.35rem 0 0;
  font-size: var(--t-sub);
  color: var(--ink-soft);
}

/* 確認入星＝家長每天必按的鈕，升 L1 滿寬（.approve-row 是 flex，按鈕只會撐到
   內容寬，所以另給容器）。駁回維持 L3 chip 靠左，不一起放大。 */
.confirm-row { margin-top: 0.8rem; }
.confirm-row form { margin: 0; }
.confirm-row .btn { width: 100%; }
/* 第 73 批修訂（redesign-76）：確認入星＋打折入星同大小並排（Tom 驗收退回 L4 小字版）。
   <a class="btn"> 要跟 <button> 等高：兩者盒模型不同，靠 grid 拉平＋置中。 */
.confirm-row-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
}
.confirm-row-pair a.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

/* ══ 第 39 批：任務清單勾選前後等高（Tom 回報的 bug）══════════════════ */

/* 已完成的項目外面包 button.linkish（點一下取消勾選），未完成是純文字。
   button 原本自帶 padding:0.45rem 0，於是已勾 38.8px、未勾 34px，
   兩欄 grid 的上下列因此高低不一（同一列會被 grid 拉齊，錯開的是列與列之間）。
   → 高度統一交給 li，button 只負責可點範圍。 */
.habit-mini-list li {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  min-height: 36px;
  padding: 0;
}

/* form 不參與版面，button 直接當 li 的子項。
   注意：模板原本在 form 上寫 inline style="display:inline"，會蓋掉這條，
   於是 align-self:stretch 失效、可點區只有文字那一小塊——那兩處 inline 已拔掉。 */
.habit-mini-list li > form { display: contents; }

.habit-mini-list .linkish {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  align-self: stretch;   /* 撐滿列高 */
  flex: 1;               /* 撐滿列寬。交付只寫 align-self，那只管交叉軸——
                            實測可點區仍只有文字那 48px（格子有 149px）。
                            這是「取消勾選」的復原動作，點錯不痛，target 大一點好按。 */
  padding: 0;
  font-weight: var(--w-body);      /* 與 li.is-done 同級；原本寫死 700，勾選後字會突然變粗 */
  text-align: left;
}

/* ══ 第 40 批：小孩錢包近期進出（基準 v41）══════════════════════════ */

/* .hint 一直只有兩條情境規則（.quest-bar-meta .hint／.stat-pill.hint），
   沒有基礎規則——points/kid 近期進出與 cash/flow 的輔助資訊因此跟主文字
   一樣黑一樣粗，一行看起來像好幾件事並列。全站 16 處都靠這條弱化。
   兩條情境規則的選擇性都比它高，不會被蓋掉。 */
.hint {
  font-size: var(--t-sub);
  font-weight: var(--w-body);
  color: var(--ink-muted);
}

.log-day {
  margin: 0.85rem 0 0.1rem;
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}
.log-day:first-of-type { margin-top: 0.35rem; }

.log-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 52px;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--bg-accent);
}
.log-row:last-of-type { border-bottom: none; }
.log-main { flex: 1; min-width: 0; }
.log-label {
  display: block;
  font-size: var(--t-body);
  font-weight: 700;
}
.log-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.18rem;
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-muted);
}
.log-pool { padding: 0.12rem 0.45rem; border-radius: 999px; }
.log-pool-free { background: var(--brand-soft); color: var(--brand-dark); }
.log-pool-earmark { background: var(--cal-family-soft); color: var(--cal-family-ink); }
.log-by { display: inline-flex; align-items: center; gap: 0.25rem; }
/* 交付原本寫 0.62rem，破了三階下限。18px 圈裡放 0.75rem（12.75px）的單字仍放得下，
   實測沒有溢出（有頭像圖時字級根本用不到）。 */
.log-by .avatar-sm { width: 18px; height: 18px; font-size: var(--t-meta); vertical-align: 0; }
.log-photo {
  color: var(--brand-dark);
  text-decoration: underline;
  text-decoration-color: var(--brand-border);
  text-underline-offset: 3px;
}
.log-missing {
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  background: var(--danger-soft);
  color: var(--danger-ink);
  text-decoration: none;
}

/* 進來品牌綠、花掉深墨——不用紅色，花錢不是錯事，紅色留給真正的警示 */
.log-amt {
  flex: none;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  font-variant-numeric: tabular-nums;
}
.log-in { color: var(--brand); }
.log-out { color: var(--ink); }

.log-more {
  margin: 0.75rem 0 0;
  font-size: var(--t-sub);
  color: var(--ink-soft);
}

/* ══ 第 41 批：記帳依類別提醒拍照（基準 v41）══════════════════════ */

/* 餐費專用：把「為什麼要拍」寫出來，比命令句有用 */
.photo-nudge {
  background: var(--warm);
  border: 1px solid var(--warm-deep);
  border-radius: var(--radius);
  padding: 0.8rem 0.85rem;
  margin-bottom: 0.85rem;
}
.photo-nudge-head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 0.6rem;
}
.photo-nudge-ico {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: var(--r-ctl);
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
}
.photo-nudge-ico svg { width: 19px; height: 19px; }
.photo-nudge-text { flex: 1; min-width: 0; }
.photo-nudge-title {
  display: block;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  color: var(--warm-ink);
}
.photo-nudge-sub {
  display: block;
  margin-top: 0.1rem;
  color: var(--warm-ink);
}
.photo-nudge .receipt-pick { min-height: 48px;  }
.photo-nudge .photo-pick-cam {
  background: var(--accent);
  border-color: var(--accent);
  color: #5c3d06;
}
.photo-nudge .photo-pick-lib {
  background: #fff;
  border-color: var(--warm-deep);
  color: var(--warm-ink);
}

/* 沒拍照時的送出鈕：金色，說出後果但不擋。btn-nudge 是 L1 的變體，不是新層級 */
.btn-nudge {
  background: var(--accent);
  color: #5c3d06;
  width: 100%;
  min-height: 52px;
  font-weight: var(--w-strong);
}
.photo-later {
  margin: 0.5rem 0 0;
  font-size: var(--t-sub);
  color: var(--ink-muted);
  text-align: center;
}

/* 選好照片的回饋（四類共用） */
.photo-picked {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  background: var(--brand-soft);
  border: 1px solid var(--brand-border);
  border-radius: var(--radius);
  padding: 0.75rem 0.8rem;
  margin-bottom: 0.85rem;
}
.photo-picked-ico {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: var(--r-ctl);
  background: var(--brand);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 1.1rem; /* 圖形尺寸，不算字階 */
  font-weight: var(--w-strong);
}
.photo-picked-text { flex: 1; min-width: 0; }
.photo-picked-title {
  display: block;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  color: var(--brand-dark);
}
.photo-picked-name {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--t-sub);
  color: var(--brand-dark);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 自由花用的輕提醒：一句話，不做卡片 */
.photo-hint {
  margin: 0.4rem 0 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--accent-ink);
}

/* ══════════════════════════════════════════════════════════════
   第 42 批 — 小孩錢包「想買的東西」常駐卡（基準 v42 · redesign-44）
   用法：整段 append 到 static/css/app.css 尾端。既有規則不刪不改。
   注意（第 72 批減法 A14 更新）：這裡原本寫「.savings-card / .goal-title /
   .goal-eta 仍被摺疊裡的舊版目標卡使用」——**那個舊版目標卡早就不在了**，
   `.savings-card .goal-title` 已隨本批的死 class 清倉刪除。
   `.goal-title`／`.goal-eta` 還活著（`gcard-*` 那組在用）。
   新卡一律用 gcard-* 前綴這條不變。
   ══════════════════════════════════════════════════════════════ */

/* ── 主目標（最接近達成的那個）────────────────────────────── */
.gcard-title {
  margin: 0 0 0.2rem;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  line-height: var(--lh-tight);
}
.gcard-nums {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0.45rem 0 0.35rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.gcard-nums strong {
  font-size: var(--t-num);
  font-weight: var(--w-strong);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.gcard-pct { font-size: var(--t-sub); font-weight: var(--w-strong); color: var(--brand); }

/* 16px：比任務進度條（14px）粗一級——這是這張卡的主角 */
.gcard-track {
  height: 16px;
  background: var(--bg-accent);
  border-radius: 999px;
  overflow: hidden;
}
.gcard-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--brand), var(--brand-dark));
  transition: width 0.35s ease;
}

/* 「還差 $360」用金色粗體——差額比百分比有感，小孩會自動換算成「再洗三次碗」 */
.gcard-diff {
  margin: 0.45rem 0 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--accent-ink);
}

/* ── 存進去這一行：緊接在主目標下方 ──────────────────────── */
.gcard-alloc {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--bg-accent);
}
.gcard-alloc-text {
  flex: 1;
  min-width: 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.gcard-alloc-text strong { color: var(--ink); }
/* 金＝管錢的動作（與記帳鈕同一套語彙） */
.gcard-alloc .btn-accent-sm {
  flex: none;
  min-height: 48px;
  padding: 0.55rem 1rem;
  border-radius: var(--r-ctl);
  background: var(--accent);
  border: none;
  color: #5c3d06;
  font-family: inherit;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  cursor: pointer;
}

/* ── 等爸媽核准 ───────────────────────────────────────────── */
.gcard-pending {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.75rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--r-ctl);
  background: var(--accent-soft);
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--accent-ink);
}
.gcard-pending-name { flex: 1; min-width: 0; }
.gcard-pending-amt {
  flex: none;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: #fff;
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
}

/* ── 達成：存錢最難的是延遲滿足，達成那刻沒回饋就沒有下一個目標 ── */
.gcard-done {
  border-radius: var(--radius);
  padding: 1.1rem;
  color: #fff;
  background:
    radial-gradient(90% 120% at 100% 0%, rgba(232, 168, 56, 0.45) 0%, rgba(232, 168, 56, 0) 55%),
    linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
}
.gcard-done-ico { display: block; /* 圖形尺寸，不算字階 */ font-size: 1.75rem; line-height: 1; margin-bottom: 0.35rem; }
.gcard-done-title { margin: 0 0 0.2rem; font-size: var(--t-num); font-weight: var(--w-strong); }
.gcard-done-sub {
  margin: 0 0 0.75rem;
  font-size: var(--t-sub);
  color: rgba(255, 255, 255, 0.85);
}
.gcard-done .btn {
  width: 100%;
  background: #fff;
  color: var(--brand-dark);
  font-weight: var(--w-strong);
}
/* 第 54 批：那顆鈕拿掉了（連到今天頁、按了等於沒按），換成一句話。
   規則不刪 `.gcard-done .btn`——結案動線做出來時那裡會再放一顆真的鈕。 */
.gcard-done-cta {
  margin: 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.95);
}

/* 第二個之後的目標也要能存進去——原本每個目標都撥得進去，只讓主目標能存
   是動線退步。金額先夾住 min(要存的錢, 還差多少)，不給按了必失敗的鈕。 */

/* ══════════════════════════════════════════════════════════════
   第 45 批 — 家長錢包兩層分頁（基準 v43 · redesign-46）
   整段 append 到 static/css/app.css 尾端。既有規則不刪不改。
   前綴 pw-*（parent wallet）。
   沿用既有：.wallet-seg / .wallet-seg-item（錢／星星那排，完全不動）
             .cash-hero / .pool-cell / .card-soft / .fold / .fold-sum
   ══════════════════════════════════════════════════════════════ */

/* ── 上層：小孩分頁。帶數字是刻意的——分頁的代價是不能並排比較，
      分頁自己顯示總額，家長不切換也知道誰多誰少 ───────────────── */
.pw-kidtabs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0.45rem;
  margin-bottom: 0.55rem;
}
.pw-kidtab {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 52px;
  padding: 0.5rem 0.7rem;
  border-radius: var(--r-ctl);
  background: var(--surface-2);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.pw-kidtab.is-active {
  background: #fff;
  box-shadow: 0 1px 4px rgba(13, 115, 119, 0.14), inset 0 0 0 2px var(--brand);
}
.pw-kidtab .avatar-sm { flex: none; width: 28px; height: 28px; font-size: var(--t-sub); }
.pw-kidtab-text { min-width: 0; text-align: left; }
.pw-kidtab-name {
  display: block;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  line-height: var(--lh-tight);
  color: var(--ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pw-kidtab.is-active .pw-kidtab-name { color: var(--brand); }
.pw-kidtab-sum {
  display: block;
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.pw-kidtab.is-active .pw-kidtab-sum { color: var(--ink-muted); }

/* ── 記帳提示：跟著錢，不跟著待審 ───────────────────────────── */
.pw-alert {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 48px;
}
.pw-alert + .pw-alert { margin-top: 0.55rem; }
.pw-alert-first {
  margin-top: 0.8rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--bg-accent);
}
.pw-alert-text {
  flex: 1;
  min-width: 0;
  font-size: var(--t-sub);
  font-weight: 700;
}
.pw-alert-miss { color: var(--danger-ink); }
.pw-alert-todo { color: var(--accent-ink); }

/* ── 投資：家長只要「投了多少、現在多少」 ───────────────────── */
.pw-inv-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.15rem 0 0.7rem;
  border-bottom: 1px solid var(--bg-accent);
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.pw-inv-total strong {
  font-size: var(--t-title);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.pw-inv-pct { flex: none; font-size: var(--t-body); font-weight: var(--w-strong); }

.pw-hold {
  padding: 0.65rem 0;
  border-bottom: 1px solid #f2f5f4;
}
.pw-hold-head {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.pw-hold-name {
  flex: 1;
  min-width: 0;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pw-hold-mkt {
  flex: none;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  font-variant-numeric: tabular-nums;
}
.pw-hold-pct {
  flex: none;
  min-width: 58px;
  text-align: right;
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
}
.pw-hold-cost {
  display: block;
  margin-top: 0.2rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}

/* ── 選要改哪一檔：一個入口 → 清單 → 表單 ───────────────────── */
.pw-pick-hint {
  margin: 0.55rem 0 0.5rem;
  font-size: var(--t-sub);
  color: var(--ink-muted);
}
.pw-pick {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 52px;
  padding: 0.65rem 0.8rem;
  border-radius: var(--r-ctl);
  background: var(--bg);
  border: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
}
.pw-pick + .pw-pick { margin-top: 0.4rem; }
.pw-pick-text { flex: 1; min-width: 0; }
.pw-pick-name { display: block; font-size: var(--t-body); font-weight: var(--w-strong); }
.pw-pick-meta {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}

/* ── 零狀態：不佔位講兩個 0 ─────────────────────────────────── */
.pw-empty { text-align: center; }
.pw-empty-title { margin: 0 0 0.2rem; font-size: var(--t-title); font-weight: var(--w-strong); }
.pw-empty-sub {
  margin: 0;
  font-size: var(--t-sub);
  color: var(--ink-muted);
}

/* ══════════════════════════════════════════════════════════════
   第 46 批 — 家長錢包修正 ＋ 用錢流向改日期分組
   基準 v44 · redesign-47 · 整段 append 到 static/css/app.css 尾端
   既有規則不刪不改。
   注意：日期分組的列樣式沿用第 40 批的 .log-day / .log-row / .log-in /
   .log-out（小孩「近期進出」已在用），這裡只補「池的左側色條」與
   本頁專用的少數幾條。兩頁的一筆帳因此長得一樣。
   ══════════════════════════════════════════════════════════════ */

/* ── 用錢流向：一筆帳的左側色條 ─────────────────────────────
   日期放最前面之後，仍要一眼看出支出類別不同。
   顏色刻意沿用錢包四格的 border-left-color（pool-free / pool-earmark /
   pool-goal），家長不必再學一套對應。 #}                        */
.flow-row {
  border-left: 4px solid var(--line);
  padding-left: 0.65rem;
  border-radius: 0 var(--r-ctl) var(--r-ctl) 0;
}
.flow-row.flow-free {
  border-left-color: var(--brand);
  background: rgba(13, 115, 119, 0.035);
}
.flow-row.flow-earmark {
  border-left-color: var(--cal-family);
  background: rgba(90, 102, 117, 0.05);
}
.flow-row.flow-goal {
  border-left-color: var(--ok);
  background: rgba(45, 138, 110, 0.05);
}
.flow-row.flow-invest {
  border-left-color: var(--cal-school);
  background: rgba(62, 124, 177, 0.05);
}
.flow-row .log-amt { padding-right: 0.65rem; }

/* 池名用文字放第二行（色條負責掃視、文字負責確認），
   顏色與左側色條同一組 */
.flow-pool { font-weight: 700; }
.flow-free .flow-pool { color: var(--brand-dark); }
.flow-earmark .flow-pool { color: var(--cal-family-ink); }
.flow-goal .flow-pool { color: #1f6b54; }
.flow-invest .flow-pool { color: var(--cal-school-ink); }

/* 日期標題右邊的當天小計——依池分組給不了的資訊，
   也是家長最想知道的「哪一天花爆了」 */
.log-day-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
.log-day-sum {
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* 三個池餘額收成一排 chip：改成日期分組後，
   原本寫在每個池小標裡的餘額不能消失 */
.flow-bal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.75rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--bg-accent);
}
.flow-bal-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  font-size: var(--t-sub);
  font-weight: 700;
}
.flow-bal-free { background: var(--brand-soft); color: var(--brand-dark); }
.flow-bal-earmark { background: var(--cal-family-soft); color: var(--cal-family-ink); }
.flow-bal-goal { background: #e3f2ec; color: #1f6b54; }

/* ── 家長錢包：「用錢流向」單獨成卡時不該有分隔線 ───────────
   kid-fold-row 的用途是「卡片內的分隔列」，自帶 border-top；
   單獨當一張卡時那條線變成卡片內部一條浮空橫線。 */
.pw-linkcard {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 56px;
  padding: 0.85rem 1.15rem;
  font-weight: var(--w-strong);
  text-decoration: none;
  color: inherit;
}

/* ── 持倉清單：補展開指示 ───────────────────────────────────
   旁邊三處摺疊都有 .fold-sum::after 的「▸」，只有這裡沒有，
   家長會以為那是唯讀資訊。 */
.pw-pick::after {
  content: "▸";
  flex: none;
  font-size: var(--t-sub);
  color: var(--ink-soft);
  transition: transform 0.15s ease;
}
.pw-pick-fold[open] > .pw-pick::after { transform: rotate(90deg); }

/* ══ 沒錢了（Tom 2026-07-27：「沒了就說沒錢」）════════════════════════
   餐費不另設單餐上限——餘額本身就是上限。原本餘額 0 只是把 15 個欄位變灰，
   畫面上一堆點不動的東西卻沒說為什麼。 */
.nomoney { text-align: center; }
.nomoney-ico { display: block; /* 圖形尺寸，不算字階 */ font-size: 2rem; line-height: 1; margin-bottom: 0.45rem; }
.nomoney-title {
  margin: 0 0 0.3rem;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
}
.nomoney-sub {
  margin: 0;
  font-size: var(--t-sub);
  color: var(--ink-muted);
}


/* ══════════════════════════════════════════════════════════════
   第 47 批 — 消費類別 ／ 家庭花費 ／ 收藏頁
   基準 v44 · redesign-49 · 整段 append 到 static/css/app.css 尾端
   既有規則不刪不改。前綴：cat-*（類別）／hh-*（household）／fav-*（收藏）
   沿用既有：.card-soft .card-title .chip .chip-radio .chip-row .chip-danger
             .setting-row .stat-pill .empty-hint .note-sm .chore-row
             .wallet-seg .wallet-seg-item .star-hero .cash-hero-*
   ══════════════════════════════════════════════════════════════ */

/* ── A. 消費類別 ─────────────────────────────────────────────── */

/* 類別 picker：3–15 顆都要好看。chip-row 已經是 flex-wrap，
   這裡只把行距收緊一點，因為記帳頁上面還有金額與池的選擇。 */
.cat-pick { row-gap: 0.4rem; }

/* 明細列上的類別小標（花用月曆／用錢流向／家庭花費共用）。
   刻意做成「弱一階」的中性灰字，不是彩色 chip——一列裡已經有
   池色條與金額兩個強元素，類別只需要能讀到。 */
.cat-tag {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.45rem;
  border-radius: var(--r-ctl);
  background: var(--surface-2);
  color: var(--ink-muted);
  font-size: var(--t-sub);
  font-weight: 700;
  white-space: nowrap;
}
/* 舊帳沒有類別：不回填，就老實顯示，但比有類別的更淡 */
.cat-tag.cat-none {
  background: transparent;
  color: var(--ink-soft);
  padding-left: 0;
  padding-right: 0;
  font-weight: 700;
}

/* ── A-3. 本月依類別（/cash/flow 與 /household 共用）───────────
   不用圓餅圖：手機上小、要新 JS、又要一組分類色（紅綠已被漲跌／
   成功危險佔用）。水平長條只靠「長度」排序，單一品牌色即可。 */
.catbar-list { display: flex; flex-direction: column; gap: 0.55rem; }
.catbar-row { display: block; }
.catbar-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}
.catbar-name {  font-weight: 700; }
.catbar-amt {
  font-weight: var(--w-strong);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.catbar-pct {
  margin-left: 0.35rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-soft);
}
.catbar-track {
  height: 10px;
  border-radius: 999px;
  background: var(--bg-accent);
  overflow: hidden;
}
.catbar-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--brand);
  min-width: 3px;
}
/* 第一名深一階、其餘同色——排序靠長度，深淺只是給眼睛一個起點 */
.catbar-row:first-child .catbar-fill { background: var(--brand-dark); }
.catbar-row.cat-none-row .catbar-fill { background: var(--ink-soft); }
.catbar-row.cat-none-row .catbar-name { color: var(--ink-soft); }

/* ── A-2. 類別管理頁 ─────────────────────────────────────────── */
.cat-admin-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
}
.cat-admin-row:last-of-type { border-bottom: none; }
.cat-admin-name { flex: 1; min-width: 0; font-weight: 700; }
.cat-admin-actions { display: flex; align-items: center; gap: 0.3rem; flex: none; }
.cat-admin-actions form { margin: 0; }
/* 改名用 <details> 展開，不需要 JS，也不必另開一頁 */
.cat-rename { margin: 0 0 0.6rem; }
.cat-rename > summary {
  list-style: none;
  cursor: pointer;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--brand-dark);
  padding: 0.15rem 0;
}
.cat-rename > summary::-webkit-details-marker { display: none; }
.cat-rename-body {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  padding: 0.5rem 0 0.2rem;
}
.cat-rename-body input[type="text"] { flex: 1; min-width: 0; }
/* 停用中的那一段：整段淡出，但名字仍讀得到（舊帳還在用這個名字） */
.cat-off .cat-admin-name { color: var(--ink-muted); }

/* ── C. 家庭花費 ─────────────────────────────────────────────── */

/* 小孩視角主角卡：沿用 .star-hero 的深綠底＋白字（家長錢包 hero 同一套），
   數字再大一階——這一頁的重點就是那個數字。 */
.hh-hero-num {
  display: block;
  font-size: 2.6rem;
  font-weight: var(--w-strong);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
.hh-hero-foot {
  display: block;
  margin-top: 0.45rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.82);
}

/* 對照：家裡 vs 你自己。刻意用同一個顏色、同一種長條，
   不排名、不評分、不加箭頭——只是把兩個數字放在同一把尺上。 */
.hh-cmp { display: flex; flex-direction: column; gap: 0.6rem; }
.hh-cmp-row { display: block; }
.hh-cmp-head {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
  font-size: var(--t-sub);
  font-weight: 700;
}
.hh-cmp-amt { font-variant-numeric: tabular-nums; font-weight: var(--w-strong); }
.hh-cmp-track { height: 12px; border-radius: 999px; background: var(--bg-accent); overflow: hidden; }
.hh-cmp-fill { display: block; height: 100%; border-radius: 999px; background: var(--cal-family); min-width: 3px; }
.hh-cmp-row.is-mine .hh-cmp-fill { background: var(--brand); }

/* 家長列表：一列＝金額＋類別＋說明＋日期，右邊一顆刪 */
.hh-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--line);
}
.hh-row:last-of-type { border-bottom: none; }
.hh-row-main { flex: 1; min-width: 0; }
.hh-row-title { display: block; font-weight: 700;  }
.hh-row-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.15rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-soft);
}
.hh-row-amt {
  flex: none;
  font-size: var(--t-title);
  font-weight: var(--w-strong);
  font-variant-numeric: tabular-nums;
}
.hh-row-act { flex: none; }
.hh-row-act form { margin: 0; }

/* ── D. 收藏頁 ───────────────────────────────────────────────── */

/* 篩選：沿用 wallet-seg 的分段外觀，但三格、且不 sticky
   （wallet-seg 本體是 sticky，那是錢包頁的行為，不該帶進來） */
.fav-seg {
  position: static;
  top: auto;
  grid-template-columns: repeat(3, 1fr);
  margin-bottom: 0.5rem;
}
.fav-seg-2 { grid-template-columns: repeat(2, 1fr); }

.fav-row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--line);
}
.fav-row:last-of-type { border-bottom: none; }
.fav-main { flex: 1; min-width: 0; }
.fav-title { display: block;  font-weight: var(--w-strong);  }
.fav-note {
  margin: 0.2rem 0 0;
  font-size: var(--t-sub);
  color: var(--ink-muted);
  text-wrap: pretty;
}
.fav-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.35rem;
}
.fav-by {  font-weight: 700; color: var(--ink-soft); }
/* 想去／去過：不用紅綠（紅綠留給漲跌與成功危險）——想去＝暖金，去過＝品牌綠 */
.fav-state {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
}
.fav-state-want { background: var(--accent-soft); color: var(--accent-ink); }
.fav-state-been { background: var(--brand-soft); color: var(--brand-dark); }
.fav-act { display: flex; align-items: center; gap: 0.35rem; margin-top: 0.45rem; }
.fav-act form { margin: 0; }

/* ── D-3. 快速動作磚 ──────────────────────────────────────────
   第 47 批放橫跨兩欄收尾列的寫法（7 顆＝6 半寬＋1 橫跨）。
   第 57 批（2026-08-09）拆過一次（觀察期減法），第 73 批（2026-08-30，
   Tom 拍板）還原。

   第 75 批一度加「今天算假日」變 8 顆、把 tile-fav 改半寬塞 4 列整齊；
   **第 77 批（Tom 退回三態文案，2026-09-06）把那顆磚搬到卡上方的
   `.switch-row` 開關列**，磚數退回 7 顆，tile-fav 改回橫跨兩欄收尾。
   （今天頁往後不宜再加第 8 顆磚；真的要加，先把「解放日」搬去行事曆。） */
.btn.tile-fav {
  background: var(--cal-review-soft);
  color: var(--cal-review-ink);
}
.action-grid .btn.tile-fav {
  grid-column: 1 / -1;
  flex-direction: row;
  gap: 0.45rem;
}

/* ── D-3b. 開關列（今天算假日）─────────────────────────────────
   第 77 批（Tom 退回文案，2026-09-06）：三態磚語意不明，改成 iOS
   設定頁「飛航模式」式的一列——左字右開關，兩態。節奏比照 .setting-row。
   開關本體刻意不用 `input[type=checkbox]`：這裡要無 JS 也能送出，
   checkbox 光是 checked/unchecked 不會自動 POST，`<button type="submit">`
   才做得到「按下就送出」。跟 admin/rules.html 那顆 `label.switch`
   （checkbox＋JS 即時切換小卡）是兩回事，選不同的 class 名稱範圍
   （`button.switch` vs `label.switch input + .switch-track`）互不影響。 */
.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.65rem;
  padding: 0.6rem 0;
  margin: 0;
  border-bottom: 1px solid rgba(13, 115, 119, 0.08);
}
.switch-row-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.switch-row-title {
  font-weight: 700;
  color: var(--ink);
}
.switch-row-sub {
  font-size: var(--t-sub);
  color: var(--ink-muted);
  font-weight: var(--w-body);
}
button.switch {
  position: relative;
  flex: none;
  width: 51px;
  height: 31px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: var(--line);
  cursor: pointer;
  transition: background 0.2s ease;
}
button.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(13, 52, 49, 0.2);
  transition: transform 0.2s ease;
}
button.switch[aria-checked="true"] {
  background: var(--ok);
}
button.switch[aria-checked="true"]::after {
  transform: translateX(20px);
}
button.switch:focus-visible {
  outline: 2px solid var(--brand-border);
  outline-offset: 2px;
}

/* ── 第 48 批 · 連結預覽卡 ─────────────────────────────────────
   貼上社交／短影音連結後顯示縮圖＋標題。整張卡是連結（點哪都開）。
   IG／FB 抓不到時退成 .fav-pv-flat 的單行平台標，不留空縮圖位。 */
.fav-pv {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.45rem 0 0;
  padding: 0.5rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  color: inherit;
}
.fav-pv-flat { padding: 0.4rem 0.6rem; }
.fav-pv-img {
  flex: none;
  width: 96px;
  height: 64px;
  object-fit: cover;
  border-radius: 8px;
  background: var(--bg-accent);
}
.fav-pv-ico { flex: none; font-size: 1.1rem; line-height: 1; }
.fav-pv-text { min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.fav-pv-title {
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.4;
  /* 標題可能很長（YouTube 尤其）：兩行截斷，不要把整列撐開 */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fav-pv-site {
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ══ 第 49 批：星星流水（錢歸錢星星看星星）════════════════════════════
   沿用現金那組 .log-* 的視覺語彙——同一種互動語言，但兩本帳各自一頁、
   內容永不混流。這裡只補星星專屬的三種東西。 */

/* 口袋↔撲滿的內部搬動：既不是進也不是出。刻意不搶眼，但**一定看得到**——
   過濾掉它就是 Austin 那個「星星憑空少掉」的病。 */
.log-row-move { background: rgba(90, 102, 117, 0.04); }
.log-move {
  color: var(--ink-soft);
  font-weight: 700;   /* 比 .log-amt 的 800 輕一級，讀得到但不搶焦點 */
}
.log-pool-move { background: var(--surface-2); color: var(--ink-muted); }

/* 池別 chip：口袋走品牌綠、撲滿走金色，與錢包四格同一套配色 */
.log-pool-pocket { background: var(--brand-soft); color: var(--brand-dark); }
.log-pool-piggy { background: var(--accent-soft); color: var(--accent-ink); }

/* 星星流水頁的兩顆餘額 chip（沿用 .flow-bal 版面，配色跟著星星走） */
.flow-bal-pocket { background: var(--brand-soft); color: var(--brand-dark); }
.flow-bal-piggy { background: var(--accent-soft); color: var(--accent-ink); }

/* ══════════════════════════════════════════════════════════════
   第 48 批 — 收藏頁列改版（方案 1b）
   基準 v48 · redesign-52 · 整段 append 到 static/css/app.css 尾端
   既有規則不刪不改；.fav-row／.fav-title／.fav-pv-* 用後出現的同名
   規則覆寫（同權重、後者勝），舊 class 名一個都不必改。
   ══════════════════════════════════════════════════════════════ */

/* ── 1. 列骨架：縮圖 116px 方框在左，名稱與它同高 ───────────────── */
.fav-row {
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.8rem 0;
}
/* 縮圖／占位框共用外框：固定 116×116，清單高度才不會參差 */
.fav-thumb {
  flex: none;
  position: relative;
  width: 116px;
  height: 116px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  color: inherit;
}
.fav-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* 平台標貼在縮圖下緣——原本是預覽卡裡獨佔一行的文字 */
.fav-thumb-site {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0.25rem 0.4rem;
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
  color: #fff;
  background: rgba(11, 38, 36, 0.6);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 沒縮圖（沒網址、抓失敗、pending）：框留著，放類別 emoji ＋平台標。
   不留白、不塌陷——每一列一樣高。
   ⚠️ 三種狀態都要留（紅線）：ok＝縮圖、pending＝「抓預覽中…」且**不是連結**、
      failed／無＝平台圖示＋名稱。抓不到是常態，不可寫「載入失敗」或放破圖。 */
.fav-thumb-empty {
  flex-direction: column;
  gap: 0.3rem;
  background: var(--bg);
  border: 1.5px dashed var(--line);
}
.fav-thumb-emoji { font-size: 2rem; /* 圖形尺寸，不算字階 */ line-height: 1; opacity: 0.55; }
.fav-thumb-flat { font-size: var(--t-meta); font-weight: var(--w-strong); color: var(--brand-dark); }
.fav-thumb-pending { font-size: var(--t-meta); font-weight: var(--w-strong); color: var(--ink-soft); }

/* ── 2. 名稱升一階，其餘全部降 ─────────────────────────────────── */
/* ⚠️ 兩行截斷保留（紅線：YouTube 標題很長，放開會把整列撐爛）。
   名稱本身用家長打的 f.title（短），預覽抓到的長標題不再顯示在列上。 */
.fav-title {
  font-size: var(--t-title);
  line-height: 1.3;
  letter-spacing: -0.005em;
  text-wrap: pretty;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fav-title > a { color: inherit; text-decoration: none; }
/* 地點與類別 emoji 同一行，緊貼名稱下方 */
.fav-where {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}
.fav-note { margin-top: 0.3rem; font-size: var(--t-sub); }
.fav-meta { margin-top: 0.45rem; }
.fav-state { font-size: var(--t-meta); }
.fav-by { font-size: var(--t-meta); }

/* ── 3. 列上只留一顆動作 chip，其餘收進「⋯」───────────────────── */
.fav-act { margin-top: 0.5rem; }
/* 「⋯」摺疊：跟類別改名同一套 <details>，仍然沒有 JS */
.fav-more { margin: 0; }
.fav-more > summary {
  list-style: none;
  cursor: pointer;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  color: var(--ink-muted);
}
.fav-more > summary::-webkit-details-marker { display: none; }
.fav-more[open] > summary { background: var(--surface-2); }
.fav-more-body {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  padding: 0.5rem 0 0.15rem;
}
.fav-more-body form { margin: 0; }
/* 摺疊裡的「換連結／補上網址」輸入列 */
.fav-more-link {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  width: 100%;
  padding-top: 0.35rem;
}
.fav-more-link input[type="text"] { flex: 1; min-width: 0; }

/* ── 4. 舊的獨立預覽卡不再使用 ───────────────────────────────────
   .fav-pv 整組（96px 卡＋兩行文字）由 .fav-thumb 取代。
   規則留在原處不刪（紅線：既有規則不刪不改），模板不再引用即可。 */

/* 「近期進出」每列的改帳入口（第 49 批追加）。沿用 .log-photo 的下劃線語彙，
   但走中性墨色——它不是「有東西可看」而是「可以動手改」。 */
.log-edit {
  color: var(--ink-muted);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 3px;
}

/* ── 第 48 批 · 收件時補的修正（Code 端）─────────────────────────
   design 那份沒測「⋯ 展開後」的狀態：.fav-act 是 flex 列，展開時
   .fav-more-body 由內容撐成 225px（輸入框 170＋存 48），又不能收縮，
   375px 螢幕上整頁會橫向捲。讓它展開時自己佔一整列、內部可收縮。 */
.fav-act { flex-wrap: wrap; }
.fav-more { min-width: 0; }
.fav-more[open] { flex: 1 1 100%; }
.fav-more-body { max-width: 100%; }
.fav-more-link { min-width: 0; }

/* ══════════════════════════════════════════════════════════════
   第 49 批 — 小孩今天頁收尾
   基準 v50 · redesign-53 · 整段 append 到 static/css/app.css 尾端
   既有規則不刪不改。
   ══════════════════════════════════════════════════════════════ */

/* 無底色按鈕（按鈕四層的 L4）補上框線。
   問題：.btn 基底是 border: none 又沒有背景，所以「沒有修飾詞」的那顆在真機上
   只剩一行綠字 —— 看起來是文字連結不是按鈕，排在 btn-primary（實心綠）與
   btn-accent（金框）下面時整組節奏斷掉。
   修法：只補框 ＋ 白底，字級／字重／高度（48px）／圓角全部沿用基底，
   維持 L4 是最輕的一階（1.5px 淺灰框 < btn-accent 的 2px 金框）。

   排除清單（四種自己有底色的）：
   .btn-primary / .btn-accent   自己有底色
   [class*="tile-"]             快速動作色磚（家長今天頁；小孩「我們的發現」也吃這個）
   .claim-btn                   領薪水那兩顆（小孩今天頁）
   .btn-nudge                   ← 收件時補的：餐費「先記下，等等補照片」的金鈕
                                （第 41 批定案）。四個 :not() 讓這條選擇器的
                                權重是 0,5,0，會蓋過 .btn-nudge 的 0,1,0，
                                不排除的話那顆金鈕會變白底 */
.btn:not(.btn-primary):not(.btn-accent):not(.claim-btn):not(.btn-nudge):not([class*="tile-"]) {
  background: var(--surface);
  border: 1.5px solid var(--line);
  color: var(--ink);
}
/* 按壓態沿用全站的 scale + brightness（app.css 2640 行附近），這裡只補 hover */
.btn:not(.btn-primary):not(.btn-accent):not(.claim-btn):not(.btn-nudge):not([class*="tile-"]):hover {
  border-color: var(--brand-border);
}

/* ══ 第 50 批：貼上網址就記一筆（redesign-53）══════════════════════════
   Tom 2026-07-29：「就跟在 LINE 貼上連結會抓到的東西一樣。」
   字級只准三階：0.85 決策／0.8 次要／0.75 純標籤。 */

.link-card {
  margin: 0.6rem 0 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
}
.link-card-img {
  display: block;
  width: 100%;
  aspect-ratio: 1.91 / 1;   /* og:image 的慣用比例，圖再怎麼歪都不會把卡撐爛 */
  object-fit: cover;
  background: var(--bg-accent);
}
.link-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.65rem 0.75rem;
  min-width: 0;
}
/* 名字是抓來的預設值、當場可以改（Tom 2026-07-29）——所以它是 input
   不是文字。看起來要像標題（大、粗），但摸得出來可以打字（底線框）。 */
.link-card-label {
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
  color: var(--ink-soft);
}
.link-card-name {
  width: 100%;
  min-width: 0;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: var(--r-ctl);
  background: var(--surface);
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  color: inherit;
}
.link-card-name:focus {
  outline: none;
  border-color: var(--brand-border);
}
/* 沒有圖的卡（抓不到，或對方根本沒給圖）：不要留一塊空白 */
.link-card-plain .link-card-body { padding: 0.6rem 0.7rem; }
.link-card-desc {
  font-size: var(--t-sub);
  color: var(--ink-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* 說明是可編輯欄位（Tom 2026-08-30），跟名字輸入框同一套視覺，但多行 */
.link-card-desc-input {
  width: 100%;
  min-width: 0;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  font-size: var(--t-sub);
  color: inherit;
  resize: vertical;
}
.link-card-desc-input:focus {
  outline: none;
  border-color: var(--brand-border);
}
.link-card-site {
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.link-card-hint {
  margin: 0.6rem 0 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-soft);
}

/* 收回帶：按錯「去過了」的救生索。跟清單卡分開一塊，看得出是暫時的 */
.fav-undo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.fav-undo form { margin: 0; }
.fav-undo-text {
  flex: 1;
  min-width: 0;
  font-size: var(--t-sub);
  font-weight: 700;
  color: var(--ink-muted);
}

/* 清單列上的節錄（抓來的），跟自己寫的 .fav-note 區分：這句不是人寫的 */
.fav-desc {
  margin: 0.3rem 0 0;
  font-size: var(--t-sub);
  color: var(--ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* 「⋯」裡的改名稱／心得：兩格輸入 ＋ 一顆存，窄螢幕自己換行 */
.fav-more-edit {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  width: 100%;
}
.fav-more-edit input[type="text"] { flex: 1 1 8rem; min-width: 0; }

/* ══ 專款可以是負的（Tom 2026-07-29）══════════════════════════════════
   餐費是必需品，餘額見底時擋下來不會讓小孩不吃飯，只會讓那一餐不被記錄。
   所以改成先欠著——但「欠」一定要看得出來，不然家長會漏掉「該補伙食費」。 */

.pool-num-owed { color: var(--danger); }
.muted-owed { color: var(--danger); font-weight: 700; }

/* ══ 收藏類別由家長自訂（Tom 2026-07-30，redesign-55）══════════════════
   類別個數不再固定，等分 grid（.wallet-seg）5 個就只剩 73px。
   上排改成可橫向捲的 chip 列；下排「想去／去過」仍是等分 grid。 */

.fav-catbar {
  display: flex;
  gap: 0.35rem;
  margin: 0 0 0.5rem;
  padding: 0.25rem;
  background: var(--surface-2);
  border-radius: var(--r-ctl);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.fav-catbar::-webkit-scrollbar { display: none; }
.fav-cattab {
  flex: 0 0 auto;
  scroll-snap-align: start;
  text-align: center;
  text-decoration: none;
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  padding: 0.55rem 0.85rem;
  border-radius: 9px; /* 內圈=外圈 12 − 內距 */
  color: var(--ink-muted);
  white-space: nowrap;
}
.fav-cattab.is-active {
  background: #fff;
  color: var(--brand);
  box-shadow: 0 1px 4px rgba(13, 115, 119, 0.12);
}

/* 管理頁：每一類底下那行「N 筆 · 分想去去過」 */
.cat-admin-sub { margin: 0 0 0.15rem; }
.cat-admin-hint { font-size: var(--t-sub); font-weight: 700; color: var(--ink-soft); }
.cat-admin-check { display: inline-flex; align-items: center; gap: 0.35rem; }
.cat-rename-body select { flex: 1 1 6rem; min-width: 0; }

/* ══ 口袋星星的倒數（Tom 2026-08-01，redesign-56）══════════════════════
   每批星各自倒數，滿 N 小時進撲滿。放在星星英雄卡裡（深色底），
   所以文字用白色系。倒數一次只顯示一個單位（時→分→秒），欄寬才固定。 */

.pocket-cd {
  margin-top: 0.7rem;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
}
.pocket-cd-head {
  margin: 0 0 0.4rem;
  font-size: var(--t-meta);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.78);
}
.pocket-cd-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.18rem 0;
}
.pocket-cd-stars { font-size: var(--t-sub); font-weight: var(--w-strong); color: #fff; }
.pocket-cd-left {
  font-size: var(--t-sub);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  font-variant-numeric: tabular-nums;  /* 秒在跳的時候寬度不要抖 */
  white-space: nowrap;
}
.pocket-cd-due { color: var(--accent-soft); }
/* 結轉說明是一整句話，不是會跳秒的數字——nowrap 會把卡片撐出橫捲 */
.pocket-cd-note { white-space: normal; text-align: right; }

/* 小孩今天頁的「我有多少／還能玩多久」（Tom 2026-08-02）。
   整條是連結，點下去進星星那頁——原本這兩個答案要切兩次分頁才看得到。 */
.kid-stat {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0 0 0.85rem;
  padding: 0.55rem 0.75rem;
  border-radius: var(--r-ctl);
  background: var(--surface-2);
  color: var(--ink-muted);
  text-decoration: none;
  font-size: var(--t-sub);
  font-weight: 700;
}
.kid-stat strong { font-size: var(--t-body); color: var(--ink); }
.kid-stat-sep { color: var(--ink-soft); }

/* 紀錄頁的「紀錄 ／ ⚙設定」（2026-08-02）：底部第四格已改名「紀錄」，
   設定是一年去五次的東西，降級成右上角一顆齒輪，不再佔一半的分頁寬度。 */
.trail-switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.85rem;
}
.trail-switch-item {
  font-weight: var(--w-strong);
  color: var(--ink);
  text-decoration: none;
}
.trail-switch-item.is-active { color: var(--brand); }
.trail-switch-gear {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.4rem 0.7rem;
  border-radius: var(--r-ctl);
  background: var(--surface-2);
  color: var(--ink-muted);
  text-decoration: none;
  font-size: var(--t-sub);
  font-weight: var(--w-strong);
  min-height: 44px;
}
.trail-switch-gear svg { width: 18px; height: 18px; }
.trail-switch-gear.is-active {
  background: #fff;
  color: var(--brand);
  box-shadow: 0 1px 4px rgba(13, 115, 119, 0.12);
}

/* 口袋倒數放在淺色卡上（家長錢包）：小孩那張是深綠英雄卡、字是白的，
   直接搬過來會整段看不見（2026-08-02）。 */
.pocket-cd-light { border-top-color: var(--line); }
.pocket-cd-light .pocket-cd-head { color: var(--ink-muted); }
.pocket-cd-light .pocket-cd-stars { color: var(--ink); }
.pocket-cd-light .pocket-cd-left { color: var(--ink-muted); }
.pocket-cd-light .pocket-cd-due { color: var(--accent-ink); }

/* ═══════════════════════════════════════════════════════════════
   第 50 批 append：發星儀式感 ＋ 錢的全線重整
   基準 v54 · 整段 append 到 static/css/app.css 尾端，既有規則不刪不改
   前綴：award-*／push-nudge／kid-pick／split-*／ratio-*／pw-action*／
         earmark-owed／book-row2／photo-nudge-slim／chip-scroll／flow-award-line
   沿用既有：.card-soft .chip .chip-radio .log-row .log-pool .pool-cell
             .btn .btn-primary .note-sm .empty-hint .fold-inline
   ═══════════════════════════════════════════════════════════════ */

/* ── A1 慶祝卡（today/kid 頂端；「收下」是純 POST form 的 submit）── */
.award-celebrate {
  background: var(--accent-soft);
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  padding: 1.25rem 1rem 1rem;
  text-align: center;
  animation: celebrate-pop 0.45s ease-out;
}
@keyframes celebrate-pop {
  0% { transform: scale(0.85); opacity: 0; }
  60% { transform: scale(1.04); }
  100% { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .award-celebrate { animation: none; } }
.award-celebrate-ico { display: block; /* 圖形尺寸，不算字階 */ font-size: 2rem; line-height: 1; }
.award-celebrate-title { margin: 0.35rem 0 0; font-size: var(--t-title); font-weight: var(--w-strong); }
.award-celebrate-note { margin: 0.1rem 0 0; font-size: var(--t-body); font-weight: 700; color: var(--accent-ink); }
/* 去向行文案由後端組：「放滿 {{ pocket_hold_hours }} 小時就會進撲滿（這批還有 …）」
   ——小時數是 /admin/rules 可調值，不可寫死（§9.8-H ①） */
.award-celebrate-dest { margin: 0.5rem 0 0; font-size: var(--t-sub); color: var(--ink-muted); }
.award-celebrate-btn {
  display: block; width: 100%;
  background: var(--accent); color: #fff;
  font: inherit; font-size: var(--t-body); font-weight: var(--w-strong);
  border: none; border-radius: var(--r-ctl);
  padding: 0.75rem; margin-top: 0.75rem;
  min-height: 44px; cursor: pointer;
}
.award-celebrate-btn:active { transform: scale(0.98); }
/* 第 4 筆起的合併卡（堆疊上限 3 張＋這張；一顆鈕批次收） */
.award-celebrate-more {
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--r-ctl);
  padding: 0.6rem 0.85rem;
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
}
.award-celebrate-more-text { font-size: var(--t-sub); font-weight: 700; color: var(--accent-ink); }
.award-celebrate-more .award-celebrate-btn {
  width: auto; margin: 0; padding: 0.45rem 0.8rem;
  font-size: var(--t-sub); border-radius: 9px; min-height: 0;
}

/* ── A2 家長回饋卡（送出後取代 flash 條；flash 生命週期，不用收）── */
.award-fb {
  background: var(--surface);
  border: 1px solid var(--brand-border);
  border-left: 4px solid var(--ok);
  border-radius: var(--radius);
  padding: 0.75rem 0.9rem;
  display: flex; flex-direction: column; gap: 0.25rem;
}
.award-fb-head { margin: 0; font-weight: var(--w-strong); color: var(--ok-ink); }
.award-fb-line { margin: 0; font-size: var(--t-sub); color: var(--ink); }
.award-fb-line .hint { color: var(--ink-muted); }
.award-fb-warn { margin: 0.15rem 0 0; font-size: var(--t-sub); color: var(--danger-ink); }

/* ── A3 開啟通知那一行（小孩星星頁，未訂閱才渲染）── */
.push-nudge {
  background: var(--brand-soft);
  border-radius: var(--r-ctl);
  padding: 0.6rem 0.85rem;
  display: flex; align-items: center; gap: 0.6rem;
}
.push-nudge-ico { font-size: 1.1rem; /* 圖形尺寸，不算字階 */ line-height: 1; }
.push-nudge-text { flex: 1; font-size: var(--t-sub); font-weight: 700; color: var(--brand-dark); }

/* ── A4 流水裡「爸媽發的」列（星星流水共用件的 is_award 分支）
      金徽章「加在」池別徽章旁，不取代（§9.8-H ③）── */
.log-row-award {
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-ctl);
  padding-left: 0.6rem;
  padding-right: 0.6rem;
}
.log-pool-award { background: var(--accent); color: #fff; }

/* ── A5 發星／扣星表單升級 ── */
/* 「發給誰」頭像 chips（name 仍是 kid_id；radio 藏在 label 裡，無 JS 可用。
   Code 端會把 base.html 的 select[name="kid_id"] 監聽改成同時吃 radio） */
.kid-pick-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.kid-pick {
  /* Code 端補：交付把 input 設成 position:absolute 卻沒給定位祖先，
     絕對定位會跑到最近的定位祖先去，有機會把版面撐出橫捲。 */
  position: relative;
  display: flex; align-items: center; gap: 0.4rem;
  border: 2px solid var(--line); background: var(--surface);
  border-radius: 999px;
  padding: 0.3rem 0.85rem 0.3rem 0.3rem;
  font-weight: 700; color: var(--ink-muted);
  cursor: pointer; min-height: 44px;
}
.kid-pick input { position: absolute; opacity: 0; pointer-events: none; }
.kid-pick:has(input:checked) {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-weight: var(--w-strong);
}
.kid-pick:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; }
/* 顆數欄加大（發星是儀式，數字要大）；沿用 .stars-input 的框，只放大字級 */
/* Code 端訂正：既有 `.field input:not(...):not(...)` 是 (0,3,1)——第一次補
   `.field input.stars-input-big` 只有 (0,2,1) 還是輸（實測 font-weight 有套、
   字級沒套，就是被它壓的證據）。class 重複一次補到 (0,3,1) 平手、
   靠檔尾後出而勝。 */
.field input.stars-input-big.stars-input-big { font-size: 1.5rem; font-weight: var(--w-strong); width: 5rem; text-align: center; }

/* ── B1 發錢三分預覽條（無 JS：段寬照後端算好的 %；有 JS 才填實際金額）── */
.split-bar {
  display: flex; height: 38px;
  border-radius: var(--r-ctl); overflow: hidden;
  /* Code 端訂正：交付寫 0.78rem，不在字級三階（0.85／0.8／0.75）上 */
  font-size: var(--t-sub); font-weight: var(--w-strong); color: #fff; text-align: center;
}
.split-seg { display: flex; flex-direction: column; justify-content: center; min-width: 0; }
.split-seg span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 2px; }
.split-seg-free { background: var(--brand); }
.split-seg-invest { background: var(--brand-dark); }
.split-seg-goal { background: var(--accent); }
/* 專款選中：整條換灰單段 */
.split-seg-earmark { flex: 1; background: var(--surface-2); color: var(--ink-muted); justify-content: center; }
.split-rule { margin: 0.35rem 0 0; font-size: var(--t-meta); color: var(--ink-muted); }

/* ── B2 /admin/rules 三分比例欄位 ── */
.ratio-fields { display: flex; gap: 0.5rem; align-items: end; }
.ratio-fields .field { flex: 1; margin: 0; }
.ratio-fields input { text-align: center; font-weight: var(--w-strong); }
.ratio-fields.ratio-bad input { border-color: var(--danger); }
.ratio-sum {
  background: var(--brand-soft); color: var(--ok-ink);
  font-size: var(--t-sub); font-weight: var(--w-strong);
  border-radius: var(--r-ctl); padding: 0.55rem 0.6rem;
  white-space: nowrap; align-self: end;
}
.ratio-sum-bad { background: var(--danger-soft); color: var(--danger-ink); }

/* ── C 家長錢包 hero 下的發錢／發星入口（radio 預選當前分頁小孩）── */
.pw-actions { display: flex; gap: 0.5rem; }
.pw-action {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 0.35rem;
  border: 2px solid var(--brand); color: var(--brand-dark);
  background: var(--surface);
  font-weight: var(--w-strong); text-align: center; text-decoration: none;
  border-radius: var(--r-ctl); padding: 0.65rem 0.5rem; min-height: 44px;
}
.pw-action-stars { border-color: var(--accent); color: var(--accent-ink); }

/* ── D 甲案：塊內摘要化 ── */
/* 投資第 3 檔起收進「其他 N 檔」；summary 沿用 fold-inline，只加行高 */
/* 現金流水的「還有 N 筆」摺疊。**不共用 holding-more**——那是投資卡的，
   借用會讓「兩檔以內不該出現摺疊」那條測試誤判（真的踩到了）。 */
.log-more-fold > summary,
.holding-more > summary {
  font-size: var(--t-sub); font-weight: 700; color: var(--ink-muted);
  padding: 0.5rem 0; cursor: pointer; min-height: 44px;
  display: flex; align-items: center;
}
/* 缺照片橫幅 >3 筆時 chips 一行橫捲，不換行堆高 */
.chip-scroll {
  display: flex; flex-wrap: nowrap; gap: 0.4rem;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; margin-top: 0.45rem;
}
.chip-scroll::-webkit-scrollbar { display: none; }
.chip-scroll .chip { flex: 0 0 auto; }
/* Code 端補：3 筆以下走這條（原本是 inline style 的 flex-wrap）。
   交付只給了 chip-scroll，另一半沒給——不補的話 chips 會變成沒有間距的裸列。 */
.chip-row-wrap { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.45rem; }

/* photo-nudge 一行化：icon＋標題＋副句同一列，選鈕列不動 */
.photo-nudge-slim { padding: 0.55rem 0.7rem; }
.photo-nudge-slim .photo-nudge-head { margin-bottom: 0.45rem; }
.photo-nudge-slim .photo-nudge-text { flex-direction: row; align-items: baseline; gap: 0.4rem; }
.photo-nudge-slim .photo-nudge-sub { font-size: var(--t-meta); }

/* ── E2 星星進出頁（對齊 cash/flow 骨架；幾乎全部重用既有件）── */
.flow-award-line {
  background: var(--accent-soft); color: var(--accent-ink);
  /* Code 端訂正：同上，0.78rem → 0.8rem */
  font-size: var(--t-sub); font-weight: var(--w-strong);
  border-radius: var(--r-ctl); padding: 0.25rem 0.6rem;
}

/* ── E3 專款負數「欠錢」＝記號感，不是錯誤感 ── */
.earmark-owed {
  background: repeating-linear-gradient(
    -45deg,
    var(--accent-soft), var(--accent-soft) 6px,
    #faecd2 6px, #faecd2 12px
  );
}
.earmark-owed .pool-num { color: var(--ink); }
.earmark-owed-badge {
  display: inline-block;
  background: var(--accent-soft); color: var(--accent-ink); /* P2:注意式 badge */
  /* Code 端訂正：交付寫 0.62rem，破了字級三階下限（0.85／0.8／0.75）。
     tests 的 test_css_小字層只剩量過格子的日曆例外 會直接擋下——
     第 40 批交付也在同一個數字上犯過一次（.log-by .avatar-sm 也是 0.62rem）。 */
  font-size: var(--t-meta); font-weight: var(--w-strong);
  border-radius: 999px; padding: 0.05rem 0.4rem;
  margin-left: 0.3rem; vertical-align: middle;
}

/* ═══════════════════════════════════════════════════════════════
   第 51 批 append：記帳縱向壓縮（重提）＋ 錢包逐塊收高 ＋ 第 50 批微調
   基準 v55 · 整段 append 到 static/css/app.css 尾端，既有規則不刪不改
   前綴：book-compact／book-optional／wallet-cta-row／log-tight／log-row-slim
   微調（覆寫第 50 批，靠後出勝）：split-bar／award-celebrate／earmark-owed
   字級自查：本段最小 0.75rem，全部落在三階（0.85／0.8／0.75）上
   ═══════════════════════════════════════════════════════════════ */

/* ── 51-1 記帳縱向壓縮（不靠兩欄；加在四張表單的 .card-soft 上）──
   兩招：①欄距 0.75/1rem → 0.55rem；②選填欄（餐別、補充說明）收進原生
   details。390px 實測（previews）：meal 表單約省 190px，欄寬不變、無橫捲。 */
.book-compact .field { margin-bottom: 0.55rem; }
.book-compact .field:last-of-type { margin-bottom: 0.65rem; }
.book-compact > .muted:first-child { margin-bottom: 0.5rem; }
/* 選填欄摺疊：沿用 .fold-inline 的 summary 樣式，僅補行高與間距 */
.book-optional { margin: 0 0 0.55rem; }
.book-optional > summary {
  font-size: var(--t-sub); font-weight: 700; color: var(--ink-muted);
  min-height: 44px; display: flex; align-items: center; cursor: pointer;
}
.book-optional[open] > summary { margin-bottom: 0.35rem; }
.book-optional .field:last-child { margin-bottom: 0; }

/* ── 51-2 我的錢：兩顆整幅鈕併一列（記帳為主、存起來為次）── */
.wallet-cta-row { display: flex; gap: 0.5rem; margin-top: 0.75rem; }
.wallet-cta-row .btn { flex: 1; display: flex; justify-content: center; margin: 0; }
.wallet-cta-row .btn-primary { flex: 1.4; }

/* ── 51-3 近期進出緊排：標題＋徽章＋輔助鏈結同一行，長標題截尾。
      自由／專款徽章永遠可見（flex:0 0 auto），紅線 F2 不破。
      日標籤與列距同步收緊（scoped 在卡上的 .log-tight）。 ── */
.log-tight .log-day { margin: 0.5rem 0 0.1rem; }
.log-row-slim {
  display: flex; justify-content: space-between; align-items: center; gap: 0.5rem;
  padding: 0.32rem 0;
}
.log-row-slim .log-main {
  display: flex; flex-direction: row; align-items: center; gap: 0.4rem;
  min-width: 0;
}
.log-row-slim .log-label {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
}
.log-row-slim .log-meta { display: contents; }
.log-row-slim .log-pool,
.log-row-slim .log-by,
.log-row-slim .log-photo,
.log-row-slim .log-missing,
.log-row-slim .log-edit { flex: 0 0 auto; margin: 0; }
.log-row-slim .log-amt { flex: 0 0 auto; }
/* 星星流水的獎勵列（第 50 批 log-row-award）在緊排下仍要吃得到底色與金條 */
.log-row-slim.log-row-award { padding-left: 0.6rem; padding-right: 0.6rem; }

/* ── 51-4 第 50 批微調（過眼後的數值，覆寫靠檔尾後出）── */
/* 三分條：38px 兩行字太貼，加高＋定 line-height */
.split-bar { height: 42px; }
.split-seg span { line-height: var(--lh-tight); }
/* 慶祝卡：390px 上略收 padding 與行距，卡矮 ~14px、儀式感不減 */
.award-celebrate { padding: 1rem 0.9rem 0.85rem; }
.award-celebrate-title { margin-top: 0.3rem; }
.award-celebrate-dest { margin-top: 0.35rem; }
.award-celebrate-btn { margin-top: 0.65rem; padding: 0.7rem; }
/* 專款欠錢斜紋：#faecd2 寫死違反 token 慣例，改由 token 混出同一色。
   **Code 端訂正為漸進增強**：全站原本零處 color-mix，而 iOS Safari 要 16.2 起才支援；
   不支援時整條 repeating-linear-gradient 會整個失效——斜紋**靜默消失**，
   「欠錢」就只剩一個數字，正是這個專案最怕的那種失敗。
   兩條都寫：舊瀏覽器吃第一條字面值，新的被第二條覆寫。 */
.earmark-owed {
  background: repeating-linear-gradient(
    -45deg,
    var(--accent-soft), var(--accent-soft) 6px,
    #faecd2 6px, #faecd2 12px
  );
}
@supports (background: color-mix(in oklab, red 10%, blue)) {
  .earmark-owed {
    background: repeating-linear-gradient(
      -45deg,
      var(--accent-soft), var(--accent-soft) 6px,
      color-mix(in oklab, var(--accent) 10%, var(--accent-soft)) 6px,
      color-mix(in oklab, var(--accent) 10%, var(--accent-soft)) 12px
    );
  }
}

/* ═══════════════════════════════════════════════════════════════
   第 51 批（實機收尾）— **只取 `.cat-fold` 這一段**
   同一批 design 交了兩包：`wallet_compaction`（22:38）與
   `wallet_tighten`（22:49，回應四點回饋的修訂版）。兩包對「近期進出緊排」
   與「兩顆鈕併列」用了**不同做法**（`.log-row-slim` vs `.log-tight .log-row`、
   `.wallet-cta-row` vs `.btn-pair`），疊起來會互相打架。
   第一包已套用且實測 2467px（優於兩包的 2600 估計），所以第二包只取
   它真正新的這段——它解掉了我上一輪沒解掉的「記帳縱向壓縮」。
   `.alloc-inline`（把錢存起來一列式）**沒取**：那要把 `remembered_input.html`
   換成手寫 markup，是金流表單的輸入記憶機制，風險不值得——高度目標已達成。
   ═══════════════════════════════════════════════════════════════ */

/* ── B1 類別摺疊（cash/book 三支專款分支）──
   類別要嘛照舊猜對（實測 Max 94% 都是同一個），要嘛就是「換一個類別」
   這個少數動作。原生 details，無 JS 可用：不點開直接送出＝送預設。
   summary 顯示的預選名由後端傳（preselected_category_label）。 */
.cat-fold { margin: 0 0 0.75rem; }
.cat-fold > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.45rem; font-size: var(--t-sub); min-height: 44px; }
.cat-fold > summary::-webkit-details-marker { display: none; }
.cat-fold-label { font-weight: 700; }
.cat-fold-current { background: var(--accent-soft); color: var(--accent-ink); border-radius: 999px; padding: 0.15rem 0.6rem; font-size: var(--t-sub); font-weight: 700; }
.cat-fold-hint { color: var(--ink-muted); font-size: var(--t-meta); margin-left: auto; }
.cat-fold[open] .cat-fold-hint { visibility: hidden; }
.cat-fold-body { margin-top: 0.5rem; }

/* ══ 第 52 批 append：記帳最後一段（基準 v57）══════════════
   整段 append 到 static/css/app.css 尾端，既有規則不刪不改。
   前綴：chip-tight／field-inline-row／photo-nudge-1row／alloc-inline
   字級三階自查：本段只用 0.85／0.8／0.75 ✓
   觸控自查：所有 .chip 仍 min-height 44px（只收水平 padding，不收高度）✓ */

/* ── A1 緊排 chip：只收水平 padding 與字距，高度不動 ──
   餐別 5 顆（不指定／早／午／晚／點心）在 390px 從兩行變一行。
   實測寬度估算（Nunito 0.85rem）：兩字 chip ≈45px、三字 ≈57px，
   4×45 + 57 + 4×0.3rem gap ≈ 256px < 可用 ~350px。
   套在 .chip-row 上，只影響掛了 .chip-tight 的那一排。 */
.chip-row.chip-tight { gap: 0.3rem; }
.chip-row.chip-tight .chip {
  padding: 0.45rem 0.55rem;
  font-size: var(--t-sub);
  letter-spacing: 0;
}

/* ── A2 標籤與 chip 排同一行起頭 ──
   原本「餐別（選填）」「吃了什麼（點一個）」各自佔一整行（各 ~26px）。
   標籤變成 flex 的第一個項目、和第一顆 chip 同一基線。
   換行時標籤留在第一行，chip 自然往下包。 */
.field-inline-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; }
.field-inline-row > .field-inline-label {
  font-weight: 700;
  font-size: var(--t-sub);
  flex: 0 0 auto;
  margin-right: 0.15rem;
}
.field-inline-row > .field-inline-hint { font-size: var(--t-meta); color: var(--ink-muted); }

/* ── A3 照片區：nudge 標題與兩顆選鈕同一行 ──
   原本 head 一行（圖示＋兩行字）＋pick-row 一行＝兩段。
   390px 下「拍一下吃的」＋兩顆 chip 併排放得下；副標退成 head 下一行小字。
   只在掛了 .photo-nudge-1row 的那一塊生效，其他頁的 photo-nudge 不動。 */
.photo-nudge.photo-nudge-1row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.photo-nudge-1row .photo-nudge-head { flex: 1 1 auto; min-width: 0; margin: 0; }
.photo-nudge-1row .photo-nudge-sub { font-size: var(--t-meta); }
.photo-nudge-1row .receipt-pick-row { flex: 0 0 auto; margin: 0; }
.photo-nudge-1row .receipt-pick { padding: 0.45rem 0.6rem; font-size: var(--t-sub); }

/* ── B 一列式金額表單：不動 remembered_input include，純 CSS ──
   交付寫「建議清單是絕對定位的子元素，所以改 flex 橫排完全安全」——
   **前提是錯的**：`.remembered-field` 確實是 position:relative（app.css:2074），
   但 `.remembered-suggest`（app.css:2078）是普通區塊（margin: 0.35rem 0 0），
   父層 relative 不代表子層 absolute。照原樣做，清單展開時會變成 flex 項目
   **擠到輸入框旁邊**。
   Code 端補上它以為已經存在的那件事：只在 .alloc-inline 底下把清單改成
   絕對定位掛在欄位下方（父層本來就 relative，所以這樣是安全的）。 */
.alloc-inline { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.alloc-inline .remembered-field {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  flex: 0 0 auto;
}
.alloc-inline .remembered-field > label { margin: 0; font-size: var(--t-sub); font-weight: 700; }
.alloc-inline .remembered-field > input { width: 5rem; margin: 0; }
.alloc-inline > .btn {
  /* Code 端補：交付只寫了 margin:0，但 `.btn-primary { width: 100% }`（app.css:284）
     會讓鈕撐滿整行、在 flex-wrap 下自己換一行——一列式就沒發生。
     實測金額欄 top 1472、鈕 top 1530，差 58px。 */
  margin: 0;
  width: auto;
  flex: 0 0 auto;
}

/* Code 端訂正（見上）：清單絕對定位，不參與橫排 */
.alloc-inline .remembered-suggest {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 12rem;
  z-index: 20;
}

/* ═══════════════════════════════════════════════════════════════
   第 54 批（Code 端）— 撲滿星換錢：怎麼分自己選（Tom 2026-08-08）
   基準 v58 · redesign-67 · append 到尾端，既有規則不刪不改
   沿用既有：.chip .chip-radio .approve-row .muted .stars-input
   ═══════════════════════════════════════════════════════════════ */

/* 固定兩欄，不橫捲也不讓寬度自己長。
   橫捲會讓最後一題（全拿去投資）藏在畫面外，而那正是代價最大的那個，
   藏起來等於偷偷簡化了選擇；自動換行則會變成一顆一行——實測 390px 下
   最長那顆 242px，四顆各占一行多吃 200px 高，而錢包正在減肥。 */
.plan-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  margin: 0 0 0.5rem;
}
.plan-note {
  margin: 0 0 0.5rem;
  font-size: var(--t-sub);
  color: var(--ink-muted); /* 波8b 順手修:基準殘留的未定義 var(--muted) */
}
.plan-goal {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.15rem;
  font-size: var(--t-sub);
}
.plan-goal > label { flex: 0 0 auto; font-weight: 700; }
.plan-goal > select { flex: 1 1 auto; min-width: 0; margin: 0; }
/* 審核卡上的「他選了什麼」 */
.pending-plan {
  margin: 0 0 0.45rem;
  font-size: var(--t-sub);
}

/* ══ 第 54 批 append：餐費信封 ＋ 週結算（基準 v59）══════════════
   整段 append 到 static/css/app.css 尾端，既有規則不刪不改。
   前綴：env-*（envelope）
   重用不重造：結算的四題 chip 直接用既有 .plan-row / .plan-chip；
   欠錢的斜紋與徽章直接用既有 .earmark-owed / .earmark-owed-badge。

   ⚠ 本段**零固定高度、零寫死寬度**（Code 端無法提供 390px 實測值，
   所以不做任何依賴實測的版型）：卡高由內容撐開、數字用 clamp() 隨寬度縮，
   一行放不下就換行。最窄 320px 到最寬平板都不會溢出。

   字級三階自查：輔助文字只用 0.85／0.8／0.75；
   1.75rem 與 1.05rem 是「數字」不是輔助文字（同 .cash-hero-num／.pool-num）。 */

/* ── ① 餐費信封卡（四池下方獨立卡；卡殼沿用 .card-soft）────────── */
.env-card { display: flex; flex-direction: column; gap: 0.5rem; }

.env-head { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.env-name { font-weight: var(--w-strong); font-size: var(--t-title); color: var(--ink); }
/* 「還要撐 3 天」——時間性是這張卡的重點，給它徽章的份量 */
.env-days {
  background: var(--accent-soft); color: var(--accent-ink);
  border-radius: 999px; padding: 0.1rem 0.6rem;
  font-size: var(--t-sub); font-weight: var(--w-strong); white-space: nowrap;
}
.env-days-last { background: var(--danger-soft); color: var(--danger-ink); }

/* 大字：今天還能花 N。clamp 讓四位數在窄機上自己縮，不必量寬度 */
.env-today {
  margin: 0; font-weight: var(--w-strong); line-height: var(--lh-tight); color: var(--brand-dark);
  font-size: clamp(1.4rem, 9vw, 1.75rem);
  font-variant-numeric: tabular-nums;
}
.env-today-label { font-size: var(--t-sub); font-weight: 700; color: var(--ink-muted); }
/* 今天已經花超過日均：數字歸零、不變紅、不罵他（同 .earmark-owed 的分寸） */
.env-today-zero { color: var(--ink-muted); }

.env-sub { margin: 0; font-size: var(--t-sub); color: var(--ink-muted); }
/* 新的一封被扣掉上期欠款：結果當主詞，過程退成這一行小字 */
.env-note-debt { margin: 0; font-size: var(--t-meta); color: var(--accent-ink); }

.env-track {
  height: 8px; border-radius: 999px; background: var(--line);
  overflow: hidden;
}
.env-fill { height: 100%; border-radius: 999px; background: var(--brand); }
/* 花光了：條滿格轉暖色，仍不是錯誤色 */
.env-fill-full { background: var(--accent); }

/* ── ② 其他信封：一行一封 ──────────────────────────────────
   餐費以外的封（修自行車、臨時備用金、學費課本）多半沒有到期日，
   所以這一列**不畫倒數也不畫進度**——只有名字與剩多少。
   有到期日時右邊才多一顆 .env-days。 */
.env-line {
  display: flex; align-items: center; gap: 0.5rem;
  /* 整列是連結，觸控紅線 44px：padding 只給到 36px，靠 min-height 補足
     （同 .chip／.cat-fold > summary 的做法） */
  min-height: 44px;
  padding: 0.5rem 0; border-top: 1px solid var(--line);
  text-decoration: none; color: inherit;
}
.env-line-name { font-weight: 700; font-size: var(--t-sub); min-width: 0; flex: 1 1 auto;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.env-line-num { font-weight: var(--w-strong); font-size: var(--t-sub); flex: 0 0 auto;
  font-variant-numeric: tabular-nums; }
.env-line-num-owed { color: var(--danger-ink); }

/* ── ③ 結算卡：這一封結束了 ──────────────────────────────────
   ⚠ 紅線：**不是慶祝卡**。沒有 🎉、沒有漸層、沒有「你省下了」。
   用中性的收尾色（--surface-2）講一件事實，然後把選擇權交給他。
   四題 chip 直接沿用 .plan-row / .plan-chip，本段不再定義。 */
.env-settle {
  background: var(--surface-2); border: 1.5px solid var(--brand-border);
  border-radius: var(--radius); padding: 1rem;
  display: flex; flex-direction: column; gap: 0.5rem;
}
.env-settle-title { margin: 0; font-weight: var(--w-strong); font-size: var(--t-title); }
.env-settle-num { font-weight: var(--w-strong); font-size: clamp(1.4rem, 9vw, 1.75rem);
  line-height: var(--lh-tight); color: var(--brand-dark); font-variant-numeric: tabular-nums; margin: 0; }
.env-settle-sub { margin: 0; font-size: var(--t-sub); color: var(--ink-muted); }
/* 結算卡等他挑完才消失（Tom 2026-08-08）：這行講清楚為什麼它還在 */
.env-settle-wait { margin: 0; font-size: var(--t-meta); color: var(--accent-ink); }

/* ── ④ 家長端：每個小孩的信封明細 ────────────────────────────
   沿用 .env-line 的排版，外面包一層帶標題的區塊即可。 */
.env-parent-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.5rem; font-size: var(--t-sub); color: var(--ink-muted); font-weight: 700;
  margin-top: 0.5rem;
}

/* ── ⑤ 發專款表單：天數那一列 ────────────────────────────────
   金額欄後面接「發幾天」，同一列；窄機自己換行。 */
.env-span-row { display: flex; align-items: flex-end; gap: 0.5rem; flex-wrap: wrap; }
.env-span-row > .field { margin-bottom: 0; }
.env-span-hint { font-size: var(--t-meta); color: var(--ink-muted); flex-basis: 100%; margin: 0; }

/* ── 第 58 批 A1：最近的結果（小孩今天頁）─────────────────────────
   ⚠ 紅線：**不是慶祝卡**。沒有漸層、沒有動畫、沒有圖示，
   核准與駁回**共用同一種卡**——差別只在文字。駁回要的是記號感不是錯誤感，
   所以這裡刻意不給 .is-bad 之類的紅色修飾類別（給了就會有人拿去用）。
   字級三階：0.85（結果本文）／0.8（標題）／0.75（時間與註腳）。 */
.result-block {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 0.75rem 0.85rem;
  margin-bottom: 0.85rem;
}
.result-title {
  margin: 0 0 0.15rem; font-size: var(--t-sub); font-weight: var(--w-strong); color: var(--ink-muted);
}
.result-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.5rem; margin: 0; padding: 0.4rem 0; border-top: 1px solid var(--line);
}
.result-text { font-size: var(--t-sub); font-weight: 700; min-width: 0; }
.result-when {
  font-size: var(--t-meta); color: var(--ink-muted); flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}
/* 看過就收起來——不講的話下次打開會變成「剛剛那行怎麼不見了」 */
.result-foot {
  margin: 0.4rem 0 0; padding-top: 0.4rem; border-top: 1px solid var(--line);
  font-size: var(--t-meta); color: var(--ink-muted);
}

/* ═══════════════════════════════════════════════════════════════
   第 61 批 · 夢想計價（append 到 app.css 尾端；既有規則不刪不改）

   字級一律 var(--t-*, 硬值)。**第 72 批減法 A3 更新（2026-08-23）**：
   這段原本寫「上線後自動接上」，但四顆 token 從第 61 批到第 71 批
   一直沒有人定義，而同一個檔案下面（波 8a，`:root` 在檔尾）另有一份
   字級階梯——兩份數字不一樣，誰也沒有標明哪份是活的。現況如下：

     已定義且是活的（波 8a，第 69 批，檔尾 :root）：
       --t-body 0.95rem 16.15px / --t-sub 0.85rem 14.45px / --w-body 400
     過渡別名（第 72 批 A3 補進同一個 :root，值＝各自原本的 fallback，
     所以補上去的當下視覺零變化）：
       --t-display 1.75rem / --t-num 1.3rem / --t-title 1.05rem / --t-meta 0.75rem

   **下面這行的 --t-body 0.875rem 是第 61 批當時的值，已經過期**——
   波 8a 把它改成 0.95rem，這七個元件在第 69 批就自動接上了。
   **最終階梯由波 8b 決定**：波 8b 會重訂 --t-title／--t-num／--t-micro
   並收掉 1rem 那一層，屆時上面四顆過渡別名的值會被改寫，
   本段註解也要一併重寫。在那之前，不要照這段的舊數字新增規則。
   全段零百分比文字；`%` 只出現在進度條寬度與行情（見 README §四）。
   ═══════════════════════════════════════════════════════════════ */

/* ── 61a-1 第二步摘要卡：整頁唯一的 --t-display ─────────────── */
.dp-sum {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.6rem;
  background: var(--surface);
  border-radius: var(--radius);
  padding: 0.85rem;
  box-shadow: var(--shadow);
  margin-bottom: 0.6rem;
}
.dp-sum-label {
  display: block;
  font-size: var(--t-meta);
  font-weight: var(--w-body);
  color: var(--ink-muted);
}
.dp-sum-num {
  display: block;
  font-size: var(--t-display);
  font-weight: var(--w-strong);
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
}
/* 摘要卡裡那顆是 L2（回第一步的真連結，不是頁內返回鍵） */
.dp-sum > .chip { flex: none; }

/* ── 61a-2／61b 夢想條：決定畫面共用 ───────────────────────── */
.dp-strip {
  background: var(--brand-soft);
  border: 1px solid var(--brand-border);
  border-radius: var(--radius);
  padding: 0.7rem 0.85rem;
  margin-bottom: 0.6rem;
}
.dp-strip-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
.dp-strip-main {
  font-size: var(--t-num);
  font-weight: var(--w-strong);
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
}
/* 夢想條裡的 pace 副句比卡片裡深一階——底色是 brand-soft，灰字會掉到 3:1 以下 */
.dp-strip .goal-eta,
.dp-strip .goal-eta-ok,
.dp-strip .goal-eta-none { color: #3f5b58; }

/* ── 61a-3 四個分配選項 ────────────────────────────────────── */
.plan-opts {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.plan-opt {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  min-height: 48px;
  box-sizing: border-box;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--r-ctl);
  padding: 0.6rem 0.65rem;
  cursor: pointer;
}
.plan-opt:has(input:checked) { border-color: var(--brand); }
.plan-opt > input[type="radio"] {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 0.18rem 0 0;
  accent-color: var(--brand);
}
.plan-opt-body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.plan-opt-amt {
  font-size: var(--t-title);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.plan-opt-sub {
  font-size: var(--t-body);
  font-weight: var(--w-body, 400);
  color: var(--ink-muted);
}
/* 講夢想的那一句用 ok-ink：它是這一批的重點，也是唯一「確定的錢」 */
.plan-opt-sub.is-dream { color: var(--ok-ink); }

/* ── 61a-4 33% 地面帶：四個選項站著的地板，不是第五個選項 ──
   刻意貼齊選項下緣（負 margin 吃掉 gap）、共用下緣圓角、無 radio、不可點。 */
.plan-floor {
  margin: -2px 0 0.6rem;
  border-top: 2px solid var(--brand-border);
  border-radius: 0 0 var(--r-ctl) var(--r-ctl);
  background: var(--surface-2);
  padding: 0.5rem 0.65rem;
  font-size: var(--t-meta);
  font-weight: var(--w-body);
  color: #3f5b58;
}

/* ── 61a-5 零目標邀請行（SPEC §四 的全 App 最重要空狀態）────
   暖色＝邀請不是錯誤；退掉的計價句在同一個位置說出它為什麼不在。 */
.dream-empty {
  margin: 0 0 0.6rem;
  background: var(--accent-soft);
  border: 1px solid var(--warm-deep);
  border-radius: var(--radius);
  padding: 0.7rem 0.85rem;
  font-size: var(--t-body);
  font-weight: var(--w-body, 400);
  color: var(--accent-ink);
  text-wrap: pretty;
}
.dream-empty > a { color: var(--accent-ink); font-weight: 700; }

/* ── 61b 主夢想卡的 pace 副句：既有 .goal-eta 的兩個新修飾子 ── */
.goal-eta-ok { color: var(--ok-ink); }
.goal-eta-warn { color: var(--accent-ink); }

/* ── 61b-⑧ 待挑卡：主夢想存滿又有多個候選（全站退回元計價）── */
.dream-pick {
  background: var(--surface);
  border: 2px solid var(--brand-border);
  border-radius: var(--radius);
  padding: 0.85rem;
}
.dream-pick-title {
  margin: 0.3rem 0 0.5rem;
  font-size: var(--t-title);
  font-weight: 700;
  text-wrap: pretty;
}
.dream-pick-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--r-ctl);
  text-decoration: none;
  color: var(--ink);
}
.dream-pick-row + .dream-pick-row { margin-top: 0.35rem; }
.dream-pick-name { font-size: var(--t-body); font-weight: 700; min-width: 0; }
.dream-pick-num {
  flex: none;
  font-size: var(--t-meta);
  font-weight: var(--w-strong);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* ── 61c 投資區的夢想句 ────────────────────────────────────
   .inv-dream＝確定的錢（現在就能轉）；.inv-dream-plain＝不確定或沒有夢想。
   賠錢一律用 -plain：紙上損益不移動夢想，夢想沒有退。 */
.inv-dream,
.inv-dream-plain {
  margin: 0.1rem 0 0;
  font-size: var(--t-body);
  font-weight: var(--w-body, 400);
}
.inv-dream { color: var(--ok-ink); }
.inv-dream-plain { color: var(--ink-muted); }

/* ── 第 61 批 · 收件審查的微調（2026-08-15）──────────────────────
   交付的 `.dream-pick-row` 是照 `<a href>` 畫的，但換主夢想是**狀態變更**，
   紅線要求純 POST form。所以那一列改成 `<form><button>`，
   下面把按鈕 reset 回「看起來就是一列」——版面一格都沒動。
   既有規則不刪不改，只 append。 */
.dream-pick-form { margin: 0; }
.dream-pick-form + .dream-pick-form > .dream-pick-row { margin-top: 0.35rem; }
button.dream-pick-row {
  width: 100%;
  background: var(--surface);
  font: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

/* 61c 的「賺 N／賠 N」那一行：夢想句的主句，跟副句同一組間距。
   數字本身沿用既有的 `<strong>`，不新增字級。 */
.inv-dream-line {
  margin: 0.5rem 0 0;
  font-variant-numeric: tabular-nums;
}

/* ══ 第 63 批 波 3 · 追加式（append 到 app.css 尾端，既有規則不刪不改）══
   沿用既有：.env-settle .env-settle-title .env-settle-num .env-settle-sub
             .dp-sum .dp-sum-label .dp-sum-num .dp-strip .plan-opt
             .plan-floor .setting-arrow                                      */

/* ── 波3-① 結算入口卡 ───────────────────────────────────────
   四題選項搬到第二步頁之後，錢包上這張卡只剩「發生了什麼＋去哪裡決定」。
   整張卡是一個連結（不是卡裡放一顆鈕）——目標區塊 390×177，
   小孩不必瞄準。無 JS 紅線：它就是一個 <a href>。 */
.env-settle-link { text-decoration: none; color: var(--ink); gap: 0.3rem; }
.env-settle-go {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 44px; margin-top: 0.1rem;
  font-size: var(--t-body); font-weight: 700; color: var(--brand-dark);
}
.env-settle-go .setting-arrow { font-size: 1.2rem; /* 圖形尺寸，不算字階 */ line-height: 1; }

/* ── 波3-② 第二步一屏收斂 ───────────────────────────────────
   摘要卡改單行（標籤與金額同一基線），省 29px。
   星換錢與結算兩個來源共用；星換錢那顆「改星數」chip 仍在同一行右側。 */
.dp-sum.is-tight { margin-bottom: 0.45rem; padding-top: 0.45rem; padding-bottom: 0.45rem; }
.dp-sum.is-tight > span {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.4rem;
}
.dp-sum.is-tight .dp-sum-label { display: inline; }
/* 第 72 批減法 A3：原本是 `var(--t-num)`，而 --t-num 一直沒被定義，
   實際吃的是 1.5rem。A3 把 --t-num 定成 1.3rem（＝它在別處的 fallback）之後，
   這一條會**變小 0.2rem**——但這是波 3-② 刻意訂的「第二步一屏收斂」尺寸
   （1.75 → 1.5，介於 --t-display 與 --t-num 之間，階梯裡沒有這一級）。
   改吃 --t-display 會反而變大回 1.75rem，一樣不是零變化。
   **保留硬值 1.5rem**，等波 8b 訂完階梯再歸位。 */
.dp-sum.is-tight .dp-sum-num { font-size: var(--t-num); }

/* ══ 第 63 批 波 4 ═══════════════════════════════════════════════════
   指路卡上的「▸」是假摺疊箭頭。`.fold-sum::after` 是給真的 `<details>`
   用的，`.pw-linkcard` 是一個 `<a href>`——點下去會跳頁不會展開，那顆
   ▸ 說的是另一件事（同 `test_家長錢包四格補齊且假箭頭已解` 抓到的那類）。
   收掉它，方向指示交給 `.setting-arrow` 的「›」。 */
.pw-linkcard .fold-sum::after { content: none; }
.pw-linkcard .setting-arrow { flex: none; /* 圖形尺寸，不算字階 */ font-size: 1.2rem; line-height: 1; }

/* ══ 第 63 批 波 6＋波 7 · 追加式（append 到尾端，既有規則不刪不改）══════
   沿用既有：.card-soft .gcard-alloc .log-row .log-row-slim .log-amt .log-in
             .dp-sum .dp-sum-label .dp-sum-num .note-sm .setting-arrow
             .pw-linkcard .split-seg                                        */

/* ── 波 6-① 夢想頁的「做」與「因」 ─────────────────────────────
   撥款表單與最近撥入列共用一張卡（接在主夢想卡下面）。
   `.gcard-alloc` 自帶 border-top——它原本長在卡片內部當分隔線，
   這裡是卡片的第一個孩子，那條線會變成卡頂一條多出來的橫線。 */
.dream-do { margin-top: 0.6rem; }
.dream-do > .gcard-alloc:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}
.dream-cause-label {
  margin: 0 0 0.35rem;
  font-size: var(--t-meta);
  font-weight: 700;
  color: var(--ink-muted);
}

/* ── 波 6-② 記帳結果條 ──────────────────────────────────────
   沿用第二步的 `.dp-sum.is-tight`（同一種「一行講完一件事」的摘要條）。
   這裡只加它跟頁標題之間的距離與第三段的字級——第三段是**現況**
   （「Switch 還差 1,140 元」），不是變化量，所以不變色、不加箭頭。 */
.dp-sum-result { margin-bottom: 0.75rem; }
.dp-sum-result .dp-sum-tail {
  flex-basis: 100%;
  font-size: var(--t-meta);
  font-weight: var(--w-body);
  color: var(--ink-muted);
}

/* ── 波 7-① 家長四池卡下的主夢想列 ──────────────────────────
   一列 56px，跟 `.pw-linkcard` 同一個高度與內距語彙（它也是「一列＋›」）。
   沒有主夢想時是 `<span>` 不是 `<a>`，所以 hover／箭頭都不出現。 */
.pw-dream {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 56px;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--bg-accent);
  text-decoration: none;
  color: inherit;
}
.pw-dream-name {
  flex: 1;
  min-width: 0;
  font-size: var(--t-body);
  font-weight: 700;
}
.pw-dream-num {
  flex: none;
  font-size: var(--t-body);
  font-weight: var(--w-strong);
  font-variant-numeric: tabular-nums;
}
.pw-dream-none { font-weight: var(--w-body); color: var(--ink-muted); }
.pw-dream .setting-arrow { flex: none; /* 圖形尺寸，不算字階 */ font-size: 1.2rem; line-height: 1; }

/* ── 波 7-② 發錢 modal 的夢想預覽行 ─────────────────────────
   接在三分預覽條下面，講「那一份進去之後會怎樣」。
   `hidden` 由同檔 JS 控（專款／沒填金額／該小孩沒有主夢想都不講話）。 */
.give-dream {
  margin: 0.45rem 0 0;
  font-size: var(--t-meta);
  font-weight: var(--w-body);
  color: var(--ink-muted);
}
.give-dream[hidden] { display: none; }

/* ═══════════════════════════════════════════════════════════════
   第 69 批 · 波 8a：字級 token 第一批（append；既有規則一行不刪不改）

   階梯出處＝第 63 批報告 §6.1（**後訂、以現況為準**，不是第 60 批階段 A 的
   0.875rem 那版）：--t-body 0.95rem／--t-sub 0.85rem。根字級 17px，
   所以 0.95rem = 16.15px、0.85rem = 14.45px。

   本波只動 font-size 與「內文」那一組的 font-weight，**不動 line-height、
   不動 margin**（那是下一波），高度因此只會有可預測的 ±2% 漂移。

   分組準則（盤點表在 design/outbox_specs/spec_69_wave8a.md）：
     內文    ＝讀的是句子（說明、清單內容、列的描述）→ --t-body ＋ --w-body
     非內文  ＝名稱、列標題、行內數字、按鈕與連結文字 → 只換 size，weight 不動
     不動    ＝① 輸入框（iOS 在 <16px 的欄位聚焦時會自動放大整頁，1rem=17px
                  只剩 0.85px 餘裕，字級要動得先訂輸入層 token）
                ② 圖示／字符（頭像字母、✓、×、›、⋯——那是圖形尺寸不是字級）
                ③ 1rem 的卡片標題與大數字（屬 --t-title／--t-num，波 8b）
                ④ 後面已被更高權重或更後面的規則蓋掉的宣告（動它只會製造死宣告）
   ═══════════════════════════════════════════════════════════════ */

:root {
  --t-body: 1rem;      /* 17px；波 8b 拍板＝根字級（原 0.95rem，若 Tom 否決改回即可） */
  --t-sub: 0.85rem;    /* 14.45px；與第 21 批「說明句 0.85」同值，只是換成 token */
  --w-body: 400;       /* 內文字重：第 63 批 §9-② Tom 拍板由 600–800 降到 400 */

  /* ── 第 72 批減法 A3（2026-08-23）：四顆「假 token」補齊 ──────────
     `--t-display`／`--t-num`／`--t-title`／`--t-meta` 從第 61 批起被
     18 條宣告以 `var(--t-x, 硬值)` 的形式引用，卻**從來沒有被定義過**，
     18 條全部一直在吃 fallback。同一個檔案裡因此有兩份互相矛盾的字級階梯
     （見本檔 ~6224 那段註解），下一個人照哪一份做都可能是錯的。

     **這四個值＝它們各自現在的 fallback 值**，所以定義的當下視覺零變化；
     它們是**過渡別名**，不是拍板的階梯。最終階梯由**波 8b**決定
     （波 8b 要一起收 --t-micro 與 1rem 那一層），屆時直接改這四行的值。

     定義好之後，那 18 條的硬編 fallback 一併拿掉（`var(--t-x, 1.75rem)`
     → `var(--t-x)`）：§4.5「禁新增 `var(--x, 硬值)` 硬編 fallback；
     token 缺就補進 `:root`」。留著的話波 8b 改了 token，畫面卻可能
     還吃著舊值——而且要改的地方變成兩處。

     唯一 fallback 不同的個案是 `.dp-sum.is-tight .dp-sum-num`
     （原本 `var(--t-num)`，比這裡的 1.3rem 大），
     已就地改成硬值 1.5rem 保住原樣，見該行註解。 */
  --t-display: 1.75rem;  /* 過渡別名：第 61 批 .dp-sum-num 的 fallback 值 */
  --t-num: 1.35rem;      /* 22.95px；波 8b 定案＝.brand/.page-title 現值 */
  --t-title: 1.15rem;    /* 19.55px；波 8b 定案 */
  --t-meta: 0.75rem;     /* 過渡別名：第 61 批 6 條 meta 字的 fallback 值 */
  /* ── 波 8b-1（redesign-77）：字重 2 級＋行高＋間距 token（間距波 8b-2 才鋪）── */
  --w-strong: 700;     /* 名稱、標題、數字、按鈕字；取代散落的 800/900 */
  --lh-tight: 1.2;     /* 標題／數字／單行控制項；內文一律吃 body 的 1.45 */
  --sp-1: 0.25rem;     /* 行內元素之間 */
  --sp-2: 0.5rem;      /* 卡內元素之間 */
  --sp-3: 0.75rem;     /* 區塊之間、卡與卡之間 */
  --sp-4: 1.15rem;     /* 卡片內距（＝.card-soft 現行左右值） */
}

/* ── 8a-1 內文：吃 --t-body ＋ --w-body ────────────────────────
   只有這一組動 weight，而且只動「本來就寫死 600–800 的句子」；
   本來沒寫 font-weight 的維持不寫，避免把繼承來的字重意外改掉。 */
/* ── 8a-1 內文：吃 --t-body ＋ --w-body ────────────────────────
   只有這一組動 weight，而且只動「本來就寫死 600–800 的句子」；
   本來沒寫 font-weight 的維持不寫，避免把繼承來的字重意外改掉。 */
.page-lead,
.fam-sum-kid,
.wait-row,
.weekly-list {
  font-size: var(--t-body);
}
.pattern-line,
.award-celebrate-note {
  font-size: var(--t-body);
  font-weight: var(--w-body);
}

/* ── 8a-2 非內文：只換 size，weight 一律不動 ──────────────────── */

/* 按鈕與 chip 的字（例外清單：weight 維持現值） */
.btn,
.chip,
.check-chip,
.day-pass-btn,
.award-celebrate-btn,
.action-grid .btn,
.photo-nudge .receipt-pick,
.gcard-alloc .btn-accent-sm {
  font-size: var(--t-body);
}

/* 連結列與切換列 */
/* 連結列與切換列 */
.trail-switch-item,
.back-link,
.kid-cash-more,
.pending-jump {
  font-size: var(--t-body);
}

/* 名稱與列標題（不是卡片標題——那一層是 --t-title，波 8b） */
/* 名稱與列標題（不是卡片標題——那一層是 --t-title，波 8b） */
.login-brand .brand-sub,
.sprout-lv,
.nudge-title,
.rule-row-label,
.per-kid-name,
.photo-nudge-title,
.photo-picked-title,
.pw-hold-name,
.pw-pick-name,
.catbar-name,
.hh-cmp-head,
.fav-pv-title,
.stars-label,
.remember-row {
  font-size: var(--t-body);
}

/* 行內數字（跟著同一列的文字走；大字數字屬 --t-num，本波不定義） */
.pw-hold-mkt,
.catbar-amt,
.kid-stat strong {
  font-size: var(--t-body);
}

/* 提示條與狀態（有底色的訊號，weight 是它的語氣，不降） */
/* 提示條與狀態（有底色的訊號，weight 是它的語氣，不降） */
.flash,
.status-wait {
  font-size: var(--t-body);
}

/* ── 8a-3 說明句層：吃 --t-sub ────────────────────────────────
   值與現況相同（0.85rem），這一段只是把 69 條散落的宣告接上 token；
   真正變小的只有原本 0.88rem 的七條（見 spec 的變化表）。
   weight 這一波一律不動——sub 層的字重是波 8b 的題目。 */
/* ── 8a-3 說明句層：吃 --t-sub ────────────────────────────────
   值與現況相同（0.85rem），這一段只是把 69 條散落的宣告接上 token；
   真正變小的只有原本 0.88rem 的七條（見 spec 的變化表）。
   weight 這一波一律不動——sub 層的字重是波 8b 的題目。 */
.header-meta,
.header-view-switch > summary,
.field label,
.member-user,
.cal-daynum,
.cal-day-meta,
.cal-event-time .t-all,
.quest-bar-meta .hint,
.section-label,
.habit-mini-list,
.rate-line,
.dual-preview .opt,
.note-sm,
.ptr-tip,
.fold-sum,
.kid-fold-row .fold-sum,
.wallet-jump a,
.fam-sum-meal,
.streak-sub,
.weekly-talk,
.back-sticky-page,
.star-pool-sub,
.chip.chip-compact,
.chip-row.chip-tight .chip,
.nudge-sub,
.mins-analogy,
.pool-num-row .pool-pct,
.pool-rate,
.rule-card-sub,
.rule-row-unit,
.rule-preview,
.rule-off-note,
.photo-nudge-sub,
.photo-later,
.photo-picked-name,
.photo-hint,
.photo-nudge-1row .receipt-pick,
.gcard-diff,
.gcard-alloc-text,
.gcard-pending,
.gcard-done-sub,
.gcard-done-cta,
.pw-alert-text,
.pw-inv-total,
.pw-hold-pct,
.pw-pick-hint,
.pw-empty-sub,
.nomoney-sub,
.cat-rename > summary,
.cat-fold > summary,
.hh-hero-foot,
.fav-where,
.fav-note,
.fav-cattab,
.link-card-name,
.pocket-cd-stars,
.award-celebrate-more-text,
.award-fb-line,
.push-nudge-text,
.log-more-fold > summary,
.holding-more > summary,
.book-optional > summary,
.field-inline-row > .field-inline-label,
.alloc-inline .remembered-field > label,
.plan-goal,
.pending-plan,
.env-today-label,
.env-line-name,
.env-line-num,
.env-settle-sub,
.result-text,
.empty-hint {
  font-size: var(--t-sub);
}


/* ═══ 波 8b-1（redesign-77，2026-08-29 design）：字階鋪完 ═══════════════
   字階 6 級（--t-meta/sub/body/title/num/display）／字重 2 級（--w-body 400、
   --w-strong 700；唯二例外 .brand/.page-title 800）／行高 3 種（1.45 body、
   --lh-tight 1.2、圖示 1）。詳 batch65_typography/spec_65_wave8b1.md。
   圖形尺寸不算字階（×/›/emoji/頭像/登入英雄），逐行已標「圖形尺寸」註解。 */
strong, b { font-weight: var(--w-strong); } /* 蓋掉 UA 的 bolder：700 容器內的 strong 不再被推到 900（合成粗體＝糊） */
