/* ============================================================
   MIWANG — THƯ VIỆN COMPONENT DÙNG CHUNG
   ------------------------------------------------------------
   Dùng cho CẢ trang công khai LẪN admin dashboard.
   Mọi giá trị lấy từ css/tokens.css — không có số lẻ nào ở đây.

   Quy ước đặt tên: .khối__phần--biến-thể
   ============================================================ */

/* ============================================================
   NÚT
   Bốn cỡ dùng chung hệ tỷ lệ ở token §6: chiều cao, padding, cỡ chữ,
   cỡ icon và gap luôn thay đổi cùng nhau.
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ctl-md-gap);
  height: var(--ctl-md-h);
  padding-inline: var(--ctl-md-px);
  border-radius: var(--r-pill);
  font-family: var(--f-body);
  font-size: var(--ctl-md-fs);
  font-weight: var(--fw-medium);
  line-height: 1;
  letter-spacing: var(--ls-normal);
  white-space: nowrap;
  cursor: pointer;
  border: var(--bw) solid transparent;
  transition: background-color var(--d-fast) var(--ease),
              border-color var(--d-fast) var(--ease),
              color var(--d-fast) var(--ease),
              transform var(--d-instant) var(--ease);
}

.btn:active { transform: scale(0.98); }

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
}

.btn__icon-svg {
  width: var(--ctl-md-icon);
  height: var(--ctl-md-icon);
  flex: none;
}

/* Núm tròn chứa mũi tên — đặc trưng lấy từ ảnh tham khảo.
   Nút có núm phải giảm padding bên phải để núm không lệch tâm. */
.btn--knob { padding-right: calc((var(--ctl-md-h) - var(--ctl-md-knob)) / 2); }

.btn__knob {
  display: grid;
  place-items: center;
  width: var(--ctl-md-knob);
  height: var(--ctl-md-knob);
  border-radius: var(--r-circle);
  flex: none;
  transition: transform var(--d-base) var(--ease);
}
.btn__knob svg { width: var(--ctl-md-icon); height: var(--ctl-md-icon); }
.btn:hover .btn__knob { transform: translateX(3px); }

/* ---- Cỡ ---- */
.btn--sm {
  height: var(--ctl-sm-h);
  padding-inline: var(--ctl-sm-px);
  font-size: var(--ctl-sm-fs);
  gap: var(--ctl-sm-gap);
}
.btn--sm .btn__icon-svg { width: var(--ctl-sm-icon); height: var(--ctl-sm-icon); }

.btn--lg {
  height: var(--ctl-lg-h);
  padding-inline: var(--ctl-lg-px);
  font-size: var(--ctl-lg-fs);
  gap: var(--ctl-lg-gap);
}
.btn--lg .btn__icon-svg { width: var(--ctl-lg-icon); height: var(--ctl-lg-icon); }
.btn--lg.btn--knob { padding-right: calc((var(--ctl-lg-h) - var(--ctl-lg-knob)) / 2); }
.btn--lg .btn__knob { width: var(--ctl-lg-knob); height: var(--ctl-lg-knob); }
.btn--lg .btn__knob svg { width: var(--ctl-lg-icon); height: var(--ctl-lg-icon); }

.btn--xl {
  height: var(--ctl-xl-h);
  padding-inline: var(--ctl-xl-px);
  font-size: var(--ctl-xl-fs);
  gap: var(--ctl-xl-gap);
}
.btn--xl .btn__icon-svg { width: var(--ctl-xl-icon); height: var(--ctl-xl-icon); }
.btn--xl.btn--knob { padding-right: calc((var(--ctl-xl-h) - var(--ctl-xl-knob)) / 2); }
.btn--xl .btn__knob { width: var(--ctl-xl-knob); height: var(--ctl-xl-knob); }
.btn--xl .btn__knob svg { width: var(--ctl-xl-icon); height: var(--ctl-xl-icon); }

