/* ──────────────────────────────────────────────────────────────────────────────────────────
   yolocodes — lớp thiết kế "YOLO nhưng tỉnh"
   ──────────────────────────────────────────────────────────────────────────────────────────
   Nạp SAU app.css, có chủ đích. app.css là 36KB rule viết tay trên một site đang chạy; viết
   lại tại chỗ nghĩa là rollback phải revert ba mươi sáu kilobyte dưới áp lực. Cách này rollback
   là gỡ một dòng <link>.

   ĐỊNH VỊ: người trẻ sống YOLO nhưng tiêu tiền tỉnh — đi tìm đồ tốt, giá tốt. Tra
   ui-ux-pro-max từ ba hướng độc lập (coupon marketplace, travel/tourism, và chính định vị này)
   đều trả về cùng một style: Vibrant & Block-based, với Aurora UI là lớp gradient mượn từ
   ngành du lịch.

   RÀNG BUỘC THẬT: thẻ du lịch sáng được là nhờ NHIẾP ẢNH. Site này không có — 34/34 ảnh trang
   danh mục là logo store 150x150. Nên độ sáng đến từ màu, gradient, chữ và bố cục; đây là chỗ
   cố ý lệch khỏi tham chiếu chứ không phải làm chưa tới.

   THƯƠNG HIỆU GIỮ NGUYÊN. Con cú là tím và xanh lá, theme-color đã là #602F8B từ khi site ra
   đời. #602F8B ở lại làm màu thương hiệu sâu; #7C3AED là lớp tương tác, sáng hơn cho nhóm trẻ.

   Contrast tính bằng công thức WCAG, không nhìn bằng mắt: 22/22 cặp light, 23/23 cặp dark,
   11/11 chip danh mục. Bốn chỗ phản trực giác được ghi comment ngay tại nơi khai báo:
     · nút chữ đen thì hover phải SÁNG lên
     · gradient có trần cứng ở --ylc-brand
     · màu chữ của tấm vé đổi CÙNG LÚC với nền
     · ring focus trên nền đậm phải là trắng
   ────────────────────────────────────────────────────────────────────────────────────────── */

:root {
  /* ── nền & mực ─────────────────────────────────────────────────────────────────────── */
  --ylc-bg: #faf5ff;           /* nền ám tím, không phải xám trung tính */
  --ylc-surface: #ffffff;
  --ylc-ink: #1e1b2e;
  --ylc-muted: #4b5563;
  --ylc-rule: #e4dcf7;
  --ylc-rail: #f0ebfa;

  /* ── thương hiệu: HAI VAI TRÒ, TÁCH RỜI ────────────────────────────────────────────────
     Bản trước chỉ có một token tím và nó vừa làm nền vừa làm chữ. Sang chế độ tối, đảo nó
     sáng lên là đúng cho vai trò "chữ" và sai hoàn toàn cho vai trò "nền": footer sẽ thành
     nền sáng mang chữ trắng. Đặt tên theo VAI TRÒ, không theo màu, thì mỗi cái đảo theo đúng
     logic của nó. */
  --ylc-deep: #602f8b;         /* MẶT NỀN TỐI mang chữ sáng: footer, hero, tấm vé */
  --ylc-deep-ink: #602f8b;     /* TÍM LÀM CHỮ trên nền sáng: tiêu đề, logo */
  --ylc-brand: #7c3aed;        /* lớp tương tác: link, viền, focus */
  --ylc-brand-soft: #ede9fe;
  /* ĐẦU SÁNG của gradient — tách khỏi --ylc-brand, và đây là lý do:
     --ylc-brand phải SÁNG lên ở chế độ tối (nó là chữ/viền trên nền tối). Nhưng đầu sáng của
     gradient là NỀN mang chữ trắng, nên nó phải đi ngược lại. Dùng chung một token thì ở dark
     gradient chạy tới #a78bfa và chữ trắng tụt còn 2.72:1.
     Trần cứng: trắng được 5.70 ở #7c3aed, chỉ còn 4.23 ở #8b5cf6 và 2.72 ở #a78bfa. */
  --ylc-grad-hi: #7c3aed;
  --ylc-on-dark: #ffffff;
  --ylc-on-dark-soft: #ddd6fe; /* hover trên nền đậm */
  --ylc-on-dark-dim: #e9e2f8;  /* tiêu đề cột footer */

  /* ── hành động & trạng thái ────────────────────────────────────────────────────────────
     CTA là xanh SÁNG với chữ ĐEN. Chữ trắng trên #16a34a chỉ được 3.30:1 — trượt. Và vì chữ
     đen, hover phải SÁNG LÊN: tối đi (#15803d) tụt xuống 4.19, cũng trượt. Ngược với thói
     quen của mọi nút chữ trắng trên web. */
  --ylc-go: #16a34a;
  --ylc-go-hi: #22c55e;
  --ylc-on-go: #000000;
  --ylc-flag: #ffb703;
  --ylc-invalid: #b3261e;
  --ylc-placeholder: #6b7280;

  /* ── chữ ───────────────────────────────────────────────────────────────────────────── */
  --ylc-fs-xs: .78rem;  --ylc-fs-sm: .88rem;  --ylc-fs-md: 1rem;
  --ylc-fs-lg: 1.125rem; --ylc-fs-xl: 1.5rem; --ylc-fs-ticket: 2rem;
  --ylc-fs-page: clamp(1.6rem, 4vw, 2.2rem);
  --ylc-fw-body: 400; --ylc-fw-med: 600; --ylc-fw-bold: 800;

  /* ── khoảng cách ───────────────────────────────────────────────────────────────────── */
  --ylc-s1: .25rem; --ylc-s2: .5rem; --ylc-s3: .75rem;
  --ylc-s4: 1rem;   --ylc-s5: 1.5rem; --ylc-s6: 2rem;

  /* ── hình & lớp ────────────────────────────────────────────────────────────────────── */
  --ylc-r: 10px; --ylc-r-sm: 6px; --ylc-r-pill: 999px;
  --ylc-z-header: 1030;
  --ylc-sh-1: 0 1px 2px rgb(16 24 40 / .06), 0 1px 3px rgb(16 24 40 / .08);
  --ylc-sh-2: 0 6px 16px rgb(16 24 40 / .12);
}

