/* ─────────────────────────────────────────────────────────────────────
   HỆ THỐNG THỊ GIÁC · sản phẩm hoàn tiền Đầy Túi
   Rút ra ngày 2026-09-27 sau khi đọc trọn hệ thống của ShopBack, Klarna
   và Wise trên Mobbin, mỗi sản phẩm 8 tới 10 màn liền mạch.

   Hướng: sao kê ngân hàng. Không phải biên lai giấy thủ công, và không
   phải bảng điều khiển fintech nhiều màu.

   MƯỜI LUẬT. Trái luật nào thì sửa, đừng thêm ngoại lệ.

   1.  Màu chia hai tầng, và hai tầng không bao giờ chạm nhau.

       TẦNG THƯƠNG HIỆU. Một màu duy nhất, dùng ở nơi nói "đây là ai":
       băng trên cùng, nút chính, mục đang chọn, chữ ký thương hiệu.

       TẦNG TIỀN. Xanh là đã đối soát, hổ phách là ước tính, đỏ là huỷ
       hoặc âm. Ba màu này không bao giờ dùng để trang trí.

       Màu thương hiệu không được chạm vào con số tiền, huy hiệu trạng
       thái, hay dòng trong bảng. Ngược lại, ba màu tiền không được dùng
       làm nhận diện. Lẫn hai tầng thì người ta không biết màu đang nói
       về thương hiệu hay đang nói về tiền của họ.

       Cấu trúc này lấy từ ShopBack, Gojek và Grab: dải màu thương hiệu ở
       trên, thẻ trắng chở dữ liệu ở dưới.
   2.  Một câu nhắc không phải trạng thái tiền, nên nó dùng khối trung
       tính. Chỉ tô màu khi thứ đó thật sự làm tiền kẹt lại.
   3.  Mọi số tiền và mọi mã dùng chữ đơn cách, để cột số thẳng hàng.
   4.  Số đã chắc là số chính. Số ước tính là dòng phụ nhỏ hơn ngay dưới,
       không bao giờ bằng vai. Hai số bằng nhau thì số ước tính trông như
       tiền đã có, mà T12 cấm đúng điều đó.
   5.  Huy hiệu trạng thái luôn có chấm màu kèm chữ, để người mù màu vẫn
       phân biệt được. Không bao giờ dùng riêng màu để mang nghĩa.
   6.  Nút đen là cam kết, nút viền là tuỳ chọn. Mỗi màn một nút đen.
   7.  Tab gạch chân dùng cho mục lớn. Viên thuốc dùng cho bộ lọc trong
       một mục. Không đổi vai hai thứ đó.
   8.  Bốn giá trị bo góc, không có giá trị thứ năm. Khi một thứ bo góc
       nằm trong một thứ bo góc khác, bán kính trong bằng bán kính ngoài
       trừ đi khoảng đệm. Bằng nhau thì trông lệch, mà lệch ngược thì
       trông hỏng.
   9.  Trên thiết bị cảm ứng, mọi thứ bấm được đạt 44px.
   10. Ảnh phải là ảnh thật. Không dựng giao diện giả bằng div.

   NGOẠI LỆ, cố ý và có giới hạn. Ba bề mặt dưới đây giữ nguyên ngôn ngữ
   thị giác của chủ nó, vì giả vờ chúng là của ta thì người dùng hiểu sai
   mình đang ở đâu:

   - Luồng chat Telegram, xem chat.css
   - Tấm chọn tài khoản của Google, trong onboarding.html
   - Vỏ khung điện thoại trong các trang trưng bày

   Mọi mã màu viết cứng trong prototype đều nằm trong ba chỗ đó. Chỗ khác
   mà có mã màu cứng là lỗi.
   ───────────────────────────────────────────────────────────────────── */