/* ---- Biến thể ---- */
.btn--primary { background: var(--c-accent); color: var(--c-text-on-accent); }
.btn--primary:hover { background: var(--c-accent-hover); }
.btn--primary:active { background: var(--c-accent-press); }
.btn--primary .btn__knob { background: var(--c-text-on-accent); color: var(--c-accent); }

.btn--contrast { background: var(--c-text); color: var(--c-bg); }
.btn--contrast:hover { background: var(--c-text-muted); }
.btn--contrast .btn__knob { background: var(--c-bg); color: var(--c-text); }

.btn--ghost {
  background: transparent;
  color: var(--c-text);
  border-color: var(--c-border-strong);
}
.btn--ghost:hover { border-color: var(--c-accent); color: var(--c-accent); }

.btn--subtle { background: var(--c-bg-elev-2); color: var(--c-text); }
.btn--subtle:hover { background: var(--c-bg-elev-3); }

.btn--danger { background: var(--c-danger); color: #fff; }
.btn--danger:hover { filter: brightness(1.08); }

.btn--plain { background: transparent; color: var(--c-text-muted); }
.btn--plain:hover { color: var(--c-text); background: var(--c-bg-elev-2); }

.btn--block { width: 100%; }

/* ============================================================
   NÚT CHỈ CÓ ICON
   Hình vuông theo chiều cao control để luôn tròn đều.
   ============================================================ */
.icon-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--ctl-md-h);
  height: var(--ctl-md-h);
  border-radius: var(--r-circle);
  border: var(--bw) solid var(--c-border);
  background: transparent;
  color: var(--c-text-muted);
  cursor: pointer;
  flex: none;
  transition: color var(--d-fast) var(--ease),
              border-color var(--d-fast) var(--ease),
              background-color var(--d-fast) var(--ease);
}
.icon-btn svg { width: var(--ctl-md-icon); height: var(--ctl-md-icon); }
.icon-btn:hover { color: var(--c-text); border-color: var(--c-border-strong); background: var(--c-bg-elev-2); }

.icon-btn--sm { width: var(--ctl-sm-h); height: var(--ctl-sm-h); }
.icon-btn--sm svg { width: var(--ctl-sm-icon); height: var(--ctl-sm-icon); }
/* Cỡ SM là 32px, DƯỚI ngưỡng chạm 44px → nới vùng bấm ngầm bằng ::after,
   giữ nguyên kích thước nhìn thấy (§12.3).
   Nới đúng 6px mỗi phía = 44px. Không nới hơn: hai nút cạnh nhau cách
   nhau 8px, nới quá sẽ khiến vùng chạm CHỒNG LẤN — lỗi tệ hơn nút nhỏ. */
.icon-btn--sm::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: var(--r-circle);
}

.icon-btn--lg { width: var(--ctl-lg-h); height: var(--ctl-lg-h); }
.icon-btn--lg svg { width: var(--ctl-lg-icon); height: var(--ctl-lg-icon); }

.icon-btn--filled { background: var(--c-accent); color: var(--c-text-on-accent); border-color: transparent; }
.icon-btn--filled:hover { background: var(--c-accent-hover); color: var(--c-text-on-accent); }

/* ============================================================
   TRƯỜNG NHẬP LIỆU
   Input, select, textarea dùng CHUNG chiều cao và padding với nút
   → xếp cạnh nhau trên một hàng luôn thẳng đáy.
   ============================================================ */
.field { display: grid; gap: var(--s-2); }

.field__label {
  font-size: var(--t-sm);
  font-weight: var(--fw-medium);
  color: var(--c-text);
  line-height: var(--lh-snug);
}
.field__label .req { color: var(--c-danger); margin-left: var(--s-1); }