/* ── chế độ tối: KHAI BÁO, CHƯA BẬT ──────────────────────────────────────────────────────
   Không có JS nào đặt `data-theme`, nên khối này không bao giờ khớp. Nó tồn tại để đợt bật
   dark sau này KHẢ THI — mọi màu đã có cặp tối đã tính — chứ không phải để bật ngay.

   Bật thật không phải "thêm một dòng": app.css 36KB còn hardcode màu sáng khắp nơi
   (body{background:#f5f5f5;color:#404040}), và <meta name="color-scheme" content="light">
   vẫn nói với trình duyệt rằng trang này chỉ có giao diện sáng. Đó là một đợt riêng. */
:root[data-theme="dark"] {
  --ylc-bg: #14111c;        --ylc-surface: #2a243e;
  --ylc-ink: #f3f0fa;       --ylc-muted: #a9a3bd;
  --ylc-deep: #42216a;      /* VẪN TỐI — vai trò của nó là mặt nền, không phải sắc tím */
  --ylc-deep-ink: #c4b5fd;  /* vai trò chữ thì ĐẢO, vì thứ quanh nó đã tối */
  --ylc-brand: #a78bfa;     --ylc-brand-soft: #332b4d;
  --ylc-grad-hi: #5b21b6;   /* ĐI NGƯỢC --ylc-brand: đây là nền, không phải chữ (trắng 8.98) */
  --ylc-rail: #332e45;      --ylc-rule: #7a719b;
  --ylc-go: #34d399;        --ylc-go-hi: #6ee7b7;   --ylc-on-go: #000000;
  --ylc-flag: #ffcf4d;      --ylc-placeholder: #9d97b4;
  --ylc-invalid: #ff8a80;
  /* --ylc-on-dark*, --ylc-on-go, --ylc-on-flag giữ nguyên: nền chúng ngồi lên là nền tối
     (footer, hero) hoặc nền sáng (nút xanh, nút vàng) ở CẢ HAI chế độ, nên chữ không đảo. */
}

body { background: var(--ylc-bg); color: var(--ylc-ink); }
/* The band is sticky, so the first block on the page needs air under it rather than sitting
   flush against a coloured edge. */
.ylc-topbar + * { padding-top: 1.25rem; }

/* Focus nhìn thấy được trên CẢ HAI loại nền.
   Ring brand trên nền deep chỉ được 1.62:1 — gần như vô hình. Nên mọi vùng nền đậm có ring
   riêng bằng trắng (9.22:1). */
a:focus-visible, button:focus-visible, input:focus-visible, .ylc-cta:focus-visible {
  outline: 3px solid var(--ylc-brand); outline-offset: 2px;
}
.ylc-hero :where(a, button):focus-visible,
footer :where(a, button):focus-visible {
  outline-color: var(--ylc-on-dark);
}

/* ── the header band ────────────────────────────────────────────────────────────────────── */
/* Nền SÁNG, không phải dải tím.

   Dải tím làm chữ "Yolo" trong logo biến mất: cả hai đều là #602F8B, tương phản 1.00:1 — bằng
   đúng màu nền. Tấm nền trắng sau logo ở bản trước là băng dán. Viền trắng mỏng cũng không cứu
   được, vì viền bao quanh KHUNG ẢNH còn nét chữ nằm bên trong nó.

   Header sáng thì logo đọc tự nhiên ở 9.22:1, không cần sinh asset mới, và an toàn khi sau này
   bật dark mode. Màu đậm dời xuống hero và tấm vé — nơi nó không đè lên thương hiệu. */
.ylc-topbar {
  position: sticky; top: 0; z-index: var(--ylc-z-header);
  background: var(--ylc-surface);
  border-bottom: 1px solid var(--ylc-rule);
  box-shadow: var(--ylc-sh-1);
}
.ylc-topbar-in {
  max-width: 1200px; margin: 0 auto; padding: var(--ylc-s3) var(--ylc-s4);
  display: flex; align-items: center; gap: var(--ylc-s4); flex-wrap: wrap;
}
/* flex: 0 0 auto là điểm mấu chốt. Lockup là 1600x580; trong một hàng flex cạnh ô tìm kiếm
   muốn giãn, mặc định nó vẫn bị bóp còn một mẩu cú. */