:root {
  /* Trung tính. Không có sắc độ, hue = 0. */
  --paper: oklch(97.2% 0 0);
  --paper-2: oklch(94% 0 0);
  /* Gần bằng nền của ảnh đất nặn (#f0f1ec), để ảnh liền với khung chứa nó. */
  --paper-clay: oklch(95.5% 0 0);
  --surface: oklch(100% 0 0);
  --ink: oklch(17% 0 0);
  --ink-2: oklch(45% 0 0);
  --ink-3: oklch(56% 0 0);
  --line: oklch(89% 0 0);
  --line-strong: oklch(76% 0 0);

  /* TẦNG THƯƠNG HIỆU. Một màu, đổi bằng đúng năm dòng này.
     Xanh biển, hue 250. Chọn bằng khoảng cách tới ba màu tiền, vì luật
     số 1 chỉ đứng được khi băng thương hiệu không đọc nhầm thành trạng
     thái tiền. Hue 250 cách đỏ huỷ 137 độ, cách xanh đã đối soát 98 độ,
     cách hổ phách 175 độ. Không ứng viên nào khác rộng bằng.
     Bốn màu đã loại nằm ở mau.html, kèm lý do. Hue chốt cùng tên ở T20. */
  --brand: oklch(52% 0.185 250);
  --brand-hover: oklch(45% 0.18 250);
  --brand-soft: oklch(96% 0.03 250);
  --brand-top: oklch(54% 0.19 248);
  --brand-band-end: oklch(35% 0.15 262);
  --brand-band: linear-gradient(160deg, var(--brand-top), var(--brand-band-end));

  /* TẦNG TIỀN. Ba trạng thái, không thêm màu thứ tư.
     Không dùng chúng để trang trí. */
  --confirmed: oklch(48% 0.14 152);
  --confirmed-soft: oklch(95% 0.045 152);
  --pending: oklch(54% 0.14 65);
  --pending-soft: oklch(95% 0.05 75);
  --void: oklch(52% 0.19 27);
  --void-soft: oklch(95% 0.04 27);

  /* Chữ và nền trong suốt đặt trên dải xanh thương hiệu. */
  --on-brand: oklch(100% 0 0 / 0.97);
  --on-brand-2: oklch(100% 0 0 / 0.85);
  --on-brand-fill: oklch(100% 0 0 / 0.1);
  --on-brand-fill-hover: oklch(100% 0 0 / 0.16);
  --brand-glow: oklch(62% 0.16 245 / 0.45);

  --scrim: oklch(17% 0 0 / 0.35);
  --line-hair: oklch(17% 0 0 / 0.07);

  /* Chữ. Một họ cho giao diện, một họ đơn cách cho tiền và mã.
     Không dùng serif: taste-skill mục 4.1 xếp serif là lựa chọn mặc định rất không nên. */
  --font-ui: "Be Vietnam Pro", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --font-display: var(--font-ui);

  --text-micro: 0.6875rem;
  --text-sm: 0.8125rem;
  --text-base: 0.9375rem;
  --text-lg: 1.0625rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.75rem;
  --text-display: clamp(2.1rem, 1.3rem + 3.2vw, 3.75rem);
  --text-money-hero: clamp(2rem, 1.3rem + 2.6vw, 3rem);

  --tracking-label: 0.1em;

  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-8: 3rem;
  --sp-section: clamp(3rem, 2rem + 4vw, 6rem);

  /* Một thang bo góc duy nhất, theo luật khoá hình dạng ở mục 4.4.
     Ngoài bốn giá trị này, không có bo góc nào khác trong sản phẩm. */
  --radius-sm: 4px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;
  /* Dùng cho thứ nằm lọt trong một khung bo --radius với đệm 4px. */
  --radius-inner: 6px;

  /* Vùng chạm tối thiểu trên thiết bị cảm ứng. */
  --touch: 44px;

  /* Bóng đổ nhuốm theo màu nền, không đen thuần. */
  --shadow-raise: 0 1px 2px oklch(17% 0 0 / 0.06);
  --shadow-lift: 0 1px 3px oklch(17% 0 0 / 0.08), 0 8px 24px oklch(17% 0 0 / 0.06);
  --shadow-float: 0 2px 4px oklch(20% 0.05 262 / 0.08), 0 24px 48px oklch(20% 0.08 262 / 0.18);
  --shadow-brand: 0 24px 48px oklch(20% 0.1 262 / 0.28);

  --duration-fast: 120ms;
  --duration-normal: 200ms;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Chuyển trang mờ dần thay vì trắng xoá. Trình duyệt chưa hỗ trợ thì chuyển như cũ. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }

  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: var(--duration-normal);
  }
}