/* Dòng giải thích "để làm gì" — §6.1 bắt buộc cho trường khó hiểu */
.field__hint {
  font-size: var(--t-xs);
  color: var(--c-text-dim);
  line-height: var(--lh-snug);
}
.field__error {
  font-size: var(--t-xs);
  color: var(--c-danger);
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--ctl-md-h);
  padding: 0 var(--ctl-md-px);
  border-radius: var(--ctl-md-radius);
  border: var(--bw) solid var(--c-border-strong);
  background: var(--c-bg-inset);
  color: var(--c-text);
  font-family: var(--f-body);
  /* 16px trên di động là bắt buộc: dưới 16px thì iOS Safari TỰ PHÓNG TO
     trang khi người dùng chạm vào ô nhập, phá toàn bộ bố cục. */
  font-size: var(--t-base);
  line-height: var(--lh-snug);
  transition: border-color var(--d-fast) var(--ease),
              box-shadow var(--d-fast) var(--ease),
              background-color var(--d-fast) var(--ease);
}

.textarea {
  padding-block: var(--s-3);
  min-height: calc(var(--ctl-md-h) * 3);
  line-height: var(--lh-base);
  resize: vertical;
}

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

.input:hover,
.select:hover,
.textarea:hover { border-color: var(--c-text-dim); }

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

.input:disabled,
.select:disabled,
.textarea:disabled { opacity: 0.5; cursor: not-allowed; }

.input[aria-invalid="true"],
.textarea[aria-invalid="true"] { border-color: var(--c-danger); }

/* Ô nhập số: tắt nút tăng/giảm cho gọn (cạm bẫy §6.6.4) */
.input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.input[type="number"]::-webkit-outer-spin-button,
.input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Select: mũi tên tự vẽ để đồng nhất trên mọi hệ điều hành.
   SVG nhúng bằng data URI nên không phát sinh request mạng. */
.select {
  appearance: none;
  padding-right: calc(var(--ctl-md-px) + var(--icon-md) + var(--s-2));
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a7a76' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--ctl-md-px) center;
  background-size: var(--icon-md);
  cursor: pointer;
}

/* Ô nhập kèm icon bên trái */
.input-group { position: relative; display: flex; align-items: center; }
.input-group .input { padding-left: calc(var(--ctl-md-px) + var(--icon-sm) + var(--s-2)); }
.input-group__icon {
  position: absolute;
  left: var(--ctl-md-px);
  width: var(--icon-sm);
  height: var(--icon-sm);
  color: var(--c-text-dim);
  pointer-events: none;
}

/* ---- Công tắc bật/tắt ---- */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  cursor: pointer;
  /* Cả cụm công tắc + nhãn cao đủ 44px để dễ chạm */
  min-height: var(--tap-min);
}
.switch__track {
  position: relative;
  width: 44px;
  height: 26px;
  border-radius: var(--r-pill);
  background: var(--c-bg-elev-3);
  flex: none;
  transition: background-color var(--d-fast) var(--ease);
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 20px; height: 20px;
  border-radius: var(--r-circle);
  background: var(--c-text);
  transition: transform var(--d-base) var(--ease);
}
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch input:checked + .switch__track { background: var(--c-accent); }
.switch input:checked + .switch__track::after {
  transform: translateX(18px);
  background: var(--c-text-on-accent);
}
.switch input:focus-visible + .switch__track {
  outline: var(--focus-ring-w) solid var(--c-accent);
  outline-offset: var(--focus-ring-offset);
}
.switch__label { font-size: var(--t-sm); }

/* ============================================================
   THẺ
   ============================================================ */
.card {
  background: var(--c-bg-elev);
  border: var(--bw) solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  transition: border-color var(--d-base) var(--ease),
              background-color var(--d-base) var(--ease);
}
.card--flush { padding: 0; overflow: hidden; }
.card--interactive { cursor: pointer; }
.card--interactive:hover { border-color: var(--c-border-strong); }

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  margin-bottom: var(--s-5);
}
.card__title { font-size: var(--t-d4); font-weight: var(--fw-bold); letter-spacing: var(--ls-tight); }
.card__body { display: grid; gap: var(--s-4); }

/* Khung ảnh trong thẻ — CHỈ đặt tỉ lệ khung, KHÔNG đặt kèm min-height.
   Đặt cả hai sẽ khoá luôn chiều rộng tối thiểu và gây tràn ở màn hẹp
   (cạm bẫy hình học §12.4). */