.ylc-logo { display: flex; align-items: center; flex: 0 0 auto; text-decoration: none; }
/* Logo: viền trắng bám theo NÉT CHỮ, và to hơn.

   Hai lỗi của bản trước, cả hai do cùng một giả định sai — rằng nền phía sau logo sẽ luôn
   sáng vì tôi đã đặt header là trắng:

   1. Chrome auto-dark (và các tiện ích kiểu Dark Reader) đảo nền sáng thành đen ở khâu VẼ.
      `computed style` vẫn báo #ffffff, nên phép đo bằng getComputedStyle không thấy gì —
      chỉ ảnh chụp mới thấy. Header thành đen, và logo tím-trên-đen biến mất y như nó từng
      tím-trên-tím. Đổi từ nền tím sang nền trắng chỉ là đổi một giả định mong manh này lấy
      một giả định mong manh khác.
   2. 40px là quá nhỏ. Bản gốc của site để logo rộng 423px ở trang chủ; 110px là một phần tư.

   `filter: drop-shadow` bám theo KÊNH ALPHA của ảnh, nên nó vẽ viền quanh chính nét chữ và
   con cú — khác hẳn `border`/`outline`, vốn chỉ bao quanh khung ảnh hình chữ nhật và không
   giúp được gì cho chữ nằm bên trong. Xếp chồng nhiều lớp cho viền đủ dày để đọc được.

   Trên nền sáng viền trắng vô hình nên không tốn gì; trên nền tối nó là thứ duy nhất giữ cho
   logo còn đọc được. Nhờ vậy logo không còn phụ thuộc vào một nền mà nó không kiểm soát. */