/* Thuộc tính hidden luôn thắng, kể cả khi lớp của phần tử có đặt display. */
[hidden] {
  display: none !important;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Luôn chừa chỗ cho thanh cuộn, để trang ngắn và trang dài canh giữa như nhau khi chuyển trang. */
html {
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.022em;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

a {
  color: inherit;
}

/* ---- Primitive: nhãn chữ nhỏ in hoa.
   Dùng tiết kiệm. taste-skill mục 4.7 giới hạn tối đa 1 nhãn trên mỗi 3 mục. ---- */
.label {
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  /* Chữ 11px viết hoa: ink-3 chỉ đạt 4,3:1 trên nền giấy, ink-2 mới qua AA. */
  color: var(--ink-2);
}

/* ---- Primitive: số tiền. Đơn cách để cột tiền thẳng hàng tuyệt đối. ---- */
.money {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: -0.03em;
}

.money--confirmed {
  color: var(--confirmed);
}

.money--pending {
  color: var(--pending);
}

/* Số tiền từ 24px trở lên: Be Vietnam Pro 800, chữ số bảng (DESIGN.md, The Tabular Money Rule). */
.money--hero {
  font-family: var(--font-ui);
  font-weight: 800;
  letter-spacing: -0.03em;
}

/* Số 0đ không phải tiền bị huỷ, nên màu ink-3, không gạch ngang. */
.money--zero {
  color: var(--ink-3);
}

.money--void {
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

/* ---- Primitive: mã đơn, ngày, mọi chuỗi cần đọc từng ký tự ---- */
.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.92em;
  letter-spacing: -0.01em;
}

/* ---- Primitive: huy hiệu trạng thái.
   Có chấm màu kèm chữ, để người mù màu vẫn phân biệt được. ---- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 2px 8px 2px 7px;
  border-radius: var(--radius-sm);
  font-size: var(--text-micro);
  font-weight: 600;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.badge--confirmed {
  background: var(--confirmed-soft);
  color: oklch(40% 0.12 152);
}

.badge--pending {
  background: var(--pending-soft);
  color: oklch(45% 0.11 62);
}

.badge--void {
  background: var(--void-soft);
  color: oklch(45% 0.16 27);
}

/* ---- Primitive: mặt nổi ---- */
.sheet {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* ---- Primitive: nút. Một thang bo góc, phản hồi khi bấm. ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 44px;
  padding: 0.6rem 1.15rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition:
    transform var(--duration-fast) var(--ease-out-expo),
    background-color var(--duration-fast) linear,
    border-color var(--duration-fast) linear;
}

.btn--primary {
  background: var(--brand);
  color: oklch(100% 0 0);
}

.btn--primary:hover {
  background: var(--brand-hover);
}

.btn--primary:active {
  transform: scale(0.985);
}

.btn--small {
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--text-sm);
}

.btn--ghost {
  background: var(--surface);
  border-color: var(--line-strong);
  color: var(--ink);
}

.btn--ghost:hover {
  border-color: var(--ink);
}

.btn--ghost:active {
  transform: scale(0.985);
}

.btn:focus-visible,
a:focus-visible,
input:focus-visible,
button:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
}

/* ---- Primitive: tab lọc ---- */
.tabs {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  flex-shrink: 0;
  scrollbar-width: none;
}

.tab {
  min-height: 34px;
  padding: 0.3rem 0.8rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--ink-2);
  white-space: nowrap;
  cursor: pointer;
  transition: all var(--duration-fast) linear;
}

.tab:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.tab[aria-selected="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: oklch(100% 0 0);
}

/* ---- Primitive: bảng kê khoá và giá trị ---- */
.kv {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-2) var(--sp-4);
  font-size: var(--text-base);
}

.kv dt {
  color: var(--ink-2);
}

.kv dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

/* ---- Primitive: khối lưu ý trước khi làm gì đó.
   Trung tính, không màu. Mẫu "Take note" của ShopBack.

   Luật màu của sản phẩm này: màu chỉ xuất hiện khi nó nói về trạng thái tiền.
   Một câu nhắc "đừng bấm link khác" không phải trạng thái tiền, nên nó không
   được mượn màu hổ phách của dòng chờ đối soát. ---- */
/* Nhận đúng hai con: một dấu (span hoặc svg) rồi một <p>. Bỏ chữ trần hay
   thêm thẻ inline vào đây thì chúng thành ô lưới riêng và chữ vỡ thành cột. */
.warn {
  display: grid;
  grid-template-columns: 16px 1fr;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  background: var(--paper-2);
  font-size: var(--text-sm);
  color: var(--ink-2);
}

.warn svg {
  width: 16px;
  height: 16px;
  margin-top: 3px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
}

/* ---- Ghi chú của bản prototype, không thuộc sản phẩm ---- */
.note {
  border-left: 2px solid var(--line-strong);
  padding-left: var(--sp-3);
  font-size: var(--text-sm);
  color: var(--ink-2);
}

.note code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--paper-2);
  padding: 0 4px;
  border-radius: var(--radius-sm);
}

/* Trên thiết bị cảm ứng, mọi thứ bấm được phải đạt 44px.
   Chuột thì nhỏ hơn được, nên chỉ bơm khi con trỏ là ngón tay. */
@media (pointer: coarse) {
  .tab,
  .btn,
  .subtab,
  .chip {
    min-height: var(--touch);
  }

  .chip {
    display: inline-flex;
    align-items: center;
  }

  .tab {
    padding-inline: var(--sp-4);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---- Primitive: đang xử lý ---- */
/* Vòng xoay đứng trước chữ của nút đang chờ. Giảm chuyển động thì vòng đứng yên, chữ vẫn báo. */
.is-busy {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  cursor: progress;
}

.is-busy::before {
  content: "";
  flex: none;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: busy-spin 700ms linear infinite;
}

@keyframes busy-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Icon đứng trước chữ trong nút, tô theo màu chữ. */
.btn__icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  fill: currentColor;
}

/* Chữ chỉ cho trình đọc màn hình, như "khoảng" đọc thay cho dấu "~". */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