.media {
  position: relative;
  aspect-ratio: var(--ar-card);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--c-bg-elev-2);
  display: grid;
  place-items: center;
}
.media--video    { aspect-ratio: var(--ar-video); }
.media--portrait { aspect-ratio: var(--ar-portrait); }
.media--square   { aspect-ratio: var(--ar-square); }
.media--photo    { aspect-ratio: var(--ar-photo); }
.media img { width: 100%; height: 100%; object-fit: cover; }
/* Khung nhúng video phải được ép kích thước: mặc định iframe là 300×150,
   không theo aspect-ratio của .media, nên sẽ lệch hẳn khỏi khung. */
.media iframe { width: 100%; height: 100%; border: 0; }

/* ============================================================
   NHÃN & HUY HIỆU
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  height: 26px;
  padding-inline: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-bg-elev-2);
  color: var(--c-text-muted);
  font-size: var(--t-2xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1;
}
.badge--accent  { background: var(--c-accent-soft);  color: var(--c-accent); }
.badge--success { background: var(--c-success-soft); color: var(--c-success); }
.badge--warning { background: var(--c-warning-soft); color: var(--c-warning); }
.badge--danger  { background: var(--c-danger-soft);  color: var(--c-danger); }
.badge--info    { background: var(--c-info-soft);    color: var(--c-info); }

/* Chấm trạng thái LUÔN đi kèm chữ — không dùng màu làm phương tiện
   truyền đạt duy nhất (§12.5). */
.badge__dot { width: 6px; height: 6px; border-radius: var(--r-circle); background: currentColor; flex: none; }

/* Thẻ phân loại bấm được — dùng cho bộ lọc dự án và thẻ blog */
.tag {
  display: inline-flex;
  align-items: center;
  height: var(--ctl-md-h);
  padding-inline: var(--s-5);
  border-radius: var(--r-pill);
  border: var(--bw) solid var(--c-border);
  background: transparent;
  color: var(--c-text-muted);
  font-size: var(--t-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: all var(--d-fast) var(--ease);
}
.tag:hover { color: var(--c-text); border-color: var(--c-border-strong); }
.tag[aria-pressed="true"],
.tag--active { background: var(--c-accent); color: var(--c-text-on-accent); border-color: transparent; }

/* ============================================================
   AVATAR
   ============================================================ */
.avatar {
  width: var(--avatar-md);
  height: var(--avatar-md);
  border-radius: var(--r-circle);
  overflow: hidden;
  background: var(--c-bg-elev-2);
  display: grid;
  place-items: center;
  flex: none;
  font-size: var(--t-sm);
  font-weight: var(--fw-semibold);
  color: var(--c-text-muted);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--xs { width: var(--avatar-xs); height: var(--avatar-xs); font-size: var(--t-2xs); }
.avatar--sm { width: var(--avatar-sm); height: var(--avatar-sm); font-size: var(--t-xs); }
.avatar--lg { width: var(--avatar-lg); height: var(--avatar-lg); font-size: var(--t-base); }
.avatar--xl { width: var(--avatar-xl); height: var(--avatar-xl); font-size: var(--t-d4); }
.avatar--2xl{ width: var(--avatar-2xl);height: var(--avatar-2xl);font-size: var(--t-d3); }

/* ============================================================
   BẢNG
   Bảng nhiều cột trên màn hẹp: GIỮ bề rộng tự nhiên rồi cho cuộn
   ngang TRONG khung riêng — không bóp chữ đến mức mỗi từ một dòng,
   và không đẩy cả trang cuộn ngang (§12.4).
   ============================================================ */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  border: var(--bw) solid var(--c-border);
  border-radius: var(--r-lg);
  -webkit-overflow-scrolling: touch;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
  min-width: 640px;   /* dưới ngưỡng này thì cuộn, không bóp */
}
.table caption {
  text-align: left;
  padding: var(--s-4) var(--s-5);
  font-size: var(--t-xs);
  color: var(--c-text-dim);
}
.table th,
.table td {
  padding: var(--s-4) var(--s-5);
  text-align: left;
  border-bottom: var(--bw) solid var(--c-border);
  vertical-align: middle;
}
.table th {
  font-size: var(--t-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-text-dim);
  background: var(--c-bg-elev);
  position: sticky;
  top: 0;
  z-index: var(--z-raised);
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--c-bg-elev); }
.table td.num { font-variant-numeric: tabular-nums; text-align: right; }