.ylc-logo img {
  height: 52px; width: auto; max-width: none; object-fit: contain; display: block;
  filter:
    drop-shadow(0 0 1px #fff) drop-shadow(0 0 1px #fff)
    drop-shadow(0 0 1px #fff) drop-shadow(0 0 2px #fff);
}
/* Lớp phòng thủ thứ hai: nói với Chrome đừng auto-dark vùng này. Không thay được viền — một
   số tiện ích dark mode bỏ qua thuộc tính này — nhưng nó miễn phí. */
.ylc-logo { color-scheme: only light; }

/* KHÔNG thu nhỏ logo ở mobile nữa. 40px là hệ quả của một bố cục sai chứ không phải một
   quyết định về kích thước: ba item cùng `flex-wrap` trong một hàng, ở 390px chúng rơi thành
   BA hàng riêng — logo một hàng, ô tìm kiếm một hàng, hai link một hàng — nên header cao 154px
   và logo đứng lẻ loi giữa 268px trống bên phải nó. Thu logo lại chỉ làm chỗ trống rộng thêm.
   Bản sửa nằm ở khối mobile phía dưới: cho logo và link dùng CHUNG hàng đầu, search xuống hàng
   riêng. Hàng đầu khi đó chứa 143 + 8 + 122 = 273px, vừa trong 296px nội dung của cả màn 320px
   — nên logo giữ đúng 52px như desktop. */

.ylc-search { flex: 1 1 320px; min-width: 220px; margin: 0; }
.ylc-search .input-group { box-shadow: none; }
/* Viền mặc định #ced4da của Bootstrap chỉ được 1.49:1 trên nền trắng — dưới ngưỡng 3:1 mà
   WCAG 1.4.11 đòi cho ranh giới của một control. Viền brand được 5.70. */
.ylc-search .form-control {
  border: 2px solid var(--ylc-brand); border-right: 0;
  border-radius: var(--ylc-r-sm) 0 0 var(--ylc-r-sm);
  height: 44px; font-size: var(--ylc-fs-sm);
  color: var(--ylc-ink); background: var(--ylc-surface);
}
.ylc-search .form-control:hover { border-color: var(--ylc-deep); }
.ylc-search .form-control::placeholder { color: var(--ylc-placeholder); opacity: 1; }
.ylc-search .form-control:user-invalid { border-color: var(--ylc-invalid); }
/* Chrome ép nền vàng lên ô đã autofill và bỏ qua `background`. Chỉ inset box-shadow thắng nó. */
.ylc-search .form-control:-webkit-autofill {
  box-shadow: inset 0 0 0 100px var(--ylc-surface);
  -webkit-text-fill-color: var(--ylc-ink);
}
.ylc-search .ylc-search-btn {
  border: 2px solid var(--ylc-flag); background: var(--ylc-flag); color: var(--ylc-on-flag);
  border-radius: 0 var(--ylc-r-sm) var(--ylc-r-sm) 0;
  font-weight: var(--ylc-fw-bold); padding: 0 1.1rem; height: 44px; cursor: pointer;
}
.ylc-search .ylc-search-btn:hover { background: #e8a903; border-color: #e8a903; }
.ylc-search .ylc-search-btn:active { filter: brightness(.94); }

.ylc-topbar-links { display: flex; gap: var(--ylc-s1); align-items: center; flex: 0 0 auto; }
.ylc-topbar-links a {
  color: var(--ylc-brand); text-decoration: none;
  font-size: var(--ylc-fs-sm); font-weight: var(--ylc-fw-med);
  padding: var(--ylc-s2) var(--ylc-s3); border-radius: var(--ylc-r-sm);
}
.ylc-topbar-links a:hover { background: var(--ylc-brand-soft); color: var(--ylc-deep-ink); }

/* ── page frame ─────────────────────────────────────────────────────────────────────────── */
.ylc-page { max-width: 1200px; margin: 0 auto; padding: 1.25rem 1rem 3rem; }
.ylc-crumb {
  font-size: .82rem; color: var(--ylc-muted); margin-bottom: .75rem;
  display: flex; gap: .4rem; flex-wrap: wrap; align-items: center;
}
.ylc-crumb a { color: var(--ylc-brand); text-decoration: none; }
.ylc-crumb a:hover { text-decoration: underline; }
.ylc-h1 { font-size: clamp(1.5rem, 3.5vw, 2rem); font-weight: 700; margin: 0 0 .4rem; }
.ylc-sub { color: var(--ylc-muted); margin: 0 0 1rem; }

/* The results bar: what you are looking at and how many of it there are. */
.ylc-resultbar {
  background: var(--ylc-surface); border: 1px solid var(--ylc-rule);
  border-radius: var(--ylc-r); padding: .7rem .9rem; margin-bottom: 1rem;
  display: flex; align-items: center; gap: .75rem 1.25rem; flex-wrap: wrap;
  font-size: .88rem;
}
.ylc-resultbar strong { font-weight: 700; }

/* ── cards ──────────────────────────────────────────────────────────────────────────────── */
.ylc-card {
  background: var(--ylc-surface);
  border: 1px solid var(--ylc-rule);
  border-radius: var(--ylc-r);
  box-shadow: var(--ylc-sh-1);
}
.ylc-card:hover, .ylc-card:focus-within {
  box-shadow: var(--ylc-sh-2); border-color: var(--ylc-brand);
}

/* The horizontal result card: mark on the left, the words in the middle, the action on the
   right. Below 768px it stacks and the action goes full width, because a 44px target at the
   edge of a phone screen is not one. */
.ylc-result {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr) 184px;
  gap: 1rem; align-items: center;
  padding: 1rem;
  margin-bottom: .75rem;
}
.ylc-result-mark {
  width: 96px; height: 72px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ylc-rule); border-radius: var(--ylc-r-sm); background: #fff;
  overflow: hidden;
}
.ylc-result-mark img { max-width: 88%; max-height: 88%; object-fit: contain; }
.ylc-result-title { font-size: 1.05rem; font-weight: 700; margin: 0 0 .25rem; line-height: 1.25; }
.ylc-result-title a { color: var(--ylc-ink); text-decoration: none; }
.ylc-result-title a:hover { color: var(--ylc-brand); text-decoration: underline; }
.ylc-result-desc {
  color: var(--ylc-muted); font-size: .88rem; margin: 0 0 .5rem;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ylc-result-rail { display: grid; gap: .4rem; justify-items: stretch; text-align: center; }

/* ── chips and badges ───────────────────────────────────────────────────────────────────── */
/* Facts, and only facts. Every chip here is a number the database already holds — how many
   offers a store has, when a code was last checked. Nothing says "only 2 left" or "15 people
   are looking", because there is no stock count and no live viewer count behind either. */
.ylc-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.ylc-chip {
  background: var(--ylc-rail); color: var(--ylc-muted);
  border-radius: var(--ylc-r-pill); padding: .2rem .6rem;
  font-size: .78rem; white-space: nowrap;
}
.ylc-chip--ok { background: #e8f5e9; color: #1b5e20; }
.ylc-badge {
  display: inline-block; border-radius: var(--ylc-r-sm);
  padding: .15rem .5rem; font-size: .68rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase;
}
.ylc-badge--code { background: var(--ylc-brand); color: #fff; }
.ylc-badge--deal { background: var(--ylc-flag); color: var(--ylc-ink); }
.ylc-badge--free { background: #e8f5e9; color: #1b5e20; }

/* ── actions ────────────────────────────────────────────────────────────────────────────── */
/* Nút xanh mang chữ ĐEN, và vì thế hover phải SÁNG lên chứ không tối đi.
   Chữ trắng trên #16a34a chỉ được 3.30:1 — trượt. Chữ đen được 6.37. Nhưng khi chữ là đen thì
   tối nền đi làm tương phản TỤT: #15803d + đen còn 4.19, cũng trượt. Sáng lên #22c55e được 9.22.
   Ngược với thói quen của mọi nút chữ trắng trên web, nên ghi ra ngay đây. */
.ylc-cta, .ylc-cta:visited {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: .55rem 1.1rem;
  background: var(--ylc-go); color: var(--ylc-on-go);
  border: 1px solid var(--ylc-go); border-radius: var(--ylc-r-sm);
  font-weight: 700; font-size: .95rem; text-decoration: none; cursor: pointer;
  width: 100%;
}
.ylc-cta:hover { background: var(--ylc-go-hi); border-color: var(--ylc-go-hi); color: var(--ylc-on-go); }
.ylc-cta:active { filter: brightness(.94); }
.ylc-cta--quiet {
  background: transparent; color: var(--ylc-brand); border-color: var(--ylc-brand);
}
.ylc-cta--quiet:hover { background: var(--ylc-brand-soft); color: var(--ylc-brand); }
.ylc-cta--code {
  background: var(--ylc-brand); border-color: var(--ylc-brand);
  border-style: dashed; letter-spacing: .06em;
}
.ylc-cta--code:hover { background: var(--ylc-deep); border-color: var(--ylc-deep); }
.ylc-microcopy { font-size: .72rem; color: var(--ylc-muted); margin: 0; }

/* ── grids and rails ────────────────────────────────────────────────────────────────────── */
.ylc-grid { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.ylc-tile { padding: 1rem; text-align: center; text-decoration: none; color: inherit; display: block; }
.ylc-tile img { max-width: 100%; height: 64px; object-fit: contain; margin-bottom: .5rem; }
.ylc-tile-name { font-weight: 600; font-size: .9rem; margin: 0; }

.ylc-with-rail { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 1.25rem; align-items: start; }
.ylc-rail-box { padding: 1rem; margin-bottom: 1rem; }
.ylc-rail-box h3 { font-size: .78rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ylc-muted); margin: 0 0 .6rem; }

.ylc-section-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin: 1.75rem 0 .75rem;
}
.ylc-section-head h2, .ylc-section-head h3 { font-size: 1.15rem; font-weight: 700; margin: 0; }
.ylc-section-head a { color: var(--ylc-brand); font-size: .88rem; font-weight: 600; text-decoration: none; }
.ylc-section-head a:hover { text-decoration: underline; }

/* ── footer ─────────────────────────────────────────────────────────────────────────────── */
/* Ghi đè các selector CÓ SẴN trong app.css, không sửa footer.twig.

   Trước: footer #095400 xanh lá, header tím, hover #ff5722 cam — ba hệ màu không liên quan trên
   cùng một trang. Tiêu đề cột #b3b3b3 trên nền đậm chỉ được 4.40:1, dưới ngưỡng 4.5.

   Khối .ylc-footer* của bản trước đã bị xoá: nó là 13 dòng CSS cho những class mà footer.twig
   chưa bao giờ dùng. */
footer { background: var(--ylc-deep); color: var(--ylc-on-dark); }
footer p.title,
footer .copyright { color: var(--ylc-on-dark-dim); }            /* 7.33 (trước 4.40) */
footer a { color: var(--ylc-on-dark); }                          /* 9.22 */
footer a:hover { color: var(--ylc-on-dark-soft); }               /* 6.64 (trước cam #ff5722) */
footer .company-info .content { color: var(--ylc-on-dark); }

/* Thanh chân trang.

   app.css:390 ghim `footer .footer-cl{max-width:20%}` — con số đó được chọn cho NĂM cột. Giờ
   lưới chỉ còn bốn cột link (Follow Us và Company Information đã xuống thanh dưới), nên 20%
   sẽ bỏ trống đúng một phần năm bên phải. 25% là con số khớp với số cột hiện tại.
   PHẢI bọc trong min-width. app.css:491 đặt 50% trong `@media (max-width:768px)`, nhưng media
   query không cộng thêm specificity: `footer .footer-cl` ở redesign.css cùng 0,2,0 và nạp sau
   nên sẽ đè cả rule mobile đó. Đo thực tế lúc chưa bọc: 390px cho bốn cột 98px nằm cùng một
   hàng, chữ bị cắt. Bọc lại thì mobile trả về 2×2 như app.css định. */
@media (min-width: 768.02px) {
  footer .footer-cl { max-width: 25%; }
}

footer .ylc-footer-base {
  border-top: 1px solid rgb(255 255 255 / .18);
  margin-top: var(--ylc-s4);
  padding-top: var(--ylc-s4);
  /* footer chỉ có min-height, không có padding-bottom, nên dòng cuối của khối pháp nhân
     chạm sát mép dưới trang. Trước khi dời xuống đây thì khối đó nằm giữa cột nên không lộ. */
  padding-bottom: var(--ylc-s5);
  row-gap: var(--ylc-s4);
}
/* p.title trong app.css có margin-top 2rem — đúng cho đầu một cột, thừa ngay dưới một đường kẻ. */
footer .ylc-footer-base p.title { margin: 0 0 var(--ylc-s3); white-space: normal; }

/* 7 icon cần ~288px. Trong ranh 228px của cột cũ chúng phải xuống hai hàng; ở đây cột lg-4
   rộng ~372px nên vừa đúng một hàng. flex-wrap giữ cho mobile hẹp vẫn xuống hàng gọn. */
footer .ylc-social-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ylc-s2); }
footer .ylc-social-row a { display: inline-flex; margin: 0; }
footer .ylc-social-row svg { display: block; }

/* Đường kẻ và khoảng đệm giờ nằm ở .ylc-footer-base bao ngoài, không phải ở riêng khối này. */
footer .ylc-footer-base .company-info { border-top: 0; margin-top: 0; padding-top: 0; }

/* Neo hai đầu thanh đáy.
   Lúc để cả hai khối dồn trái, đo ở 1280px: dòng dài nhất kết thúc ở 715px rồi trống tới mép
   phải 1204px — 490px, tức 43% bề ngang thanh, nằm im. Một thanh chạm được cả hai mép đọc ra
   là có bố cục; một thanh chỉ bám mép trái đọc ra là bị lỗi.
   order-lg-* đảo vị trí ở desktop mà không đổi thứ tự DOM, nên mobile vẫn là Follow Us trước
   rồi mới tới khối pháp nhân. */
@media (min-width: 992px) {
  footer .ylc-footer-social { text-align: right; }
  footer .ylc-social-row { justify-content: flex-end; }
}

/* ── hero ───────────────────────────────────────────────────────────────────────────────── */
/* Nơi màu đậm chuyển tới sau khi rời khỏi header. Gradient dừng ở --ylc-brand: chữ trắng còn
   5.70 ở đó, nhưng chỉ còn 4.23 ở #8b5cf6 và 2.72 ở #a78bfa. Đây chính là thứ người sau sẽ
   "làm sáng thêm cho yolo" rồi phá — trần là cứng. */
.ylc-hero {
  background: linear-gradient(135deg, var(--ylc-deep), var(--ylc-grad-hi));
  color: var(--ylc-on-dark);
  padding: var(--ylc-s6) var(--ylc-s4);
  text-align: center;
}
.ylc-hero-in { max-width: 1200px; margin: 0 auto; }
.ylc-hero .text-title-home-1 {
  font-size: var(--ylc-fs-page); font-weight: var(--ylc-fw-bold);
  color: var(--ylc-on-dark); margin: 0 0 var(--ylc-s2); line-height: 1.15;
}
.ylc-hero .text-title-home-2 {
  font-size: var(--ylc-fs-md); color: var(--ylc-on-dark);
  opacity: .92; margin: 0; max-width: 62ch; margin-inline: auto;
}

/* ── responsive ─────────────────────────────────────────────────────────────────────────── */
@media (max-width: 991.98px) {
  .ylc-with-rail { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 767.98px) {
  .ylc-result { grid-template-columns: 64px minmax(0, 1fr); }
  .ylc-result-mark { width: 64px; height: 56px; }
  .ylc-result-rail { grid-column: 1 / -1; }

  /* Masthead mobile: hàng 1 = logo (trái) + link (phải), hàng 2 = ô tìm kiếm hết bề ngang.
     `order` sắp lại thứ tự hiển thị mà không đụng thứ tự DOM, nên trình đọc màn hình và phím
     Tab vẫn đi logo → tìm kiếm → link như cũ.
     `flex: 1 0 100%` là thứ đẩy ô tìm kiếm xuống hàng riêng; base 320px của nó không đủ để
     tự xuống hàng một cách chắc chắn ở mọi bề rộng. */
  .ylc-topbar-in { padding: .5rem .75rem; gap: .5rem; }
  .ylc-logo { order: 1; }
  .ylc-topbar-links { order: 2; margin-left: auto; }
  .ylc-search { order: 3; flex: 1 0 100%; min-width: 0; }
  .ylc-page { padding: 1rem .75rem 2.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* ── result lists ───────────────────────────────────────────────────────────────────────── */
.ylc-results { display: grid; gap: .75rem; }
.ylc-results .ylc-result { margin-bottom: 0; }
.ylc-result-body { min-width: 0; }
.ylc-empty { padding: 2rem 1.25rem; text-align: center; }
.ylc-empty-title { font-weight: 700; margin: 0 0 .25rem; }

/* Bootstrap's pagination sits on the grey ground now, so it needs its own surface. */
.pagination--simple .pagination { margin: 0; }
.pagination--simple .page-link { color: var(--ylc-brand); border-color: var(--ylc-rule); }
.pagination--simple .page-item.active .page-link {
  background: var(--ylc-brand); border-color: var(--ylc-brand); color: #fff;
}

/* The side rail: related categories, and anything else that is navigation rather than result. */
.lp, .bi .shadow-sm {
  background: var(--ylc-surface); border: 1px solid var(--ylc-rule);
  border-radius: var(--ylc-r); box-shadow: var(--ylc-sh-1); padding: 1rem;
}
.lp .title, .bi .title {
  font-size: .78rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ylc-muted); margin: 0 0 .6rem; text-align: left;
}
.lp .links p { margin: 0; }
.lp .links a {
  display: block; padding: .4rem 0; color: var(--ylc-ink); text-decoration: none;
  border-bottom: 1px solid var(--ylc-rule); font-size: .9rem;
}
.lp .links a:hover { color: var(--ylc-brand); }

/* ── the store page ─────────────────────────────────────────────────────────────────────── */
/* CSS only. Every coupon row on this page carries the affiliate click path —
   `js-btn_deal_click`, `data-affiliate_url`, `data-click-log-flag` — and the tab filter works
   by toggling `js-filter-coupon-type-*` classes. Rewriting this markup to reach a nicer
   structure would put the revenue path and the filter at risk to win a layout argument. So the
   existing classes are restyled in place and not one hook is moved. */

.coupon-filter {
  display: flex; gap: .4rem; flex-wrap: wrap;
  background: var(--ylc-surface); border: 1px solid var(--ylc-rule);
  border-radius: var(--ylc-r); padding: .5rem; margin-bottom: 1rem;
}
.coupon-filter .filter-item {
  padding: .45rem .9rem; border-radius: var(--ylc-r-pill); cursor: pointer;
  font-size: .88rem; font-weight: 600; color: var(--ylc-muted); border: 1px solid transparent;
  white-space: nowrap;
}
.coupon-filter .filter-item:hover { background: var(--ylc-rail); color: var(--ylc-ink); }
.coupon-filter .filter-item-click,
.coupon-filter .filter-item.active {
  background: var(--ylc-brand); color: #fff;
}

/* One coupon.
   An earlier version of this block made `.cp` a three-column grid on the assumption that
   .deal-info, .deal-desc and .get-code were its direct children. They are not — .get-code is
   nested inside .deal-desc — so the grid placed whatever it found and the description wrapped
   one word per line with the code button sitting on top of it. On a page whose entire purpose
   is showing a code, that is worse than the layout it replaced.

   What is left is surface only: the card reads as a card, and every position stays where the
   existing stylesheet puts it. The structural version needs the real DOM read first. */
.cp {
  background: var(--ylc-surface) !important;
  border: 1px solid var(--ylc-rule);
  border-radius: var(--ylc-r) !important;
  box-shadow: var(--ylc-sh-1) !important;
  margin-bottom: .75rem;
}
.cp:hover, .cp:focus-within { box-shadow: var(--ylc-sh-2) !important; border-color: var(--ylc-brand); }

/* The real structure, read out of the rendered page rather than assumed:
       .cp > .deal > ( .deal-info.benefit-code , .deal-desc )
   and .get-code is INSIDE .deal-desc, not a sibling of it. The first attempt put a
   three-column grid on .cp, found children that were not there, and wrapped the description
   one word per line with the code button on top of it.

   So the grid goes on .deal for the two columns that really are siblings, and .deal-desc gets
   its own two-column grid to lift .get-code out to the right. No markup moves, so every
   `js-btn_deal_click` and every `data-affiliate_url` stays exactly where it was. */
.cl .cp .deal {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: 1rem; align-items: center;
  padding: 1rem;
}
.cp .deal-info {
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 76px; padding: .5rem;
  background: var(--ylc-brand-soft); border-radius: var(--ylc-r-sm);
  color: var(--ylc-brand); font-weight: 800; line-height: 1.15;
}
.cp .deal-info .discount { font-size: 1.3rem; }

/* .deal-desc: KHÔNG dựng lưới ở đây.
   `.get-code` trong app.css là `position:absolute; right:20px; top:50%`, và các con của nó
   cũng tuyệt đối — đó là widget reveal mã, animation dựa vào chính cách định vị đó. Phần tử
   tuyệt đối không tham gia lưới, nên đặt `grid-column` cho nó là vô nghĩa; mà ép nó vào lưới
   thì phá thứ đang chạy được để đổi lấy một tranh cãi về bố cục.

   Nên chỉ sửa đúng một thứ: `margin-left:103px` từng chừa chỗ cho `.deal-info` hồi nó còn
   tuyệt đối. Nay `.deal-info` là một ô lưới thật, khoảng chừa đó thành thừa và cộng dồn.
   `padding-right:235px` GIỮ NGUYÊN — nó vẫn đang chừa chỗ cho `.get-code` tuyệt đối. */
.cl .cp .deal .deal-desc { margin-left: 0; min-width: 0; }

.cl .cp .deal .deal-desc h2.title { margin: 0 0 .2rem; font-size: 1.02rem; line-height: 1.3; }
.cl .cp .deal .deal-desc h2.title a { color: var(--ylc-ink); font-weight: 700; text-decoration: none; }
.cl .cp .deal .deal-desc h2.title a:hover { color: var(--ylc-brand); text-decoration: underline; }

@media (max-width: 767.98px) {
  .cl .cp .deal { grid-template-columns: 84px minmax(0, 1fr); gap: .75rem; padding: .85rem; }
  .cl .cp .deal .deal-info { min-height: 58px; }
  .cl .cp .deal .deal-info .discount { font-size: 1.25rem; }
}

.brand-coupon-info {
  background: var(--ylc-surface); border: 1px solid var(--ylc-rule);
  border-radius: var(--ylc-r); padding: 1rem;
}
.brand-coupon-info .merchant-data { font-weight: 700; color: var(--ylc-ink); }



/* ── a pre-existing overflow, fixed while here ──────────────────────────────────────────── */
/* At 390px the store page scrolled sideways by 12px: a Bootstrap `.row` inside a container
   that does not pay for its negative gutter. It predates this branch — the layer below has
   several rows written without a `.container` around them — but a page that slides under the
   thumb is a page that feels broken, and it costs one rule to stop. */
@media (max-width: 767.98px) {
  /* `--bs-gutter-x: 0` là bản sửa thật. `body{overflow-x:hidden}` đi kèm nó ở bản trước đã
     được gỡ: nó không sửa gì cả, chỉ giấu — và sẽ giấu luôn mọi lỗi tràn ngang về sau, đúng
     lúc người ta cần nhìn thấy. */
  .container-codes .row, .container-cat .row { --bs-gutter-x: 0; }
}


/* ── tấm vé ─────────────────────────────────────────────────────────────────────────────── */
/* Thay cho nhiếp ảnh. Site không có ảnh sản phẩm — 34/34 ảnh trang danh mục là logo store
   150x150 — nên độ sáng của thẻ phải đến từ màu và chữ.

   ĐỘ ĐẶC HIỆU PHẢI KHỚP, không chỉ "nạp sau". app.css có
       .cl .cp .deal .benefit-code { color:#019a04 }        (0,4,0)
       .cl .cp .deal .deal-info    { position:absolute; ... } (0,4,0)
   Viết `.cp .deal-info` (0,2,0) thì thua cả hai: chữ giữ nguyên xanh lá trên nền tím — đo được
   2.47:1 ở đầu đậm và 1.53:1 ở đầu sáng, trượt nặng — và khối vẫn bị định vị tuyệt đối nên
   grid không xếp được nó. Đây đúng là lỗi mà cả đợt này sinh ra để sửa, chỉ đổi chỗ xuất hiện.

   Nên mọi rule dưới đây dùng chuỗi tổ tiên đầy đủ, và màu chữ đổi CÙNG LÚC với nền. */
.cl .cp .deal .deal-info {
  position: static;                 /* gỡ absolute để grid xếp được */
  width: auto; height: auto; min-height: 88px; margin: 0;
  left: auto; top: auto;
  border-right: 0;
  border-radius: var(--ylc-r-sm);
  background: linear-gradient(135deg, var(--ylc-deep), var(--ylc-grad-hi));
  padding: var(--ylc-s3) var(--ylc-s2);
}
.cl .cp .deal .deal-info,
.cl .cp .deal .deal-info .discount,
.cl .cp .deal .benefit-code {
  color: var(--ylc-on-dark);        /* 9.22 ở đầu đậm, 5.70 ở đầu sáng */
}
.cl .cp .deal .deal-info .discount { font-size: var(--ylc-fs-ticket); line-height: 1.05; }

/* Cạnh khía: một ô cao 16px chứa hõm tròn bán kính 5px ở mép trái, LẶP theo trục dọc.
   `repeat-y` là phần làm nên cạnh răng cưa — một radial-gradient đơn lẻ chỉ cho đúng MỘT hõm
   ở giữa, trông như lỗi render chứ không như cuống vé. */
.cl .cp .deal .deal-info {
  --notch: radial-gradient(circle 5px at 0 8px, #0000 98%, #000 100%);
  -webkit-mask: var(--notch) 0 0 / 100% 16px repeat-y;
          mask: var(--notch) 0 0 / 100% 16px repeat-y;
}
@supports not (mask: radial-gradient(circle 5px at 0 0, #000, #000)) {
  .cl .cp .deal .deal-info { -webkit-mask: none; mask: none; }
}

/* ── chip danh mục: ĐÃ GỠ ──────────────────────────────────────────────────────────────────
   Ở đây từng có mười một rule màu, ánh xạ cat_id sang nền pastel. Đếm trên dữ liệu thật thì
   không rule nào từng khớp:

       10/10 danh mục đang bật  ->  0 store
       5183/5999 store (86%)    ->  cat_id = 1, một category KHÔNG tồn tại
       810 store (13.5%)        ->  cat_id = 87 "Adult 18 and over"

   Tức là chip hoặc không hiện, hoặc dán nhãn giới hạn độ tuổi lên thẻ mua sắm thường. Giữ lại
   thì là trang trí giả làm thông tin — đúng thứ mà phần I14 của kế hoạch cấm.

   Nếu sau này dữ liệu danh mục được dọn (xem ghi chú trong PR), dựng lại bằng cách ánh xạ theo
   cat_id chứ không theo tên: tên đổi được trong admin, id thì không. */

/* ── vô hiệu hoá ────────────────────────────────────────────────────────────────────────── */
/* .ylc-cta là thẻ <a>, và <a> KHÔNG nhận :disabled — selector đó chỉ áp cho
   button/input/select/textarea. Cả hai dạng cùng tồn tại trên site nên khai báo cả hai.
   Lưu ý pointer-events:none chặn chuột chứ không chặn bàn phím; muốn một liên kết thật sự chết
   thì phải bỏ href. Đợt này không có CTA nào ở trạng thái vô hiệu hoá — đây là quy ước dự phòng. */
.ylc-cta[aria-disabled="true"] {
  background: var(--ylc-rail); color: var(--ylc-muted);
  border-color: var(--ylc-rule); cursor: not-allowed; pointer-events: none;
}
.ylc-cta:disabled {
  background: var(--ylc-rail); color: var(--ylc-muted);
  border-color: var(--ylc-rule); cursor: not-allowed;
}

/* ── tiêu đề trang store ─────────────────────────────────────────────────────────────────── */
/* Thẻ đổi từ h3 sang h1 để sửa thứ bậc bị đảo — trước đó tiêu đề trang là h3 còn 5 tiêu đề
   mục bên dưới là h2. Nhưng h1 mặc định của Bootstrap là 40px, nhảy hẳn so với 28px cũ, nên
   cỡ chữ do token quyết chứ không do mặc định. */
.ylc-page-title { font-size: var(--ylc-fs-page); font-weight: var(--ylc-fw-bold); line-height: 1.25; }

/* Hai thẻ dưới đây cũng vừa đổi từ p/h1 sang h1/h2. Giữ nguyên cỡ chữ mà app.css đã đặt cho
   class của chúng, để việc sửa thứ bậc HTML không kéo theo thay đổi giao diện. */
.blog-container .content-container h1.content-title { font-size: 32px; font-weight: 700; margin: 0 0 .5rem; }
.blog-container .top-content-container .top-panel .bottom-context h2 {
  font-size: 32px; font-weight: 700; color: #fff; margin-bottom: 6px; max-width: 100%;
}