/* ============================================================
   PHÂN TRANG
   ============================================================ */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  flex-wrap: wrap;
  list-style: none;
}
.pagination__link {
  display: grid;
  place-items: center;
  min-width: var(--ctl-md-h);
  height: var(--ctl-md-h);
  padding-inline: var(--s-3);
  border-radius: var(--r-md);
  border: var(--bw) solid var(--c-border);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  color: var(--c-text-muted);
  transition: all var(--d-fast) var(--ease);
}
.pagination__link:hover { color: var(--c-text); border-color: var(--c-border-strong); }
.pagination__link[aria-current="page"] {
  background: var(--c-accent);
  color: var(--c-text-on-accent);
  border-color: transparent;
  font-weight: var(--fw-semibold);
}
.pagination__gap { color: var(--c-text-dim); padding-inline: var(--s-2); }

/* ============================================================
   BREADCRUMB
   ============================================================ */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); list-style: none; font-size: var(--t-sm); }
.breadcrumb li { display: flex; align-items: center; gap: var(--s-2); color: var(--c-text-dim); }
.breadcrumb li + li::before {
  content: "/";
  color: var(--c-text-dim);
  opacity: 0.6;
}
/* Vùng chạm đủ 44px theo §12.3. Chữ nhỏ nên hộp chữ chỉ cao ~22px —
   phải tự nới chiều cao, nếu không ngón tay bấm trượt trên di động. */
.breadcrumb a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  /* Nhãn ngắn như "Dự án" chỉ rộng 37px — vẫn hụt chuẩn dù đã đủ cao. */
  min-width: var(--tap-min);
  color: var(--c-text-muted);
}
.breadcrumb a:hover { color: var(--c-accent); }
.breadcrumb [aria-current="page"] { color: var(--c-text); }

/* ============================================================
   HỘP THOẠI
   ============================================================ */
.scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-scrim);
  background: var(--c-scrim);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--d-base) var(--ease), visibility var(--d-base);
}
.scrim[data-open="true"] { opacity: 1; visibility: visible; }

.modal {
  position: fixed;
  z-index: var(--z-modal);
  /* Neo theo tâm bằng inset + margin auto thay vì transform:
     tránh làm mờ chữ do lớp hợp thành ở một số máy. */
  inset: 0;
  margin: auto;
  width: min(560px, calc(100vw - var(--s-8)));
  /* Chiều cao tối đa dùng dvh để không bị thanh địa chỉ di động cắt mất đáy */
  max-height: min(680px, calc(100dvh - var(--s-8)));
  display: flex;
  flex-direction: column;
  background: var(--c-bg-elev);
  border: var(--bw) solid var(--c-border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-4);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px) scale(0.98);
  transition: opacity var(--d-base) var(--ease),
              transform var(--d-base) var(--ease),
              visibility var(--d-base);
}
.modal[data-open="true"] { opacity: 1; visibility: visible; transform: none; }

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-6);
  border-bottom: var(--bw) solid var(--c-border);
  flex: none;
}
.modal__title { font-size: var(--t-d4); font-weight: var(--fw-bold); letter-spacing: var(--ls-tight); }
.modal__body { padding: var(--s-6); overflow-y: auto; display: grid; gap: var(--s-5); }
.modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-6);
  border-top: var(--bw) solid var(--c-border);
  flex: none;
}

@media (max-width: 560px) {
  /* Trên di động, hộp thoại trượt từ đáy lên — dễ với ngón cái hơn */
  .modal {
    inset: auto 0 0;
    margin: 0;
    width: 100%;
    max-height: 88dvh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    transform: translateY(100%);
  }
  .modal__foot { flex-direction: column-reverse; }
  .modal__foot .btn { width: 100%; }
}

/* ============================================================
   THÔNG BÁO KẾT QUẢ
   ============================================================ */
.toast {
  position: fixed;
  z-index: var(--z-toast);
  left: 50%;
  bottom: var(--s-6);
  transform: translateX(-50%) translateY(12px);
  display: flex;
  align-items: center;
  gap: var(--s-3);
  max-width: calc(100vw - var(--s-8));
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-pill);
  background: var(--c-bg-elev-3);
  border: var(--bw) solid var(--c-border);
  box-shadow: var(--shadow-3);
  font-size: var(--t-sm);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--d-base) var(--ease),
              transform var(--d-base) var(--ease),
              visibility var(--d-base);
}
.toast[data-open="true"] { opacity: 1; visibility: visible; transform: translateX(-50%); }
.toast__icon { width: var(--icon-md); height: var(--icon-md); flex: none; }
.toast--success .toast__icon { color: var(--c-success); }
.toast--danger  .toast__icon { color: var(--c-danger); }

/* ============================================================
   TRẠNG THÁI: ĐANG TẢI · RỖNG · LỖI
   Cả ba phải được THIẾT KẾ, không để trắng (§12.3).
   ============================================================ */
.skeleton {
  background: linear-gradient(90deg, var(--c-bg-elev) 25%, var(--c-bg-elev-2) 50%, var(--c-bg-elev) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s linear infinite;
  border-radius: var(--r-sm);
}
.skeleton--text { height: 1em; margin-block: 0.3em; }
.skeleton--title { height: 1.6em; width: 60%; }
.skeleton--media { aspect-ratio: var(--ar-card); border-radius: var(--r-md); }

@keyframes skeleton-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}

.state {
  display: grid;
  place-items: center;
  gap: var(--s-4);
  text-align: center;
  padding: var(--s-10) var(--s-5);
  border: var(--bw) dashed var(--c-border-strong);
  border-radius: var(--r-lg);
  background: var(--c-bg-elev);
}
.state__icon {
  display: grid;
  place-items: center;
  width: var(--avatar-lg);
  height: var(--avatar-lg);
  border-radius: var(--r-circle);
  background: var(--c-bg-elev-2);
  color: var(--c-text-dim);
}
.state__icon svg { width: var(--icon-lg); height: var(--icon-lg); }
.state__title { font-size: var(--t-d4); font-weight: var(--fw-bold); letter-spacing: var(--ls-tight); }
.state__text { font-size: var(--t-sm); color: var(--c-text-dim); max-width: 46ch; line-height: var(--lh-base); }
.state--danger { border-color: var(--c-danger); }
.state--danger .state__icon { background: var(--c-danger-soft); color: var(--c-danger); }

/* Nhãn "chỗ này còn trống" — hiện rõ để không lọt vào bản bàn giao (§14.2) */
.placeholder-note {
  display: block;
  font-size: var(--t-sm);
  color: var(--c-text-dim);
  line-height: var(--lh-base);
  max-width: 30ch;
}
.placeholder-note strong {
  display: block;
  color: var(--c-warning);
  font-size: var(--t-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  margin-bottom: var(--s-2);
}

/* ============================================================
   TIỆN ÍCH
   ============================================================ */
.stack   { display: grid; gap: var(--s-4); }
.stack-2 { display: grid; gap: var(--s-2); }
.stack-6 { display: grid; gap: var(--s-6); }
.row     { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.row-end { display: flex; align-items: center; gap: var(--s-3); justify-content: flex-end; flex-wrap: wrap; }
.spread  { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Nội dung rộng bất kỳ (biểu đồ, khối mã) cuộn TRONG khung riêng */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
