/* Be Vietnam Pro (SIL OFL 1.1) — self-hosted subset, mirrored 2026-09-07 from fonts.gstatic.com.
   Only vietnamese + latin subsets at 400/500/600/700; no CDN dependency at runtime. */
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/bevietnampro-400-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;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/bevietnampro-400-vietnamese.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/bevietnampro-500-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;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/bevietnampro-500-vietnamese.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/bevietnampro-600-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;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/bevietnampro-600-vietnamese.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/bevietnampro-700-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;}
@font-face{font-family:'Be Vietnam Pro';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/bevietnampro-700-vietnamese.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}


/* Josefin Sans (SIL OFL 1.1) — self-hosted variable subset, mirrored 2026-09-09 (see fonts/josefin.css).
   Display face: echoes the geometric "GATE" letterforms of the logo. latin + vietnamese, wght 600–700. */
@font-face{font-family:'Josefin Sans';font-style:normal;font-weight:600 700;font-display:swap;src:url('/fonts/josefinsans-var-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;}
@font-face{font-family:'Josefin Sans';font-style:normal;font-weight:600 700;font-display:swap;src:url('/fonts/josefinsans-var-vietnamese.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}

/* Manrope (SIL OFL 1.1) — self-hosted variable subset, mirrored 2026-09-14 from fonts.gstatic.com
   (css2?family=Manrope:wght@400..800, v20). Copyright 2018 The Manrope Project Authors.
   Toàn văn giấy phép đi kèm: /fonts/OFL-Manrope.txt. Cũng có ở /fonts/manrope.css.
   Display face của bộ nhận diện "Đá vôi": dấu tiếng Việt to và cân hơn Josefin ở cỡ tiêu đề.
   latin + vietnamese, wght 400–800 (dùng 700 cho nhãn, 800 cho tiêu đề). */
@font-face{font-family:'Manrope';font-style:normal;font-weight:400 800;font-display:swap;src:url('/fonts/manrope-var-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;}
@font-face{font-family:'Manrope';font-style:normal;font-weight:400 800;font-display:swap;src:url('/fonts/manrope-var-vietnamese.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;}

/* ============================================================================================
   The Gate — design tokens. Theme "the-gate" approved by Thắng 2026-09-09 (theme-the-gate.html):
   every colour is measured from the real logo — coral (identity), teal + slate (sea), sun yellow (season
   labels), cream canvas, ink from the wave shadow. Replaces the executor's invented pine/amber system.
   No dark mode in Wave 1 (product fabric colours read wrong on dark grounds).
   Contrast notes (WCAG AA, checked 09/09): pure coral #F04F32 is 3.6:1 on white — used only for accents,
   borders, focus ring and the hero; any FILL with white text uses --tg-brand-strong (4.6:1) and any SMALL
   coral text on light ground uses --tg-brand-ink (5.9:1). Small teal links use --tg-link (5.9:1 on cream).
   ============================================================================================ */
:root{
  /* ══ NGUỒN ĐỊNH NGHĨA TOKEN CHUẨN — bộ nhận diện "Đá vôi", Thắng chốt 14.09.2026 ══
     Mọi token --tg-* bên dưới chỉ TRỎ về nhóm này; không token nào bị định nghĩa hai
     lần với hai giá trị khác nhau nữa (lỗi cũ: --tg-radius khai 10px rồi 6px).
     Tên --tg-* giữ nguyên hết nên không một chỗ dùng nào phải sửa. */

  /* nền & bề mặt */
  --nen:#EFEFEA; --nen-2:#E7E7E0; --mat:#FFFFFF;
  /* chữ */
  --muc:#15181A; --muc-2:#4A5052; --muc-3:#5F6567;
  /* màu hành động: cam biển hiệu cửa hàng. Mỗi vùng một hành động chính. */
  --nhan:#C9351B; --nhan-dam:#A82A12; --nhan-chu:#B02E16; --nhan-mo:#F6E7E2; --nhan-rat-mo:#FBF2EF;
  /* đường kẻ — 1px. --ke-dam dùng cho viền điều khiển (cần >=3:1 với nền). */
  --ke:#DEDED6; --ke-nhat:#E8E8E1; --ke-dam:#767C77;
  /* khối tối */
  --toi:#171A18; --toi-muc:#F4F3ED; --toi-muc-2:#AEB3AA;
  /* trạng thái hàng — màu ngữ nghĩa, KHÔNG phải màu nhấn.
     IN_STOCK "Còn hàng" · LOW "Còn ít" · OUT "Hết" · UNKNOWN "Chưa rõ" — nghĩa và
     nhãn là hợp đồng dữ liệu, nhận diện chỉ đổi màu và kiểu chữ. */
  --con-hang:#2C6A3F; --con-hang-mo:#E3EDE6; --con-hang-ke:#5E8C72;
  --sap-het:#7A4E0F;  --sap-het-mo:#F6EEDF;  --sap-het-ke:#9C7B46;
  --het:#5F6567; --chua-ro:#5F6567;
  /* nền tảng ngoài */
  --zalo:#0068FF; --zalo-chu:#0057D9;
  /* chữ */
  --f-hien-thi:'Manrope','Be Vietnam Pro',system-ui,sans-serif;
  --f-noi-dung:'Be Vietnam Pro','Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  /* hình dạng */
  --bo:3px; --bo-nho:2px;

  /* ══ LỚP ÁNH XẠ — mọi tên --tg-* cũ giữ nguyên và luôn có giá trị ══ */
  --tg-bg:var(--nen); --tg-surface:var(--mat); --tg-surface-2:var(--nen-2);
  --tg-line:var(--ke); --tg-line-2:var(--ke-nhat);
  --tg-ink:var(--muc); --tg-ink-2:var(--muc-2); --tg-ink-3:var(--muc-3);
  --tg-brand:var(--nhan); --tg-brand-strong:var(--nhan); --tg-brand-hover:var(--nhan-dam);
  --tg-brand-ink:var(--nhan-chu); --tg-brand-soft:var(--nhan-mo); --tg-brand-tint:var(--nhan-rat-mo);
  /* teal ở lại trong logo: --tg-sea* trở thành màu tương tác duy nhất = cam nhấn */
  --tg-sea:var(--nhan-chu); --tg-sea-hover:var(--nhan-dam); --tg-sea-soft:var(--nhan-mo);
  --tg-slate:var(--muc-2); --tg-link:var(--nhan-chu);
  /* vàng ở lại trong logo: --tg-warm* trở thành nhóm màu cảnh báo/LOW */
  --tg-warm:var(--sap-het-ke); --tg-warm-ink:var(--sap-het); --tg-warm-soft:var(--sap-het-mo);
  --tg-ok:var(--con-hang); --tg-low:var(--sap-het); --tg-out:var(--het); --tg-warn:var(--nhan-chu);
  --tg-font-display:var(--f-hien-thi);
  --tg-font-body:var(--f-noi-dung);
  /* thang chữ: gộp giá trị đang có hiệu lực từ khối :root thứ hai (dòng ~528 cũ) */
  --tg-fs-2xs:.75rem; --tg-fs-xs:.875rem; --tg-fs-sm:.875rem; --tg-fs-md:1rem; --tg-fs-lg:1.125rem;
  --tg-fs-xl:clamp(1.375rem,1.1rem + 1.2vw,1.75rem);
  --tg-fs-2xl:clamp(1.75rem,1.3rem + 2vw,2.5rem);
  --tg-fs-3xl:clamp(2rem,1.4rem + 3vw,3.25rem);
  --tg-lh-tight:1.25; --tg-lh-body:1.5;
  --tg-s1:4px; --tg-s2:8px; --tg-s3:12px; --tg-s4:16px; --tg-s5:24px; --tg-s6:32px; --tg-s7:48px; --tg-s8:64px;
  --tg-radius:var(--bo); --tg-radius-sm:var(--bo); --tg-radius-pill:var(--bo);
  --tg-shadow:none;   /* phân tách bằng kẻ 1px, không bằng bóng */
  --tg-touch:44px; --tg-wrap:1160px;
}
*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--tg-bg);color:var(--tg-ink);font-family:var(--tg-font-body);
  font-size:var(--tg-fs-md);line-height:var(--tg-lh-body);overflow-x:hidden}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
h1,h2,h3{line-height:var(--tg-lh-tight);letter-spacing:-.01em;margin:0 0 var(--tg-s3)}
/* Josefin Sans for page + section titles only (geometric, like the GATE wordmark). It sits high on its
   line and has a small x-height, so it gets a touch more size and open tracking; body copy stays Be Vietnam Pro. */
h1,h2{font-family:var(--tg-font-display);letter-spacing:.005em;line-height:1.2;padding-top:.08em}
h1{font-size:var(--tg-fs-2xl);font-weight:700}
h2{font-size:var(--tg-fs-xl);font-weight:600}
h3{font-size:var(--tg-fs-lg);font-weight:600}
p{margin:0 0 var(--tg-s4)}
.wrap{max-width:var(--tg-wrap);margin:0 auto;padding:0 var(--tg-s4)}
.muted{color:var(--tg-ink-2);font-size:var(--tg-fs-sm)}
.meta{color:var(--tg-ink-3);font-size:var(--tg-fs-xs)}
.skip{position:absolute;left:-9999px;top:0;background:var(--tg-brand-strong);color:#fff;padding:var(--tg-s3);z-index:99}
.skip:focus{left:0}
:focus-visible{outline:3px solid var(--tg-brand);outline-offset:2px}

/* ---------- header / nav ---------- */
.hdr{background:var(--tg-surface);border-bottom:1px solid var(--tg-line);position:sticky;top:0;z-index:20}
.hdr .wrap{display:flex;align-items:center;gap:var(--tg-s4);min-height:56px}
/* real logo: triangle mark + "the GATE" wordmark, vectorised from the brand file 09/09 (public/brand/) */
.logo{display:inline-flex;align-items:center;flex:0 0 auto;text-decoration:none;min-height:var(--tg-touch)}
.logo img{height:34px;width:auto;display:block}
.nav{display:flex;gap:var(--tg-s1);overflow-x:auto;scrollbar-width:none;flex:1 1 auto}
.nav::-webkit-scrollbar{display:none}
.nav a{white-space:nowrap;text-decoration:none;color:var(--tg-ink-2);font-size:var(--tg-fs-sm);font-weight:500;
  padding:var(--tg-s2) var(--tg-s3);border-radius:var(--tg-radius-pill);min-height:var(--tg-touch);display:inline-flex;align-items:center}
.nav a:hover,.nav a[aria-current="page"]{background:var(--tg-brand-soft);color:var(--tg-brand-ink)}
/* search = sea colour (teal outline), so coral stays reserved for the primary action */
.hdr .srch{flex:0 0 auto;text-decoration:none;font-size:var(--tg-fs-sm);color:var(--tg-link);font-weight:600;
  border:1.5px solid var(--tg-sea);border-radius:var(--tg-radius-pill);padding:var(--tg-s2) var(--tg-s4);min-height:var(--tg-touch);display:inline-flex;align-items:center}
.hdr .srch:hover{background:var(--tg-sea-soft)}

/* ---------- breadcrumbs ---------- */
.crumbs{font-size:var(--tg-fs-xs);color:var(--tg-ink-3);padding:var(--tg-s3) 0 0;display:flex;gap:var(--tg-s2);flex-wrap:wrap}
.crumbs a{text-decoration:none;color:var(--tg-ink-2)}
.crumbs a:hover{text-decoration:underline}

/* ---------- notices ---------- */
.notice{background:var(--tg-surface-2);border:1px solid var(--tg-line);border-radius:var(--tg-radius);
  padding:var(--tg-s3) var(--tg-s4);color:var(--tg-ink-2);font-size:var(--tg-fs-sm);margin:var(--tg-s3) 0}
.notice strong{color:var(--tg-ink)}
.stalebanner{position:fixed;left:0;right:0;bottom:0;z-index:30;background:var(--tg-warm-soft);
  border-top:1px solid var(--tg-line);color:var(--tg-warm-ink);font-size:var(--tg-fs-sm);text-align:center;
  padding:var(--tg-s3) var(--tg-s4) calc(var(--tg-s3) + env(safe-area-inset-bottom))}
/* fixed, so revealing it after the freshness check can never move the page (CLS) */
.stalebanner a{color:inherit;font-weight:600;margin-left:var(--tg-s2);white-space:nowrap}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--tg-s2);min-height:var(--tg-touch);
  padding:var(--tg-s3) var(--tg-s5);border-radius:var(--tg-radius);font-weight:600;font-size:var(--tg-fs-sm);
  text-decoration:none;border:1px solid transparent;cursor:pointer;background:none}
.btn-primary{background:var(--tg-brand-strong);color:#fff}   /* strong coral: 4.6:1 with white 14px text */
.btn-primary:hover{background:var(--tg-brand-hover)}
.btn-outline{border-color:var(--tg-sea);color:var(--tg-link);background:var(--tg-surface)}
.btn-outline:hover{background:var(--tg-sea-soft);border-color:var(--tg-sea-hover)}
.btn-block{width:100%}
.btn[aria-disabled="true"]{opacity:.55;pointer-events:none}

/* ---------- home hero ---------- */
/* hero = sea-soft wash (the wave in the logo) with a coral rule on top; kicker in sun yellow */
.hero{background:linear-gradient(180deg,var(--tg-sea-soft),var(--tg-bg));border-radius:var(--tg-radius);
  padding:var(--tg-s7) var(--tg-s5);margin:var(--tg-s5) 0;border:1px solid var(--tg-line-2);border-top:4px solid var(--tg-brand);position:relative;overflow:hidden}
.hero::after{content:"";position:absolute;right:-40px;bottom:-60px;width:220px;height:220px;opacity:.16;pointer-events:none;
  background:url('/brand/the-gate-mark.svg') no-repeat center/contain}
.hero>*{position:relative}
.hero .kicker{display:inline-block;background:var(--tg-warm-soft);color:var(--tg-warm-ink);border-radius:var(--tg-radius-pill);
  padding:var(--tg-s1) var(--tg-s3);font-size:var(--tg-fs-xs);font-weight:600;letter-spacing:.02em}
.hero h1{font-size:var(--tg-fs-3xl);margin:var(--tg-s3) 0 var(--tg-s3);max-width:20ch}
.hero p{max-width:56ch;color:var(--tg-ink-2)}
.hero .cta{display:flex;gap:var(--tg-s3);flex-wrap:wrap;margin-top:var(--tg-s4)}

.sec{margin:var(--tg-s7) 0}
.sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--tg-s4);margin-bottom:var(--tg-s4)}
.sec-head a{font-size:var(--tg-fs-sm);color:var(--tg-link);font-weight:600;text-decoration:none;white-space:nowrap}

/* ---------- cards grid ---------- */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:var(--tg-s4)}
@media(min-width:720px){.grid{grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:var(--tg-s5)}}
.card{background:var(--tg-surface);border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);overflow:hidden;
  display:flex;flex-direction:column}
.card .im{display:block;aspect-ratio:4/5;background:var(--tg-surface-2);overflow:hidden}
.card .im img{width:100%;height:100%;object-fit:cover}
.card .noimg{width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:var(--tg-ink-3);
  font-size:var(--tg-fs-xs);text-align:center;padding:var(--tg-s3)}
.card .b{padding:var(--tg-s3);display:flex;flex-direction:column;gap:var(--tg-s1);flex:1}
.card .n{font-size:var(--tg-fs-sm);font-weight:600;text-decoration:none;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;min-height:2.6em}
.card .br{font-size:var(--tg-fs-xs);color:var(--tg-ink-2)}
.card .p{font-size:var(--tg-fs-md);font-weight:700;margin-top:var(--tg-s1)}
.card .sizes{display:flex;gap:var(--tg-s1);flex-wrap:wrap;margin-top:var(--tg-s1)}
.card .sizes span{font-size:10px;border:1px solid var(--tg-line);border-radius:var(--tg-radius-sm);
  padding:1px 5px;color:var(--tg-ink-2)}
.card .stores{display:flex;gap:var(--tg-s3);margin-top:auto;padding-top:var(--tg-s2);font-size:10px;color:var(--tg-ink-3)}
.card .stores span{display:inline-flex;align-items:center;gap:3px}
.card .cardcta{font-size:var(--tg-fs-xs);color:var(--tg-brand-ink);font-weight:600;text-decoration:none;margin-top:var(--tg-s2)}
.newin{display:inline-block;background:var(--tg-warm-soft);color:var(--tg-warm-ink);border-radius:var(--tg-radius-pill);
  padding:1px 8px;font-size:10px;font-weight:600;align-self:flex-start}

/* availability dots — neutral until the runtime guard says the snapshot is fresh */
.dot{width:8px;height:8px;border-radius:50%;background:var(--tg-out);display:inline-block;flex:0 0 auto}
.dot[data-tg-avail="IN_STOCK"]{background:var(--tg-ok)}
.dot[data-tg-avail="LOW"]{background:var(--tg-low)}
.dot[data-tg-avail="OUT"],.dot[data-tg-avail="UNKNOWN"]{background:var(--tg-out)}

/* ---------- availability block ---------- */
.avail{background:var(--tg-surface-2);border:1px solid var(--tg-line);border-radius:var(--tg-radius);padding:var(--tg-s4);margin:var(--tg-s4) 0}
.avail h2{font-size:var(--tg-fs-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--tg-ink-2);margin-bottom:var(--tg-s3)}
.avail .row{display:flex;justify-content:space-between;align-items:center;gap:var(--tg-s3);
  padding:var(--tg-s2) 0;border-top:1px solid var(--tg-line-2)}
.avail .row:first-of-type{border-top:0}
.avail .st{font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-ink-2)}
.avail .st[data-tg-avail="IN_STOCK"]{color:var(--tg-link)}   /* deep teal: 5.4:1 on surface-2 (Lighthouse a11y 09/09); dots keep --tg-ok */
.avail .st[data-tg-avail="LOW"]{color:var(--tg-low)}
.avail .st[data-tg-avail="OUT"],.avail .st[data-tg-avail="UNKNOWN"]{color:var(--tg-out)}

/* ---------- PDP ---------- */
.pdp{display:grid;gap:var(--tg-s5);margin:var(--tg-s4) 0 var(--tg-s8)}
@media(min-width:860px){.pdp{grid-template-columns:minmax(0,1.1fr) minmax(320px,.9fr);gap:var(--tg-s7)}}
.gal{display:grid;gap:var(--tg-s3);grid-template-columns:1fr}
.gal img{width:100%;background:var(--tg-surface-2);border-radius:var(--tg-radius);aspect-ratio:4/5;object-fit:cover}
.gal .thumbs{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--tg-s2)}
.gal .thumbs img{aspect-ratio:1/1}
.info .price{font-size:var(--tg-fs-xl);font-weight:700;margin:var(--tg-s3) 0}
.opt .lbl{font-size:var(--tg-fs-sm);font-weight:600;margin-bottom:var(--tg-s2)}
.sizechips{display:flex;gap:var(--tg-s2);flex-wrap:wrap}
.sc{min-width:var(--tg-touch);min-height:var(--tg-touch);border:1px solid var(--tg-line);background:var(--tg-surface);
  border-radius:var(--tg-radius-sm);font:inherit;font-size:var(--tg-fs-sm);cursor:pointer;padding:0 var(--tg-s3)}
.sc[aria-pressed="true"]{border-color:var(--tg-brand);background:var(--tg-brand-soft);color:var(--tg-brand-ink);font-weight:600}
.attrs{list-style:none;padding:0;margin:var(--tg-s4) 0;font-size:var(--tg-fs-sm);color:var(--tg-ink-2)}
.attrs li{padding:var(--tg-s2) 0;border-top:1px solid var(--tg-line-2);display:flex;justify-content:space-between;gap:var(--tg-s4)}
.trust{display:grid;gap:var(--tg-s2);margin:var(--tg-s5) 0;font-size:var(--tg-fs-sm);color:var(--tg-ink-2)}
.trust li{list-style:none;padding-left:22px;position:relative}
.trust li::before{content:"✓";position:absolute;left:0;color:var(--tg-sea);font-weight:700}

/* ---------- sticky action bar (mobile) ---------- */
.sticky{position:sticky;bottom:0;background:var(--tg-surface);border-top:1px solid var(--tg-line);
  display:flex;gap:var(--tg-s2);padding:var(--tg-s2) var(--tg-s3) calc(var(--tg-s2) + env(safe-area-inset-bottom));
  z-index:15;margin:0 calc(-1 * var(--tg-s4))}
.sticky .btn{flex:1;padding:var(--tg-s3) var(--tg-s2);font-size:var(--tg-fs-xs)}
@media(min-width:860px){.sticky{position:static;margin:var(--tg-s4) 0 0;border:0;padding:0}}

/* ---------- filters ---------- */
.filters{display:none}
.tg-js .filters{background:var(--tg-surface-2);border:1px solid var(--tg-line);border-radius:var(--tg-radius);
  padding:var(--tg-s3) var(--tg-s4);margin:var(--tg-s4) 0;display:grid;gap:var(--tg-s3)}
.frow{display:flex;gap:var(--tg-s2);flex-wrap:wrap;align-items:center}
.frow .flabel{font-size:var(--tg-fs-xs);font-weight:600;color:var(--tg-ink-2);min-width:64px}
.chip{border:1px solid var(--tg-line);background:var(--tg-surface);border-radius:var(--tg-radius-pill);
  padding:var(--tg-s2) var(--tg-s3);font:inherit;font-size:var(--tg-fs-xs);min-height:34px;cursor:pointer;color:var(--tg-ink-2)}
.chip[aria-pressed="true"]{background:var(--tg-brand-strong);border-color:var(--tg-brand-strong);color:#fff;font-weight:600}
.fcount{font-size:var(--tg-fs-xs);color:var(--tg-ink-3)}

/* ---------- pagination ---------- */
.pager{display:flex;gap:var(--tg-s2);flex-wrap:wrap;justify-content:center;margin:var(--tg-s6) 0}
.pager a,.pager span{min-width:var(--tg-touch);min-height:var(--tg-touch);display:inline-flex;align-items:center;
  justify-content:center;border:1px solid var(--tg-line);border-radius:var(--tg-radius-sm);text-decoration:none;
  font-size:var(--tg-fs-sm);background:var(--tg-surface)}
.pager [aria-current="page"]{background:var(--tg-brand-strong);color:#fff;border-color:var(--tg-brand-strong);font-weight:600}

/* ---------- store / NAP ---------- */
.nap{background:var(--tg-surface);border:1px solid var(--tg-line);border-radius:var(--tg-radius);padding:var(--tg-s5);margin:var(--tg-s4) 0}
.nap .addr{font-size:var(--tg-fs-lg);font-weight:600}
.storegrid{display:grid;gap:var(--tg-s4);grid-template-columns:1fr}
@media(min-width:720px){.storegrid{grid-template-columns:repeat(3,1fr)}}

/* ---------- lp tiles ---------- */
.tiles{display:grid;gap:var(--tg-s4);grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.tile{background:var(--tg-surface);border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);
  padding:var(--tg-s5);text-decoration:none;display:flex;flex-direction:column;gap:var(--tg-s2);min-height:120px}
.tile:hover{border-color:var(--tg-sea);box-shadow:var(--tg-shadow)}
.tile b{font-size:var(--tg-fs-lg);font-weight:600}
.tile span{font-size:var(--tg-fs-xs);color:var(--tg-ink-3)}

/* ---------- empty states ---------- */
.empty{background:var(--tg-surface);border:1px dashed var(--tg-line);border-radius:var(--tg-radius);
  padding:var(--tg-s7) var(--tg-s5);text-align:center;color:var(--tg-ink-2)}
.empty h2{color:var(--tg-ink)}

/* ---------- search ---------- */
.searchbox{display:flex;gap:var(--tg-s2);margin:var(--tg-s4) 0}
.searchbox input{flex:1;min-height:var(--tg-touch);border:1px solid var(--tg-line);border-radius:var(--tg-radius);
  padding:0 var(--tg-s4);font:inherit;font-size:var(--tg-fs-md);background:var(--tg-surface);color:var(--tg-ink)}

/* ---------- footer ---------- */
.ftr{background:var(--tg-surface);border-top:3px solid var(--tg-brand);margin-top:var(--tg-s8);padding:var(--tg-s6) 0}
.ftr .flogo{display:block;height:30px;width:auto;margin-bottom:var(--tg-s5)}
.ftr .cols{display:grid;gap:var(--tg-s5);grid-template-columns:1fr}
@media(min-width:720px){.ftr .cols{grid-template-columns:repeat(4,1fr)}}
.ftr h2{font-size:var(--tg-fs-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--tg-ink-2)}
.ftr ul{list-style:none;padding:0;margin:0;display:grid;gap:var(--tg-s2)}
.ftr a{font-size:var(--tg-fs-sm);color:var(--tg-ink-2);text-decoration:none}
.ftr a:hover{color:var(--tg-link)}
.ftr .build{margin-top:var(--tg-s5);padding-top:var(--tg-s4);border-top:1px solid var(--tg-line-2);
  font-size:var(--tg-fs-xs);color:var(--tg-ink-3)}

/* --- store facts (OD-3, 2026-09-09): giờ / điện thoại / Zalo trên trang cửa hàng --- */
.store-facts{display:grid;grid-template-columns:auto 1fr;gap:.25rem .75rem;margin:.5rem 0 .75rem;font-size:var(--tg-fs-sm,.875rem)}
.store-facts dt{color:var(--tg-ink-2,#55625B);margin:0}
.store-facts dd{margin:0;font-weight:600}
.store-facts dd a{color:var(--tg-link);text-decoration:underline;text-underline-offset:2px}
.tile .facts{display:block;margin-top:.25rem;color:var(--tg-ink-2,#55625B);font-size:var(--tg-fs-sm,.875rem);font-weight:400}

/* ============================================================================================
   Đợt 1 redesign — OD-WEB-12 (Thắng duyệt 11/09/2026) after the Claude Design audit.
   Same tokens, same fonts, same logo; only layout / spacing / component styling changes.
   Rules below override the Wave-1 defaults above on purpose (kept in one block for review).
   ============================================================================================ */

/* nav: bordered chips, no fade, last chip clipped as the scroll cue; active = ink fill + coral rule */
.nav{gap:6px;scroll-snap-type:x proximity;padding-right:var(--tg-s4);-webkit-mask-image:none;mask-image:none}
.nav a{scroll-snap-align:start;border:1px solid var(--tg-line);background:var(--tg-surface);color:var(--tg-ink);
  padding:0 14px;min-height:var(--tg-touch)}
.nav a:hover{background:var(--tg-surface-2);color:var(--tg-ink)}
.nav a[aria-current="page"]{background:var(--tg-ink);border-color:var(--tg-ink);color:var(--tg-bg);
  box-shadow:inset 0 -3px 0 var(--tg-brand)}
@media(max-width:719px){.logo img{height:30px}}
@media(min-width:720px){
  .nav{gap:2px}
  .nav a{border:0;background:transparent;border-radius:0;padding:0 12px;font-size:15px;font-weight:600;color:var(--tg-ink-2)}
  .nav a:hover{background:transparent;color:var(--tg-ink)}
  .nav a[aria-current="page"]{background:transparent;color:var(--tg-ink);box-shadow:inset 0 -3px 0 var(--tg-brand)}
}

/* breadcrumbs: one line, last item ellipsised, 8px above the h1 */
.crumbs{flex-wrap:nowrap;overflow:hidden;white-space:nowrap;padding-bottom:var(--tg-s2)}
.crumbs>*{flex:0 0 auto}
.crumbs>span:last-child{flex:0 1 auto;overflow:hidden;text-overflow:ellipsis;min-width:0}

/* section rhythm */
.sec{margin:var(--tg-s6) 0}
@media(min-width:720px){.sec{margin:var(--tg-s7) 0}}
.sec-tight{margin:var(--tg-s5) 0}
.sec-head{margin-bottom:var(--tg-s3)}
.sec-head h2{margin-bottom:0}

/* group chips (replace the text-only tiles): one scrollable row, count muted */
.chiprow{display:flex;gap:var(--tg-s2);overflow-x:auto;scrollbar-width:none;padding:2px var(--tg-s4) 6px 0;
  scroll-snap-type:x proximity;margin:0 calc(-1 * var(--tg-s4));padding-left:var(--tg-s4)}
.chiprow::-webkit-scrollbar{display:none}
@media(min-width:720px){.chiprow{margin:0;padding-left:0;flex-wrap:wrap;overflow:visible}}
.gchip{flex:0 0 auto;scroll-snap-align:start;display:inline-flex;align-items:center;gap:6px;min-height:40px;
  padding:0 var(--tg-s3);border:1px solid var(--tg-line);background:var(--tg-surface);border-radius:var(--tg-radius-pill);
  text-decoration:none;font-size:13px;font-weight:500;color:var(--tg-ink);white-space:nowrap}
.gchip span{color:var(--tg-ink-2);font-weight:400}
.gchip:hover{border-color:var(--tg-sea);background:var(--tg-sea-soft)}
.chiprow-anchors{margin-bottom:var(--tg-s2)}

/* legend + freshness note */
.legend{font-size:var(--tg-fs-xs);color:var(--tg-ink-2);margin:0 0 var(--tg-s3)}
.legend b{color:var(--tg-link)}
.freshnote{background:var(--tg-sea-soft);border-radius:var(--tg-radius-sm);padding:10px 12px;margin:var(--tg-s4) 0 0;
  font-size:var(--tg-fs-xs);line-height:1.4;color:var(--tg-ink)}
@media(min-width:720px){.freshnote{padding:12px 16px;font-size:13px}}
.freshnote b{font-weight:700}

/* product card: denser, price + brand on one row, contain-fit photo on cream, store chips */
.grid{gap:var(--tg-s3)}
@media(min-width:720px){.grid{gap:20px}}
.card .im{position:relative;border-bottom:1px solid var(--tg-line-2)}
.card .im img{object-fit:contain;padding:6px}
.card .noimg{flex-direction:column;gap:6px;background:var(--tg-surface-2) url('/brand/the-gate-mark.svg') no-repeat center 38%/44% auto}
.card .noimg span{position:absolute;left:8px;bottom:6px;font-family:ui-monospace,Menlo,monospace;font-size:10px;color:var(--tg-ink-3);text-align:left;padding:0}
.card .b{padding:10px 10px 12px;gap:6px}
.card .n{font-size:14px;line-height:18px;min-height:36px}
.card .pb{display:flex;justify-content:space-between;align-items:baseline;gap:var(--tg-s2)}
.card .p{font-size:16px;line-height:20px;margin:0}
.card .br{font-size:12px;line-height:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.card .sizes{margin:0;min-height:20px}
.card .sizes span{font-size:11px;line-height:14px;padding:2px 6px;font-weight:500;color:var(--tg-ink)}
.card .storeslot{margin-top:auto;min-height:28px}   /* reserved so revealing the chips never shifts the grid */
.card .stores{display:flex;gap:4px;margin-top:0;padding-top:2px;font-size:11px;color:var(--tg-ink-3)}
.card .sch{flex:1;justify-content:center;gap:5px;font-weight:600;line-height:14px;padding:5px 0;border-radius:var(--tg-radius-sm);
  border:1px solid var(--tg-line);color:var(--tg-ink-3);background:transparent}
.card .sch .dot{width:6px;height:6px}
/* chip state follows the guarded dot inside it (:has); browsers without :has keep the coloured dot */
.card .sch:has(.dot[data-tg-avail="IN_STOCK"]){background:var(--tg-sea);border-color:var(--tg-sea);color:#fff}
.card .sch:has(.dot[data-tg-avail="IN_STOCK"]) .dot{background:#fff}
.card .sch:has(.dot[data-tg-avail="LOW"]){background:var(--tg-warm-soft);border-color:var(--tg-warm);color:var(--tg-warm-ink)}
.card .sch:has(.dot[data-tg-avail="LOW"]) .dot{background:var(--tg-warm-ink)}
.card .cardcta{color:var(--tg-link);margin-top:2px;font-size:12px;line-height:16px}
@media(hover:hover){.card:hover{box-shadow:var(--tg-shadow);transform:translateY(-1px);transition:box-shadow .15s,transform .15s}}
@media(max-width:719px){.grid-more .card:nth-child(n+5){display:none}}

/* home hero: copy left, three real product tiles right (desktop) / below the buttons (mobile) */
.hero{padding:var(--tg-s4);margin:var(--tg-s4) 0 0;background:var(--tg-surface)}
.hero.hero-tiles::after{display:none}
.hero h1{font-size:clamp(1.625rem,1.2rem + 2vw,2.5rem);max-width:none}
.hero p{font-size:var(--tg-fs-sm)}
.hero .cta{margin-top:var(--tg-s3)}
@media(max-width:719px){.hero .cta{flex-wrap:nowrap}.hero .cta .btn{flex:1;padding-inline:var(--tg-s2)}}
.hero-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--tg-s3);margin-top:var(--tg-s4)}
.htile{text-decoration:none;color:var(--tg-ink);display:flex;flex-direction:column;gap:4px;min-width:0}
.htile .im{display:block;aspect-ratio:4/5;background:var(--tg-surface-2);border-radius:var(--tg-radius-sm);overflow:hidden;border:1px solid var(--tg-line-2)}
.htile .im img{width:100%;height:100%;object-fit:contain;padding:4px}
.htile b{font-size:12px;line-height:16px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.htile .hp{font-size:12px;line-height:16px;color:var(--tg-ink-2)}
@media(min-width:860px){
  .hero{padding:var(--tg-s6);margin:var(--tg-s5) 0 0}
  .hero.hero-tiles{display:grid;grid-template-columns:1.1fr 1fr;gap:var(--tg-s6);align-items:center}
  .hero-grid{margin-top:0}
  .htile b{font-size:14px;line-height:18px}
}

/* store tiles on the home page: address + direct Zalo / call / directions links */
.stile{padding:var(--tg-s4);gap:var(--tg-s2);min-height:0}
.stile-main{text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:4px}
.stile-main b{font-size:var(--tg-fs-md)}
.stile-main span{font-size:13px;color:var(--tg-ink-2)}
.stile-acts{display:flex;flex-wrap:wrap;gap:var(--tg-s2) var(--tg-s4);margin-top:var(--tg-s1)}
.stile-acts a{font-size:13px;font-weight:600;color:var(--tg-link);text-decoration:none;min-height:32px;display:inline-flex;align-items:center}
.stile-acts a:hover{text-decoration:underline}

/* PDP: info-top (name / price / stores / size) → gallery → info-rest; desktop 2 columns */
.pdp{gap:var(--tg-s4);margin:var(--tg-s2) 0 var(--tg-s6)}
.pdp h1{font-size:clamp(1.5rem,1.2rem + 1.5vw,2.25rem);margin-bottom:var(--tg-s2)}
.pricerow{display:flex;justify-content:space-between;align-items:baseline;gap:var(--tg-s3);flex-wrap:wrap;margin-bottom:var(--tg-s3)}
.pricerow .price{margin:0;font-size:22px;line-height:28px}
.pricerow .muted{font-size:13px}
.info-top .avail{margin:0 0 var(--tg-s3)}
.info-top .opt{margin:0 0 var(--tg-s2)}
.gal{grid-template-columns:1fr;gap:var(--tg-s2)}
.gal>img{object-fit:contain;max-height:360px;border:1px solid var(--tg-line-2);padding:6px}
.gal .thumbs{grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:6px}
.gal .thumbs img{aspect-ratio:1/1;object-fit:cover;border-radius:var(--tg-radius-sm);border:1px solid var(--tg-line-2)}
.info-rest .freshnote{margin-top:var(--tg-s3)}
.link3{display:inline-flex;align-items:center;min-height:var(--tg-touch);font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-link);text-decoration:none;margin-top:var(--tg-s2)}
.link3:hover{text-decoration:underline}
@media(min-width:860px){
  .pdp{grid-template-columns:minmax(0,1.1fr) minmax(320px,.9fr);grid-template-areas:"gal top" "gal rest";gap:var(--tg-s3) var(--tg-s7);align-content:start}
  .gal{grid-area:gal;align-self:start}
  .gal>img{max-height:none}
  .gal .thumbs{grid-template-columns:repeat(auto-fill,minmax(88px,1fr))}
  .info-top{grid-area:top}
  .info-rest{grid-area:rest}
  .pricerow .price{font-size:28px;line-height:32px}
}

/* availability block: three tiles instead of three rows */
.avail{background:var(--tg-sea-soft);border-color:transparent;padding:var(--tg-s3)}
.avail h2{font-family:var(--tg-font-display);font-size:12px;letter-spacing:.08em;color:var(--tg-slate);margin-bottom:var(--tg-s2);padding-top:0}
.avail .tiles3{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.avail .row{flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:2px;padding:8px 10px;border:1px solid transparent;
  border-radius:8px;background:var(--tg-surface)}
.avail .row:first-of-type{border-top:1px solid transparent}
.avail .sn{font-size:13px;font-weight:600;line-height:1.25}
.avail .st{font-size:12px}
.avail .row:has(.st[data-tg-avail="LOW"]){background:var(--tg-warm-soft);border-color:var(--tg-warm)}
.avail .st[data-tg-avail="LOW"]{color:var(--tg-warm-ink)}
.avail .row:has(.st[data-tg-avail="OUT"]),.avail .row:has(.st[data-tg-avail="UNKNOWN"]){background:transparent;border-color:var(--tg-line)}
.avail .meta{margin-top:var(--tg-s2);color:var(--tg-ink-2)}   /* ink-2 on sea-soft = 5.3:1 (ink-3 was 4.49) */
.avail-neutral .st{color:var(--tg-ink-2)}
.avail-neutral .row{border-color:var(--tg-line);background:transparent}
@media(min-width:720px){.avail{padding:var(--tg-s4)}.avail .row{padding:10px 12px}.avail .sn{font-size:15px}.avail .st{font-size:14px}}

/* sticky action bar: fixed to the bottom on mobile (product + store pages), static inside the card on desktop */
@media(max-width:859px){
  .has-bar .sticky{position:fixed;left:0;right:0;bottom:0;margin:0;padding:var(--tg-s2) var(--tg-s4) calc(var(--tg-s2) + env(safe-area-inset-bottom));z-index:25}
  .has-bar .sticky .btn{min-height:48px;font-size:14px;padding:var(--tg-s2) var(--tg-s1)}
  .has-bar .sticky .btn-primary{flex:1.2}
  .has-bar{padding-bottom:calc(64px + env(safe-area-inset-bottom))}
  .has-bar .stalebanner{bottom:calc(64px + env(safe-area-inset-bottom))}
  .nap-store .sticky+.meta{margin-top:var(--tg-s3)}
}
@media(min-width:860px){.nap-store .sticky{max-width:520px}.nap-store .sticky .btn-primary{flex:1.3}}
.nap{padding:var(--tg-s4);border-left:4px solid var(--tg-sea)}
@media(min-width:720px){.nap{padding:var(--tg-s5)}}

/* store page: the per-store list is revealed by the guard; reserve its region so the footer is not in the
   first viewport before the reveal (CLS 0.37 → 0 on mobile). Without JS the region is simply blank. */
.storelist{min-height:70vh}

/* empty state: left aligned, dashed, faint mark */
.empty{text-align:left;padding:var(--tg-s5);display:flex;flex-direction:column;align-items:flex-start;gap:var(--tg-s2)}
.empty .mark{width:28px;height:28px;opacity:.3;margin-bottom:var(--tg-s1)}
.empty h2{font-size:var(--tg-fs-md);font-family:var(--tg-font-body);margin:0}
.empty p{margin:0 0 var(--tg-s2);font-size:var(--tg-fs-sm)}

/* footer: room for the fixed bar on mobile */
@media(max-width:859px){.has-bar .ftr{padding-bottom:var(--tg-s5)}}

/* ============================================================================================
   Bài viết (/blog/) + English cluster (/en/…) — 11/09 (SEO audit items 1 + blog)
   ============================================================================================ */
.lead{font-size:var(--tg-fs-lg);color:var(--tg-ink-2);max-width:64ch;margin:var(--tg-s2) 0 var(--tg-s4)}
.postlist{list-style:none;margin:0;padding:0;display:grid;gap:var(--tg-s3)}
.postlist li{background:var(--tg-surface);border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);padding:var(--tg-s4)}
.postlist .pt{display:block;font-family:var(--tg-font-display);font-weight:600;font-size:var(--tg-fs-lg);line-height:var(--tg-lh-tight);color:var(--tg-ink);text-decoration:none}
.postlist .pt:hover{color:var(--tg-link)}
.postlist .pd{margin:var(--tg-s2) 0 0;color:var(--tg-ink-2);font-size:var(--tg-fs-sm)}
.postlist .pm,.post .pm{margin:var(--tg-s2) 0 0;color:var(--tg-ink-3);font-size:var(--tg-fs-xs)}
@media(min-width:720px){.postlist{grid-template-columns:1fr 1fr}.postlist-3{grid-template-columns:repeat(3,1fr)}}
.pchip{display:inline-block;padding:2px 8px;border-radius:var(--tg-radius-pill);background:var(--tg-sea-soft);color:var(--tg-sea-hover);font-weight:600;margin-right:var(--tg-s1)}
.post{max-width:72ch}
.post-head{margin:var(--tg-s4) 0 var(--tg-s5)}
.post-head h1{margin:var(--tg-s2) 0}
.post-head .lead{margin-top:0}
.post-body{font-size:var(--tg-fs-md);line-height:1.7}
.post-body h2{font-size:var(--tg-fs-xl);margin:var(--tg-s6) 0 var(--tg-s3)}
.post-body h3{font-size:var(--tg-fs-lg);font-family:var(--tg-font-body);font-weight:600;margin:var(--tg-s5) 0 var(--tg-s2)}
.post-body p{margin:0 0 var(--tg-s4)}
.post-body ul,.post-body ol{padding-left:1.25em;margin:0 0 var(--tg-s4)}
.post-body li{margin:0 0 var(--tg-s2)}
.post-body a{color:var(--tg-link);text-decoration:underline;text-underline-offset:3px}
.post-body a:hover{color:var(--tg-sea-hover)}
.post-body strong{color:var(--tg-ink)}
.post-body img{max-width:100%;height:auto;border-radius:var(--tg-radius)}
.post-cta{margin:var(--tg-s6) 0 var(--tg-s4);padding:var(--tg-s4);background:var(--tg-brand-tint);border:1px solid var(--tg-brand-soft);border-radius:var(--tg-radius)}
.post-cta b{display:block;font-family:var(--tg-font-display);font-size:var(--tg-fs-lg)}
.post-cta p{margin:var(--tg-s2) 0 var(--tg-s3);color:var(--tg-ink-2);font-size:var(--tg-fs-sm)}
.post-cta-acts{display:flex;gap:var(--tg-s2);flex-wrap:wrap}
.post-cta-acts .btn{min-height:var(--tg-touch)}
/* home: three latest posts as plain text tiles (no images → no LCP/CLS cost) */
.postrow{display:grid;gap:var(--tg-s3);grid-template-columns:1fr}
@media(min-width:720px){.postrow{grid-template-columns:repeat(3,1fr)}}
.postrow a{display:block;padding:var(--tg-s4);background:var(--tg-surface);border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);text-decoration:none;color:var(--tg-ink)}
.postrow a b{display:block;font-family:var(--tg-font-display);font-weight:600;font-size:var(--tg-fs-md);line-height:var(--tg-lh-tight)}
.postrow a span{display:block;margin-top:var(--tg-s2);color:var(--tg-ink-2);font-size:var(--tg-fs-sm)}
.postrow a:hover{border-color:var(--tg-sea)}
/* EN pages: photo strip + figure */
.photo{margin:var(--tg-s4) 0;border-radius:var(--tg-radius);overflow:hidden;background:var(--tg-surface-2)}
.photo img{display:block;width:100%;height:auto}
.photo figcaption{padding:var(--tg-s2) var(--tg-s3);font-size:var(--tg-fs-xs);color:var(--tg-ink-3)}
.photos{display:grid;gap:var(--tg-s3);grid-template-columns:repeat(2,1fr);margin:var(--tg-s4) 0}
.photos .photo{margin:0}
.photos .photo img{aspect-ratio:4/5;object-fit:cover}
@media(min-width:720px){.photos{grid-template-columns:repeat(4,1fr)}.photos-3{grid-template-columns:repeat(3,1fr)}}
.en-hero{display:grid;gap:var(--tg-s4);margin:var(--tg-s4) 0}
@media(min-width:860px){.en-hero{grid-template-columns:1.1fr 1fr;align-items:center}}
.en-hero .photo{margin:0}
.en-links{list-style:none;margin:0;padding:0;display:grid;gap:var(--tg-s3)}
@media(min-width:720px){.en-links{grid-template-columns:repeat(3,1fr)}}
.en-links a{display:block;padding:var(--tg-s4);background:var(--tg-surface);border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);text-decoration:none;color:var(--tg-ink)}
.en-links a b{display:block;font-family:var(--tg-font-display);font-size:var(--tg-fs-lg);line-height:var(--tg-lh-tight)}
.en-links a span{display:block;margin-top:var(--tg-s2);color:var(--tg-ink-2);font-size:var(--tg-fs-sm)}
.en-links a:hover{border-color:var(--tg-sea)}
.prose{max-width:72ch}
.prose h2{margin:var(--tg-s6) 0 var(--tg-s3)}
.prose p,.prose ul{line-height:1.7}
.prose a{color:var(--tg-link)}

/* ============================================================================================
   Đợt 2 (11/09): /mua-dong/ grouped by sub-type with anchor chips · "Đang mở" chip (JS only) ·
   store photos (real photos only)
   ============================================================================================ */
.wgroup{margin:var(--tg-s5) 0 0}
.wgroup-h{font-size:var(--tg-fs-lg);margin:0 0 var(--tg-s3);scroll-margin-top:72px}
.wgroup-h .muted{font-family:var(--tg-font-body);font-weight:400;font-size:var(--tg-fs-sm);margin-left:var(--tg-s1)}
.wgroup-more{margin:var(--tg-s3) 0 0;font-size:var(--tg-fs-sm);color:var(--tg-ink-2)}
.wgroup-more a{color:var(--tg-link);font-weight:600;text-decoration:none}
.wgroup-more a:hover{text-decoration:underline}
.openchip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;border-radius:var(--tg-radius-pill);font-size:var(--tg-fs-xs);font-weight:600;line-height:1.6;white-space:nowrap;vertical-align:middle;background:var(--tg-surface-2);color:var(--tg-ink-2)}
.openchip::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor;opacity:.75}
.openchip[data-tg-open="open"]{background:var(--tg-sea-soft);color:var(--tg-sea-hover)}
.openchip[data-tg-open="soon"]{background:var(--tg-warm-soft);color:var(--tg-warm-ink)}
.openchip[data-tg-open="closed"]{background:var(--tg-surface-2);color:var(--tg-ink-3)}
.tile .openchip{margin-top:var(--tg-s2);align-self:flex-start}
.stile-main .openchip{margin-top:2px;align-self:flex-start}
.store-facts .openchip{margin-left:var(--tg-s1)}
.store-hero{display:grid;gap:var(--tg-s4);margin:var(--tg-s3) 0 0}
@media(min-width:860px){.store-hero{grid-template-columns:1.1fr 1fr;align-items:start}}
.store-hero .photo{margin:0}

/* 12/09: store tiles on /cua-hang/ carry a real storefront thumbnail (16:9 crop) */
.tile .tile-img{width:100%;aspect-ratio:16/9;object-fit:cover;border-radius:var(--tg-radius-sm);margin-bottom:var(--tg-s2);background:var(--tg-surface-2)}

/* ============================================================================================
   Đợt 3 — mobile-first UI/UX pass (12/09). Same tokens, same fonts, same logo, same palette as the
   "the-gate" theme approved 09/09; this block only changes layout, type scale, ordering and states.
   Kept in one block, after everything else, so it can be reviewed — or reverted — on its own.
   ============================================================================================ */

/* ---- type scale ------------------------------------------------------------------------------
   Target: mobile H1 28 / H2 22 / body 16 · desktop H1 40 / H2 28 / body 16.
   h1 (--tg-fs-2xl) and h2 (--tg-fs-xl) already clamp to exactly those values; the hero was the one
   heading running its own larger scale. Headings go to 1.25 line-height, body to 1.5.            */
/* (khối :root thứ hai đã gộp lên nguồn chuẩn ở đầu file — token không còn định nghĩa trùng) */
h1,h2{line-height:1.25}
/* Secondary prose is 14px minimum. The dense data chips inside a product card (size + store chips)
   are the one deliberate exception: two cards fit in 390px only at ~173px each, where 14px chips
   overflow. They are set at 12px (--tg-fs-2xs) and are never the only place a fact appears. */
.meta,.legend,.freshnote,.card .br,.card .cardcta,.gchip,.tile span,.postrow a span,.stile-main span{font-size:var(--tg-fs-sm)}
.ftr .build{font-size:var(--tg-fs-2xs)}
.hero .kicker{font-size:var(--tg-fs-2xs)}
.card .sizes span,.card .stores,.card .sch{font-size:var(--tg-fs-2xs)}

/* ---- header: logo + search + "Danh mục" on mobile, full row on desktop ---------------------- */
.hdr .wrap{gap:var(--tg-s2)}
.srch,.menu-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;flex:0 0 auto;
  min-height:var(--tg-touch);padding:0 var(--tg-s3);border-radius:var(--tg-radius);font-size:var(--tg-fs-sm);
  font-weight:600;text-decoration:none;border:1px solid var(--tg-line);background:var(--tg-surface);color:var(--tg-ink)}
.hdr .srch{color:var(--tg-link);border-color:var(--tg-sea)}
.hdr .srch:hover{background:var(--tg-sea-soft)}
.srch .ic,.menu-btn .ic{flex:0 0 auto}
/* NOT position:relative — the panel is anchored to the header, not to this button (see .menu-panel) */
.menu{flex:0 0 auto}
.menu-btn{list-style:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
.menu-btn::-webkit-details-marker{display:none}
.menu-btn::marker{content:""}
.menu-btn:hover{background:var(--tg-surface-2)}
.menu[open] .menu-btn{background:var(--tg-ink);border-color:var(--tg-ink);color:var(--tg-bg)}
/* Panel anchored to the HEADER (.hdr is position:sticky, so it is the containing block), stretched with
   left:0;right:0 instead of a 100vw width offset from the button.
   The previous rule positioned it from the button's own right edge and assumed that edge sat flush with
   the viewport. It does not: below 860px .nav is display:none, so nothing in the header row grows and
   the logo / search / menu pack to the LEFT — the button's right edge stayed at 339px at every width.
   A 100vw panel hung off that point started at x=-35 on a 390px screen and x=-75 at 430px, pushing the
   first characters of every label off the left of the screen. left:0;right:0 cannot drift: the panel is
   exactly as wide as the header, whatever the viewport. */
.menu-panel{position:absolute;top:100%;left:0;right:0;width:auto;
  background:var(--tg-surface);border-top:1px solid var(--tg-line);border-bottom:1px solid var(--tg-line);
  box-shadow:var(--tg-shadow);z-index:30;max-height:calc(100dvh - 56px);overflow-y:auto}
.menu-panel ul{list-style:none;margin:0;padding:var(--tg-s2) 0}
.menu-panel li{margin:0}
.menu-panel a{display:flex;align-items:center;min-height:48px;padding:0 var(--tg-s4);text-decoration:none;
  color:var(--tg-ink);font-size:var(--tg-fs-md);font-weight:500;white-space:normal}
.menu-panel a:hover{background:var(--tg-surface-2)}
.menu-panel a[aria-current="page"]{color:var(--tg-brand-ink);font-weight:700;box-shadow:inset 3px 0 0 var(--tg-brand)}
.menu-panel .menu-sep{border-top:1px solid var(--tg-line-2);margin-top:var(--tg-s2);padding-top:var(--tg-s2)}
.menu-panel .menu-sep a{color:var(--tg-link);font-weight:600}
@media(max-width:859px){
  .nav{display:none}
  /* .nav was the only flex:1 child; with it hidden the row packed left and the search + menu buttons
     floated in the middle of the header. Push them to the right edge where they belong. */
  .hdr .srch{margin-left:auto}
}
@media(min-width:860px){ .menu{display:none} .nav{display:flex} }

/* screen-reader-only text: names the destination store on a button that must stay visually short */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---- home hero: short headline, one subline, real product tiles ----------------------------- */
.hero h1{font-size:var(--tg-fs-2xl);max-width:none;margin-bottom:var(--tg-s2)}
.hero .hero-sub{font-size:var(--tg-fs-md);color:var(--tg-ink-2);margin-bottom:0;max-width:40ch}
@media(max-width:719px){.hero .cta{flex-wrap:wrap}.hero .cta .btn{flex:1 1 46%;padding-inline:var(--tg-s3)}}
/* tiles: 4:5 frame, product centred on one consistent ground, name on up to two lines (the old
   single-line ellipsis cut every name mid-word: "TJO Camping …", "TJO Wanderlus…") */
.hero-grid{gap:var(--tg-s2)}
.htile .im{aspect-ratio:4/5;background:var(--tg-surface-2)}
.htile .im img{object-fit:contain;padding:6px}
.htile b{font-size:var(--tg-fs-sm);line-height:1.3;white-space:normal;overflow:hidden;text-overflow:clip;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:2.6em}
.htile .hp{font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-ink)}
@media(min-width:860px){.htile b{font-size:var(--tg-fs-md);min-height:2.6em}}

/* ---- product grid: 2 columns on mobile, 4 on desktop ---------------------------------------- */
.grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--tg-s3)}
@media(min-width:860px){.grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--tg-s5)}}
/* 4:5 frame, whole product visible, centred, always the same ground — the source photo is never
   altered, only fitted (cover was cropping sleeves and hems off flat-lay shots) */
.card .im{aspect-ratio:4/5;background:var(--tg-surface-2);display:flex;align-items:center;justify-content:center}
.card .im img{width:100%;height:100%;object-fit:contain;object-position:center;padding:8px}
.card .n{font-size:var(--tg-fs-sm);line-height:1.3;min-height:2.6em;-webkit-line-clamp:2}
.card .p{font-size:1.125rem;line-height:1.3}                       /* 18px */
@media(min-width:860px){.card .p{font-size:1.25rem}}               /* 20px */
.card .cardcta{font-weight:600}
.card .sizes span{padding:2px 7px}
/* store chips: the store's own short name instead of an internal code */
.card .sch{padding:5px 2px;letter-spacing:0}

/* ---- PDP: tên → giá → ảnh → size → cửa hàng → liên hệ ---------------------------------------- */
.info-head h1{margin-bottom:var(--tg-s2)}
.pricerow .price{font-size:1.5rem;line-height:1.25}                /* 24px mobile */
.info-top .opt{margin:0 0 var(--tg-s3)}
.opt-head{display:flex;align-items:center;justify-content:space-between;gap:var(--tg-s3);flex-wrap:wrap;margin-bottom:var(--tg-s2)}
.opt-head .lbl{margin:0}
.sizechart-link{display:inline-flex;align-items:center;gap:6px;min-height:var(--tg-touch);padding:0 var(--tg-s3);
  border:1px solid var(--tg-sea);border-radius:var(--tg-radius);background:var(--tg-sea-soft);
  color:var(--tg-link);font-size:var(--tg-fs-sm);font-weight:600;text-decoration:none}
.sizechart-link:hover{background:var(--tg-surface);border-color:var(--tg-sea-hover)}
.sizechips{gap:var(--tg-s2)}
.sc{position:relative;display:inline-flex;align-items:center;justify-content:center;font-weight:600}
.sc .sdot{position:absolute;inset:0;border-radius:inherit;pointer-events:none}
/* "tạm hết" styling is driven by the guarded dot, exactly like the store chips on a card: the static
   HTML renders UNKNOWN, so without JavaScript — or with a stale snapshot — no size is ever dimmed. */
.sc:has(.sdot[data-tg-avail="OUT"]){color:var(--tg-ink-3);background:var(--tg-surface-2);border-style:dashed;font-weight:500}
.sc:has(.sdot[data-tg-avail="OUT"])::after{content:"";position:absolute;left:8px;right:8px;top:50%;height:1px;background:currentColor;opacity:.45}
.sizehint{margin:var(--tg-s2) 0 0;font-size:var(--tg-fs-sm);color:var(--tg-ink-2)}
.sizehint-out{margin-top:2px;color:var(--tg-ink-3)}
.info-top .avail{margin:0 0 var(--tg-s2)}
.info-top .freshnote{margin-top:var(--tg-s2)}

/* The January Outdoor: say where the link goes before it is tapped */
.tjo-link{display:block;margin:var(--tg-s4) 0 0;padding:var(--tg-s3) var(--tg-s4);text-decoration:none;
  border:1px solid var(--tg-sea);border-radius:var(--tg-radius);background:var(--tg-sea-soft);color:var(--tg-ink)}
.tjo-link b{display:block;font-size:var(--tg-fs-md);color:var(--tg-link)}
.tjo-link span{display:block;margin-top:2px;font-size:var(--tg-fs-sm);color:var(--tg-ink-2)}
.tjo-link:hover{background:var(--tg-surface)}

/* per-store contact cards — every action names the store it reaches */
.scontact{margin:var(--tg-s5) 0 0}
.scontact h2{font-size:var(--tg-fs-lg);margin-bottom:var(--tg-s1)}
.scontact .meta{margin:0 0 var(--tg-s3)}
.scontact-list{list-style:none;margin:0;padding:0;display:grid;gap:var(--tg-s3)}
/* Sửa 17/09: trước đây là repeat(3,1fr). Ký hiệu 1fr = minmax(AUTO,1fr) — cận dưới auto chính là
   min-content của thẻ (~200px, bị .openchip white-space:nowrap ghim) nên lưới KHÔNG BAO GIỜ hẹp hơn
   3×200 + 2×12 = 625px. Nhưng khối này nằm trong cột phải của .pdp — minmax(320px,.9fr), thực tế chỉ
   371–513px — nên lưới luôn tràn ra ngoài cột ở MỌI bề rộng ≥860px: ở 1024px thẻ Tam Cốc bị đẩy ra
   ngoài màn hình cùng cả ba nút liên hệ của nó, ở 1440px thẻ lòi khỏi cột nhưng rơi vào lề nên không
   sinh thanh cuộn (vì thế phép kiểm "tràn ngang toàn trang" không bắt được).
   auto-fit + minmax(min(100%,13rem),1fr): số cột tự theo chỗ thật sự có (3 khi rộng, 2 ở 1024–1440,
   1 khi hẹp), và min(100%,…) đảm bảo khi container còn hẹp hơn 13rem thì cột co theo container chứ
   không tràn. Không thẻ nào bị cắt, không nút liên hệ nào ra khỏi màn hình. */
@media(min-width:860px){.scontact-list{grid-template-columns:repeat(auto-fit,minmax(min(100%,13rem),1fr))}}
.scard{background:var(--tg-surface);border:1px solid var(--tg-line);border-radius:var(--tg-radius);padding:var(--tg-s3)}
.scard-h{display:flex;align-items:center;gap:var(--tg-s2);flex-wrap:wrap}
.scard-h b{font-size:var(--tg-fs-md)}
.scard-a{display:block;margin-top:2px;font-size:var(--tg-fs-sm);color:var(--tg-ink-2)}
.scard-acts{display:flex;flex-wrap:wrap;gap:var(--tg-s2);margin-top:var(--tg-s3)}
.scard-acts .btn{flex:1 1 auto;padding-inline:var(--tg-s3);font-size:var(--tg-fs-sm)}
.scard-acts .btn-primary{flex-basis:100%}
@media(min-width:860px){.scard-acts .btn{flex-basis:100%}}
/* Chỉ trong thẻ cửa hàng: nhãn giờ mở cửa được phép xuống dòng khi cột hẹp, để nó không còn là
   "sàn" ghim min-content của thẻ. Nhãn dài nhất mà store-open.js sinh ra là "Open now · until 21:30"
   (~185px); ở bề rộng cột bình thường nó vẫn nằm gọn một dòng, chỉ ngắt khi thật sự không đủ chỗ.
   .openchip ở nơi khác (.tile, .stile-main, .store-facts) giữ nguyên nowrap. */
.scard .openchip{white-space:normal}

/* desktop: gallery in a column of its own, reading order preserved in the DOM */
@media(min-width:860px){
  .pdp{grid-template-columns:minmax(0,1.05fr) minmax(340px,.95fr);
    grid-template-areas:"gal head" "gal top" "gal rest" "gal bar";gap:var(--tg-s3) var(--tg-s7)}
  .gal{grid-area:gal}
  .info-head{grid-area:head}
  .info-top{grid-area:top}
  .info-rest{grid-area:rest}
  .pdp .sticky{grid-area:bar}
  .pricerow .price{font-size:1.75rem}                              /* 28px desktop */
}

/* ---- category: group navigation above the grid ---------------------------------------------- */
.filters{scroll-margin-top:72px}
.tg-js .filters{padding:var(--tg-s3)}
.frow .flabel{font-size:var(--tg-fs-sm);min-width:72px}
.chip{font-size:var(--tg-fs-sm);min-height:var(--tg-touch);padding:0 var(--tg-s3);display:inline-flex;align-items:center}
.fcount{font-size:var(--tg-fs-sm)}

/* ---- misc ------------------------------------------------------------------------------------ */
.btn{border-radius:var(--tg-radius)}
.ftr .buildref{display:block;margin-top:var(--tg-s1);font-size:var(--tg-fs-2xs);color:var(--tg-ink-3);
  font-family:ui-monospace,Menlo,monospace}
/* the fixed bar now carries two 48px buttons: keep its own height out of the content and off the
   focus ring of whatever is last on the page */
@media(max-width:859px){
  .has-bar{padding-bottom:calc(76px + env(safe-area-inset-bottom))}
  .has-bar .stalebanner{bottom:calc(76px + env(safe-area-inset-bottom))}
}

/* ---- Đợt 3 refinements after the first visual pass ------------------------------------------- */
/* hero tiles are ~100px wide on a 390px screen; three lines at 14px fits "TJO Wanderlust Gile"
   where two lines still ellipsised it */
.htile b{-webkit-line-clamp:3;min-height:auto}
@media(min-width:860px){.htile b{-webkit-line-clamp:2}}
/* group chips: wrap instead of scrolling. A clipped last chip as a "there is more" cue hides half the
   winter groups behind a gesture that is not visible on a screenshot or to a keyboard user. */
@media(max-width:719px){
  .chiprow{flex-wrap:wrap;overflow:visible;margin:0;padding-left:0;padding-right:0}
}
/* PDP desktop: the gallery column must not stretch down the whole info column, and the action bar is
   redundant there because the per-store cards are already on screen */
@media(min-width:860px){
  .gal{align-self:start}
  .pdp .sticky{display:none}
}
.fnote{margin:var(--tg-s1) 0 0;font-size:var(--tg-fs-sm);color:var(--tg-ink-2);line-height:1.45}
.fnote b{color:var(--tg-ink)}

/* filters as a disclosure: closed on mobile, always open on desktop */
.tg-js .filters{display:block;padding:0;background:var(--tg-surface);border-color:var(--tg-line)}
.filters-sum{display:flex;align-items:center;gap:var(--tg-s2);min-height:var(--tg-touch);padding:0 var(--tg-s3);
  cursor:pointer;list-style:none;font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-ink)}
.filters-sum::-webkit-details-marker{display:none}
.filters-sum::marker{content:""}
.filters-sum::after{content:"▾";margin-left:auto;color:var(--tg-ink-2)}
.filters[open] .filters-sum{border-bottom:1px solid var(--tg-line-2)}
.filters[open] .filters-sum::after{content:"▴"}
.filters-body{display:grid;gap:var(--tg-s3);padding:var(--tg-s3)}
/* No CSS override of the UA's <details> behaviour. Forcing `display:grid!important` on the body of a
   CLOSED <details> does lay the body out — but the <details> box itself still collapses (measured: 2px
   tall, i.e. its borders only), so the chips rendered on top of the content below and a hit test at a
   chip's centre returned the element underneath. The open/closed state is real state, so filter.js
   owns it: it opens the panel at >=860px and follows the breakpoint on resize. The island is JS-only
   anyway (the block stays `hidden` until filter.js reveals it), so there is no no-JS path to lose. */
@media(min-width:860px){
  .tg-js .filters{background:var(--tg-surface-2)}
  .filters-sum{cursor:pointer}
}

/* Đợt 3b — a facet that cannot be combined with the active one is disabled, not hidden, so the
   customer can see it exists and why it is unavailable. */
.chip[disabled],.chip[aria-disabled="true"]{opacity:.45;cursor:not-allowed;background:var(--tg-surface-2);
  border-color:var(--tg-line-2);color:var(--tg-ink-3)}
.fnote[data-tg-active="1"]{color:var(--tg-ink);background:var(--tg-warm-soft);border-radius:var(--tg-radius-sm);padding:8px 10px}

/* Store chips on a product card (Đợt 3b fix).
   `flex:1` forced the three chips to equal widths; at a 158–173px card that left "Tam Cốc" 41px and it
   broke mid-name onto two lines inside a 40px-tall chip. Measured at 360/390px, three full store names
   need ~181px and only ~138px is available, so they cannot share one row without being cut. They now
   size to their own text, never wrap mid-name, and the row wraps to a second line instead. The slot
   reserves that height so revealing the chips after the freshness guard runs still shifts nothing. */
.card .sch{flex:0 1 auto;min-width:0;white-space:nowrap;padding:5px 5px;gap:4px}
.card .stores{flex-wrap:wrap;gap:4px}
.card .sch .dot{width:5px;height:5px;flex:0 0 auto}
.card .storeslot{min-height:56px}
@media(min-width:860px){
  .card .sch{padding:5px 6px}
  .card .storeslot{min-height:28px}
}

/* ============================================================================================
   Đợt 4 — xem hàng dễ hơn (12/09). Same tokens, same fonts, same logo, same palette; layout,
   states and controls only. Appended as its own block so it can be reviewed or reverted alone.

   Measured on the baseline build (real Chrome, 390x844 and 1440x900) before writing any of it:
     · the PDP thumbnails were inert — clicking one left the main photo unchanged; there was no
       enlarge, no selected state, no position readout, no prev/next;
     · the three hero tiles put their prices at y=343 / 364 / 364 (desktop) and 450 / 468 / 468
       (mobile) because the name ran 1, 2 and 2 lines;
     · the home "Mùa đông theo nhóm" chip block was 330px tall on mobile and the product grid
       started at y=1010.
   ============================================================================================ */

/* ---- A. product photo viewing ---------------------------------------------------------------
   The main photo is wrapped in a button by public/gallery.js, so the geometry the old `.gal>img`
   rules gave it is restated here for `.gal .gal-open>img`. Nothing changes without that script. */
.gal .gal-open{display:block;width:100%;padding:0;margin:0;border:0;background:none;cursor:zoom-in;
  border-radius:var(--tg-radius);font:inherit;color:inherit}
.gal .gal-open>img{object-fit:contain;max-height:360px;border:1px solid var(--tg-line-2);padding:6px}
@media(min-width:860px){.gal .gal-open>img{max-height:none}}

/* prev / 2·4 / next — one 44px row under the photo. On desktop the thumbnail strip sits below the
   fold at 1440x900, so the readout earns its place there too. */
.gal-nav{display:flex;align-items:center;justify-content:center;gap:var(--tg-s3)}
.gal-arrow{min-width:var(--tg-touch);min-height:var(--tg-touch);display:inline-flex;align-items:center;
  justify-content:center;border:1px solid var(--tg-line);background:var(--tg-surface);color:var(--tg-ink);
  border-radius:var(--tg-radius);cursor:pointer;font:inherit;padding:0}
.gal-arrow:hover{background:var(--tg-surface-2);border-color:var(--tg-sea)}
.gal-count{font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-ink-2);min-width:5ch;
  text-align:center;font-variant-numeric:tabular-nums}

/* thumbnails: real buttons once the script has run, with the chosen one clearly marked */
.gal .gal-thumb{display:block;padding:0;margin:0;border:0;background:none;cursor:pointer;
  border-radius:var(--tg-radius-sm);font:inherit;line-height:0}
.gal .gal-thumb[aria-pressed="true"] img{border-color:var(--tg-brand);box-shadow:0 0 0 2px var(--tg-brand)}
.gal .gal-thumb:hover img{border-color:var(--tg-sea)}

/* a photo whose file will not load must leave a neutral frame, not a broken one. Also covers the
   pre-existing "Ảnh đang được chuẩn bị" case, which had no styling of its own inside .gal. */
.gal .noimg{display:flex;align-items:center;justify-content:center;aspect-ratio:4/5;max-height:360px;
  background:var(--tg-surface-2) url('/brand/the-gate-mark.svg') no-repeat center 40%/28% auto;
  border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);color:var(--tg-ink-3);
  font-size:var(--tg-fs-sm);text-align:center;padding:var(--tg-s4)}
.gal .noimg span{align-self:flex-end}
@media(min-width:860px){.gal .noimg{max-height:none}}

/* the enlarged photo. Light ground on purpose: the theme note of 09/09 keeps this site off dark
   grounds because product fabric colours read wrong on them — that applies to a full-screen photo
   more than anywhere else. Backdrop is ink at 72%, so the page behind is clearly out of play. */
.gal-lb{position:fixed;inset:0;width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;
  margin:0;padding:0;border:0;background:var(--tg-bg);color:var(--tg-ink);overflow:hidden}
.gal-lb[open]{display:grid;grid-template-rows:auto minmax(0,1fr) auto}
.gal-lb::backdrop{background:rgba(22,50,60,.72)}
.gal-lb-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--tg-s3);
  padding:var(--tg-s2) var(--tg-s3);border-bottom:1px solid var(--tg-line-2);min-height:52px}
.gal-lb-count{font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-ink-2);font-variant-numeric:tabular-nums}
.gal-lb-close{min-width:var(--tg-touch);min-height:var(--tg-touch);display:inline-flex;align-items:center;
  justify-content:center;border:1px solid var(--tg-line);background:var(--tg-surface);color:var(--tg-ink);
  border-radius:var(--tg-radius);cursor:pointer;padding:0;margin-left:auto}
.gal-lb-close:hover{background:var(--tg-surface-2);border-color:var(--tg-sea)}
.gal-lb-stage{display:flex;align-items:center;justify-content:center;min-height:0;padding:var(--tg-s3)}
.gal-lb-stage img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;
  background:var(--tg-surface);border-radius:var(--tg-radius-sm)}
.gal-lb-nav{display:flex;align-items:center;justify-content:center;gap:var(--tg-s6);
  padding:var(--tg-s3) var(--tg-s3) calc(var(--tg-s3) + env(safe-area-inset-bottom));
  border-top:1px solid var(--tg-line-2)}
.gal-arrow-lb{min-width:52px;min-height:52px}
/* nothing left that loads while the enlarged view is open: same wording as the page, close button
   and Escape still work (see public/gallery.js) */
.gal-lb-empty{margin:0;padding:var(--tg-s5);text-align:center;color:var(--tg-ink-2);font-size:var(--tg-fs-md)}

/* ---- B. home rhythm on mobile ---------------------------------------------------------------
   The four shopping groups lead; the rest are behind a real disclosure (same pattern as the
   category filters) so nothing is hidden behind an invisible gesture. */
.moregroups{margin-top:var(--tg-s2)}
.moregroups-sum{display:inline-flex;align-items:center;gap:6px;min-height:var(--tg-touch);
  padding:0 var(--tg-s3);cursor:pointer;list-style:none;font-size:var(--tg-fs-sm);font-weight:600;
  color:var(--tg-link);border:1px solid var(--tg-line);border-radius:var(--tg-radius-pill);
  background:var(--tg-surface)}
.moregroups-sum::-webkit-details-marker{display:none}
.moregroups-sum::marker{content:""}
.moregroups-sum::after{content:"▾";color:var(--tg-ink-2)}
.moregroups[open] .moregroups-sum::after{content:"▴"}
.moregroups-sum:hover{background:var(--tg-sea-soft);border-color:var(--tg-sea)}
/* one <summary>, two labels: "Xem thêm N nhóm" closed, "Thu gọn" open. Swapped by [open] in CSS so
   it still reads correctly with JavaScript switched off. */
.moregroups-sum>span{color:inherit;font-weight:600}
.moregroups .mg-less{display:none}
.moregroups[open] .mg-more{display:none}
.moregroups[open] .mg-less{display:inline}
.chiprow-more{margin-top:var(--tg-s2);padding-bottom:0}

/* ---- C. hero tiles + card rows --------------------------------------------------------------
   Reserve the tallest name's height in all three tiles so the price row lines up. The name keeps
   its 14px/16px size and its line clamp — nothing is shrunk to fit. */
.htile b{min-height:3.9em}                            /* 3 lines at line-height 1.3 */
@media(min-width:860px){.htile b{min-height:2.6em}}   /* 2 lines */
.htile .hp{margin-top:auto}
.htile{justify-content:flex-start}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   ĐỢT NHẬN DIỆN "ĐÁ VÔI" — Thắng duyệt phương hướng 14.09.2026, bản dựng thử local.
   PHẠM VI ĐỢT NÀY: màu · chữ · bo góc · thẻ sản phẩm. BỐ CỤC GIỮ NGUYÊN để so trước/sau.
   Giữ nguyên một khối ở cuối file, sau mọi thứ khác, để duyệt hoặc gỡ bỏ độc lập —
   cùng quy ước với khối "the-gate theme" phía trên.
   KHÔNG đụng: nguồn giá/tồn, mapping, size availability, URL, canonical, robots production,
   schema, hreflang, liên hệ, link TJO, gallery, xử lý ảnh lỗi, menu, filter của đợt 4.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ---- A. chữ: Manrope thay Josefin ------------------------------------------------------------
   Josefin cần letter-spacing dương và padding-top .08em vì dấu tiếng Việt bị cắt trên.
   Manrope không cần: chiều cao dấu nằm gọn trong em-box, nên trả tracking về âm cho tiêu đề
   và bỏ hẳn padding bù. Không đổi cỡ chữ — cỡ vẫn theo thang đang chạy. */
h1,h2{letter-spacing:-.022em;padding-top:0;line-height:1.18}
h1{font-weight:800;letter-spacing:-.03em;line-height:1.12}
h2{font-weight:800}
h3{font-family:var(--tg-font-display);font-weight:700;letter-spacing:-.018em}
.hdr .wm,.hdr nav a,.btn{font-family:var(--tg-font-display)}
.btn{font-weight:700;letter-spacing:-.008em}
/* giá: Manrope 800 + chữ số cùng bề rộng để cột giá thẳng hàng giữa các thẻ */
.card .p,.htile .hp,.pdp-price,.p-price{font-family:var(--tg-font-display);font-weight:800;
  font-variant-numeric:tabular-nums;letter-spacing:-.015em}

/* ---- B. điều khiển: viền đủ tương phản, vòng focus dày ---------------------------------------
   --ke-dam (#767C77) là viền của ĐIỀU KHIỂN (nút viền, ô nhập, chip size, nút gallery). Đo theo
   vai trò phi-chữ, ngưỡng 3:1: 4.27:1 trên thẻ trắng · 3.70:1 trên nền đá vôi · 3.44:1 trên nền
   phụ — đạt trên cả ba nền điều khiển thực sự xuất hiện. --ke (#DEDED6) chỉ dùng cho đường phân
   cách trang trí, không bao giờ cho ranh giới điều khiển. */
.btn-outline,.hdr .srch{border-color:var(--ke-dam);border-width:1px}
.btn-outline:hover,.hdr .srch:hover{border-color:var(--nhan-chu);background:var(--nhan-mo)}
input,select,textarea{border-color:var(--ke-dam)}
:focus-visible{outline:3px solid var(--nhan-chu);outline-offset:2px}

/* ---- C. trạng thái hàng: màu NGỮ NGHĨA, kèm hình dạng ----------------------------------------
   Nghĩa và nhãn không đổi: IN_STOCK "Còn hàng" · LOW "Còn ít" · OUT "Hết" · UNKNOWN "Chưa rõ".
   Chỉ đổi màu và thêm HÌNH DẠNG cho chấm, để trạng thái không phân biệt bằng riêng màu:
     IN_STOCK  đĩa đặc tròn       LOW  ô vuông bo nhẹ       OUT/UNKNOWN  vòng rỗng
   Không sửa markup, không sửa chữ, không sửa freshness guard. */
.dot{border:0}
.dot[data-tg-avail="IN_STOCK"]{background:var(--con-hang);border-radius:50%}
.dot[data-tg-avail="LOW"]{background:var(--sap-het);border-radius:1px}
.dot[data-tg-avail="OUT"],.dot[data-tg-avail="UNKNOWN"]{background:transparent;
  border:1.5px solid var(--het);border-radius:50%}

/* khối "Có tại cửa hàng" trên trang sản phẩm: nền trung tính thay nền teal nhạt */
.avail{background:var(--nen-2);border:1px solid var(--ke)}
.avail h2{color:var(--muc-2);font-family:var(--tg-font-display);font-weight:700}
.avail .row:has(.st[data-tg-avail="IN_STOCK"]){background:var(--con-hang-mo);border-color:var(--con-hang-ke)}
.avail .st[data-tg-avail="IN_STOCK"]{color:var(--con-hang);font-weight:700}
.avail .row:has(.st[data-tg-avail="LOW"]){background:var(--sap-het-mo);border-color:var(--sap-het-ke)}
.avail .st[data-tg-avail="LOW"]{color:var(--sap-het);font-weight:700}
.avail .st[data-tg-avail="OUT"],.avail .st[data-tg-avail="UNKNOWN"]{color:var(--het)}
/* dải dữ liệu quá 6h: vàng cảnh báo, không bao giờ đọc thành "hết hàng" */
.stalebanner{background:var(--sap-het-mo);color:var(--sap-het);border-top-color:var(--sap-het-ke)}

/* ---- D. thẻ sản phẩm --------------------------------------------------------------------------
   Bố cục thẻ giữ nguyên (khung 4:5, ảnh → tên → giá+thương hiệu → size → cơ sở → CTA).
   Bóng đã bỏ khỏi token nên mép thẻ phải do đường kẻ 1px gánh — dùng --ke thay --ke-nhat.
   Ảnh vẫn object-fit:contain: ảnh nguồn không đồng nhất nền, contain giữ trọn sản phẩm. */
.card{border-color:var(--ke)}
.card .im{background:var(--mat);border-bottom-color:var(--ke)}
.card .n{color:var(--muc)}
.card .br{color:var(--muc-3)}
.card .sizes span{border-color:var(--ke-dam);color:var(--muc-2);background:var(--mat)}
.card .cardcta{color:var(--nhan-chu);font-weight:700}
@media(hover:hover){.card:hover{border-color:var(--ke-dam);transform:translateY(-1px);
  transition:border-color .15s,transform .15s}}
/* chip cơ sở: đặc = còn hàng, nền nhạt = còn ít, viền rỗng = hết/chưa rõ */
.card .sch{border-color:var(--ke-dam);color:var(--muc-2)}
.card .sch:has(.dot[data-tg-avail="IN_STOCK"]){background:var(--con-hang);border-color:var(--con-hang);color:#fff}
.card .sch:has(.dot[data-tg-avail="IN_STOCK"]) .dot{background:#fff}
.card .sch:has(.dot[data-tg-avail="LOW"]){background:var(--sap-het-mo);border-color:var(--sap-het-ke);color:var(--sap-het)}
.card .sch:has(.dot[data-tg-avail="LOW"]) .dot{background:var(--sap-het)}
.card .sch:has(.dot[data-tg-avail="OUT"]) .dot,
.card .sch:has(.dot[data-tg-avail="UNKNOWN"]) .dot{border-color:var(--het);background:transparent}
/* giá to hơn một nấc và không bị co: đây là thông tin khách đọc trước tiên.
   tabular-nums bù lại bề ngang nên hàng "giá + thương hiệu" vẫn vừa thẻ 173px ở 360px. */
.card .p{font-size:17px;line-height:22px}
@media(min-width:720px){.card .p{font-size:18px;line-height:24px}}

/* ---- E. nhãn & chip khác ----------------------------------------------------------------------
   Chip "Đang mở" và badge mùa bỏ nền màu nhấn: giờ mở cửa là thông tin, không phải hành động. */
.hero .kicker,.newin{background:var(--nen-2);color:var(--muc-2);font-family:var(--tg-font-display);
  font-weight:700;letter-spacing:.02em}
.openchip[data-tg-open="open"]{background:var(--con-hang-mo);color:var(--con-hang)}
.openchip[data-tg-open="soon"]{background:var(--sap-het-mo);color:var(--sap-het)}
.pchip{background:var(--nen-2);color:var(--muc-2)}

/* ---- F. sửa sau khi soi bằng trình duyệt ------------------------------------------------------
   Hai chỗ đang mượn nhầm màu nhấn cho thông tin không phải hành động. Cam là màu hành động;
   dòng "tồn kho cập nhật lúc..." và dấu ✓ cam kết đều là thông tin, không phải nút. */
.freshnote{background:var(--nen-2);border:1px solid var(--ke);color:var(--muc-2)}
.freshnote b{color:var(--muc)}
.trust li::before{color:var(--muc-2)}
/* dải thông tin nhấn ở trang nội dung: kẻ trái giữ cam (đây là chỗ dẫn tới hành động) */
.nap{border-left-color:var(--nhan-chu)}

/* ---- G. chú giải tên cơ sở: chữ giải thích, không phải liên kết ------------------------------
   <StoreLegend> render một <p class="legend"> thuần chữ — không có <a>, không bấm được, chỉ mở
   rộng "T.Thiệp" thành "Tôn Thất Thiệp". Trước đó nó dùng --tg-link nên đọc như một liên kết.
   Cam chỉ dành cho thứ bấm được. Ở đây phân biệt bằng ĐẬM + mực đậm hơn, không bằng màu nhấn.
   Dùng ở: trang chủ · danh mục · trang sản phẩm · /mua-dong/ · trang cửa hàng · /en/tam-coc/.
   Trạng thái tồn kho, nhãn cơ sở và URL không đổi. */
.legend b{color:var(--muc);font-weight:700}


/* ---- H. ảnh hero trang chủ (14.09.2026) --------------------------------------------------------
   Ảnh mặt tiền cửa hàng nằm trong KHUNG RIÊNG cạnh chữ, không có chữ đè lên ảnh. Nhờ vậy tương phản
   của tiêu đề, phụ đề và hai nút KHÔNG phụ thuộc vào tấm ảnh — đổi ảnh sau này không thể làm hỏng
   khả năng đọc. Một ảnh tĩnh: không carousel, không tự chạy, không hiệu ứng.
   Ảnh chỉ CẮT chứ không kéo méo: object-fit:cover trên khung tỉ lệ cố định, tỉ lệ gốc giữ nguyên.

   1440px : chữ trên-trái · ba ô sản phẩm dưới-trái · ảnh cao hết cột phải
   <860px : tiêu đề → phụ đề → hai nút → ảnh 4:3 → chú thích. BA Ô SẢN PHẨM ẨN.
            Ẩn chứ không xoá: ba thẻ <a> vẫn nằm trong HTML nên ba liên kết nội bộ tới trang sản
            phẩm vẫn còn, và lưới sản phẩm phía dưới không đổi.
            Ảnh của ba ô chuyển sang loading="lazy" (index.astro). Đo bằng Chrome ở 390px: trang
            tải 8 tệp ảnh, bản trước tải 11 — ba dẫn xuất -360.webp mà bản trước tải RIÊNG cho ba
            ô đã biến mất, vì ba sản phẩm đó cũng nằm trong lưới phía dưới và dùng chung tệp
            -480.webp. Đừng bỏ loading="lazy": bỏ đi là ba tệp -360.webp quay lại (~44 KB thừa).
   Mọi luật dưới đây đều nằm trong .hero-photo: header, menu và các khối ngoài hero không bị chạm. */
.hero.hero-photo .hero-media{margin:var(--tg-s5) 0 0;display:flex;flex-direction:column;gap:var(--tg-s2)}
.hero.hero-photo .hero-media picture{display:block;min-height:0}
.hero.hero-photo .hero-media img{width:100%;aspect-ratio:4/3;object-fit:cover;object-position:50% 50%;
  border:1px solid var(--ke);border-radius:var(--bo);background:var(--nen-2)}
.hero.hero-photo .hero-media figcaption{font-size:var(--tg-fs-xs);line-height:1.45;color:var(--muc-2)}
.hero.hero-photo .hero-media figcaption a{color:var(--nhan-chu);font-weight:700;text-decoration:none;white-space:nowrap}
.hero.hero-photo .hero-media figcaption a:hover{text-decoration:underline}
@media(max-width:859px){
  .hero.hero-photo .hero-grid{display:none}
}
@media(min-width:860px){
  .hero.hero-photo.hero-tiles{grid-template-columns:1fr 1fr;grid-template-areas:"copy media" "tiles media";
    align-items:start;column-gap:var(--tg-s6);row-gap:var(--tg-s5)}
  .hero.hero-photo .hero-copy{grid-area:copy}
  .hero.hero-photo .hero-grid{grid-area:tiles;margin-top:0}
  .hero.hero-photo .hero-media{grid-area:media;margin:0;height:100%;min-height:340px}
  .hero.hero-photo .hero-media picture{flex:1 1 auto;display:block}
  .hero.hero-photo .hero-media img{height:100%;aspect-ratio:auto;min-height:300px}
}

/* Trang huong dan size + doan gioi thieu cua hang (14/09, sau GSC audit) */
.storeintro{margin:.75rem 0 0;max-width:62ch;line-height:1.55}
.sizetable{border-collapse:collapse;margin:.5rem 0 1rem}
.sizetable th,.sizetable td{border:1px solid var(--line,#ddd);padding:.35rem .9rem;text-align:left}
.sizetable th{font-weight:600}


/* ============================================================================================
   ĐỢT 1 — 16/09/2026 (hướng A, audit 15/09: F5 · F10 · F11 · F12 · F15). Cùng token, cùng font,
   cùng logo. Đổi: menu 7 mục (mega-menu desktop / panel 2 cấp mobile), thẻ sản phẩm v2, hub theo
   giới, ô "mua theo nhu cầu", liên kết nội bộ quanh trang danh mục, gợi ý ở trang tìm kiếm.
   Luật màu giữ nguyên: cam (--tg-brand*) chỉ cho thứ bấm được; trạng thái tồn phân biệt bằng HÌNH
   DẠNG + màu (tokens.css "Hình dạng"). Không nền tối. Không đụng PDP.
   ============================================================================================ */

/* ---- I. desktop nav: mỗi mục là .navi = link + (tuỳ) .mega mở bằng hover / focus-within ---- */
.nav{overflow:visible;align-items:stretch}
.navi{position:relative;display:flex;align-items:center;flex:0 0 auto}
.navi>a{display:inline-flex;align-items:center;min-height:var(--tg-touch)}
.navi-accent>a{color:var(--tg-brand-ink)}
.navi-within>a{color:var(--tg-ink);box-shadow:inset 0 -3px 0 var(--tg-line)}
.mega{position:absolute;top:100%;left:0;min-width:260px;max-width:min(92vw,720px);z-index:40;
  background:var(--tg-surface);border:1px solid var(--tg-line);border-top:3px solid var(--tg-brand);
  border-radius:0 0 var(--tg-radius) var(--tg-radius);box-shadow:var(--tg-shadow);padding:var(--tg-s2) 0 0;
  opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .12s,transform .12s,visibility 0s .12s}
.navi.has-mega:hover>.mega,.navi.has-mega:focus-within>.mega{opacity:1;visibility:visible;transform:none;transition-delay:0s}
/* a small gap so the pointer can travel from the label into the panel without it closing */
.navi.has-mega::after{content:"";position:absolute;left:0;right:0;top:100%;height:8px}
/* Hotfix 17/09: cột PHẢI đo theo nội dung. minmax(0,1fr) có cận dưới là số 0 xác định, nên khi trình
   duyệt tính bề rộng nội tại của .mega (position:absolute → shrink-to-fit) hai cột đóng góp 0: panel
   luôn tụt về đúng min-width 260px ở mọi màn hình, rồi nhãn dài (white-space:nowrap) tràn ra ngoài ô
   và đè lên cột bên cạnh ("Mùa đông", "Thương hiệu"). Cận dưới max-content khiến panel rộng theo nhãn
   thật; 1fr vẫn cân bằng hai cột khi còn dư. max-width bên trên vẫn giữ panel trong khung nhìn. */
.mega-list{list-style:none;margin:0;padding:0 var(--tg-s2);display:grid;grid-template-columns:repeat(2,minmax(max-content,1fr));gap:0 var(--tg-s3)}
.mega-list a{display:flex;justify-content:space-between;gap:var(--tg-s5);align-items:center;min-height:40px;padding:var(--tg-s1) var(--tg-s3);
  border-radius:var(--tg-radius-sm);text-decoration:none;color:var(--tg-ink);font-size:var(--tg-fs-sm);font-weight:500}
.mega-list a:hover,.mega-list a:focus-visible{background:var(--tg-surface-2)}
.mega-list a[aria-current="page"]{color:var(--tg-brand-ink);font-weight:700}
/* Chặn trên cho nhãn: một tên thật dài (thương hiệu mới) sẽ XUỐNG DÒNG trong ô của nó chứ không đẩy
   panel vượt max-width rồi tràn ra như cũ. 260px rộng hơn mọi nhãn hiện có nên hôm nay không ai bị ngắt. */
.mega-t{max-width:260px;line-height:var(--tg-lh-tight)}
/* số mẫu có vùng riêng: không co, không bị chữ đè lên, cách nhãn tối thiểu --tg-s5 (24px) */
.mega-n{flex:0 0 auto;font-size:var(--tg-fs-2xs);color:var(--tg-ink-3);font-weight:500;font-variant-numeric:tabular-nums}
.mega-all{display:flex;align-items:center;min-height:44px;margin-top:var(--tg-s2);padding:0 var(--tg-s4);
  border-top:1px solid var(--tg-line-2);text-decoration:none;color:var(--tg-link);font-weight:600;font-size:var(--tg-fs-sm)}
.mega-all:hover{background:var(--tg-surface-2)}
/* the last two items open toward the left edge of the row so the panel never leaves the viewport */
.navi:nth-last-child(-n+3)>.mega{left:auto;right:0}
@media(min-width:860px) and (max-width:1023px){.nav a{padding:0 9px;font-size:14px}}

/* ---- J. mobile panel: 2 cấp bằng <details>, hàng ≥ 48px, mục đang xem mở sẵn ---- */
/* Chrome giữ "layout ma" cho nội dung của <details> đang đóng (content-visibility): panel 390px bị đo thành
   khung 119px và mũi tên chevron "tràn" ra x=398 dù không hề vẽ — ui-regression mục 6 bắt nhầm. Tắt hẳn khi đóng. */
.menu:not([open]) .menu-panel{display:none}
.menu-panel .msub-d{border:0}
.menu-panel .msub-sum{display:flex;align-items:center;gap:var(--tg-s2);min-height:48px;padding:0 var(--tg-s4);cursor:pointer;
  list-style:none;font-size:var(--tg-fs-md);font-weight:600;color:var(--tg-ink);-webkit-tap-highlight-color:transparent}
.menu-panel .msub-sum::-webkit-details-marker{display:none}
.menu-panel .msub-sum::marker{content:""}
.menu-panel .msub-sum:hover{background:var(--tg-surface-2)}
.menu-panel .msub-sum .msub-n{margin-left:auto;font-size:var(--tg-fs-2xs);font-weight:500;color:var(--tg-ink-3)}
.menu-panel .msub-sum .chev{flex:0 0 auto;color:var(--tg-ink-3);transition:transform .15s}
.menu-panel .msub-d[open]>.msub-sum{background:var(--tg-surface-2)}
.menu-panel .msub-d[open]>.msub-sum .chev{transform:rotate(180deg)}
.menu-panel .msub-accent .msub-sum>span:first-child{color:var(--tg-brand-ink)}
.menu-panel .msub-list{padding:0 0 var(--tg-s2);background:var(--tg-bg)}
.menu-panel .msub-list a{min-height:44px;padding-left:var(--tg-s6);font-size:var(--tg-fs-sm);font-weight:500;justify-content:space-between;gap:var(--tg-s3)}
.menu-panel .msub-list a .msub-n{font-size:var(--tg-fs-2xs);color:var(--tg-ink-3);font-variant-numeric:tabular-nums}
.menu-panel .msub-list .msub-all{color:var(--tg-link);font-weight:600}

/* ---- K. thẻ sản phẩm v2: 1 link, ảnh 4:5 · tên · giá + hãng · 3 dấu cửa hàng (hình dạng ≠ màu) ---- */
a.card2{text-decoration:none;color:var(--tg-ink)}
a.card2 .im,a.card2 .b,a.card2 .n,a.card2 .pb,a.card2 .storeslot,a.card2 .marks,a.card2 .noimg{display:block}
a.card2 .im{position:relative}
a.card2 .noimg{position:relative;height:100%}
a.card2 .b{display:flex;flex-direction:column;gap:6px;padding:10px 10px 12px;flex:1}
a.card2 .n{min-height:36px}
a.card2 .pb{display:flex}
a.card2 .storeslot{min-height:20px;margin-top:auto}
a.card2 .marks{display:flex;gap:10px;align-items:center;padding-top:2px}
a.card2 .mk{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px}
a.card2 .mk .dot{width:10px;height:10px;box-sizing:border-box}
/* hình dạng theo tokens.css: IN_STOCK đĩa tròn đặc · LOW ô vuông bo nhẹ · OUT/UNKNOWN vòng rỗng */
a.card2 .dot[data-tg-avail="IN_STOCK"]{border-radius:50%;background:var(--tg-ok)}
a.card2 .dot[data-tg-avail="LOW"]{border-radius:2px;background:var(--tg-low)}
a.card2 .dot[data-tg-avail="OUT"],a.card2 .dot[data-tg-avail="UNKNOWN"]{border-radius:50%;background:transparent;border:1.5px solid var(--tg-out)}
a.card2:focus-visible{outline:2px solid var(--tg-brand);outline-offset:2px}
.grid{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:560px){.grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(min-width:860px){.grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(min-width:1100px){.grid{grid-template-columns:repeat(5,minmax(0,1fr))}}
/* the "3 dấu = T.Thiệp · N.Trãi · Tam Cốc" key already sits above every grid (.legend) */
.legend .lg-shapes{display:inline-flex;gap:6px;align-items:center;margin-left:var(--tg-s2);vertical-align:middle}
.legend .lg-shapes i{display:inline-block;width:9px;height:9px;box-sizing:border-box}
.legend .lg-ok{border-radius:50%;background:var(--tg-ok)}
.legend .lg-low{border-radius:2px;background:var(--tg-low)}
.legend .lg-out{border-radius:50%;border:1.5px solid var(--tg-out)}

/* ---- L. hub theo giới: ô loại có ảnh + số mẫu + chip nhóm con ---- */
.hubs{display:grid;gap:var(--tg-s3);grid-template-columns:repeat(2,minmax(0,1fr));margin:var(--tg-s4) 0}
@media(min-width:720px){.hubs{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--tg-s4)}}
@media(min-width:1024px){.hubs{grid-template-columns:repeat(4,minmax(0,1fr))}}
.hub{background:var(--tg-surface);border:1px solid var(--tg-line-2);border-radius:var(--tg-radius);overflow:hidden;display:flex;flex-direction:column}
.hub-main{display:flex;flex-direction:column;text-decoration:none;color:var(--tg-ink)}
.hub-im{display:block;aspect-ratio:5/4;background:var(--tg-surface-2);border-bottom:1px solid var(--tg-line-2);overflow:hidden}
.hub-im img{width:100%;height:100%;object-fit:contain;padding:6px;box-sizing:border-box}
.hub-im .noimg{display:block;height:100%;background:var(--tg-surface-2) url('/brand/the-gate-mark.svg') no-repeat center/36% auto;opacity:.5}
.hub-t{display:flex;justify-content:space-between;align-items:baseline;gap:var(--tg-s2);padding:10px 10px 8px;min-height:44px;box-sizing:border-box}
.hub-t b{font-size:var(--tg-fs-md);font-weight:600}
.hub-t span{font-size:var(--tg-fs-2xs);color:var(--tg-ink-3);white-space:nowrap}
.hub-main:hover .hub-t b{color:var(--tg-brand-ink)}
.hub-subs{display:flex;flex-wrap:wrap;gap:6px;padding:0 10px 10px}
.hub-subs a{display:inline-flex;align-items:center;gap:4px;min-height:40px;padding:0 12px;border:1px solid var(--tg-line);border-radius:var(--tg-radius);
  text-decoration:none;color:var(--tg-ink-2);font-size:var(--tg-fs-2xs);font-weight:500;background:var(--tg-bg)}
.hub-subs a span{color:var(--tg-ink-3)}
.hub-subs a:hover{border-color:var(--tg-brand);color:var(--tg-brand-ink)}

/* ---- M. trang chủ: ô "mua theo nhu cầu" ---- */
.needs{display:grid;gap:var(--tg-s2);grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:560px){.needs{grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--tg-s3)}}
@media(min-width:1024px){.needs{grid-template-columns:repeat(8,minmax(0,1fr))}}
.need{display:flex;align-items:center;gap:10px;min-height:56px;padding:6px;background:var(--tg-surface);border:1px solid var(--tg-line-2);
  border-radius:var(--tg-radius);text-decoration:none;color:var(--tg-ink)}
.need-im{flex:0 0 48px;width:48px;height:56px;background:var(--tg-surface-2);border-radius:var(--tg-radius-sm);overflow:hidden}
.need-im img{width:100%;height:100%;object-fit:contain;padding:2px;box-sizing:border-box}
.need-t{display:flex;flex-direction:column;gap:2px;min-width:0}
.need-t b{font-size:var(--tg-fs-sm);font-weight:600;line-height:1.2}
.need-t span{font-size:var(--tg-fs-2xs);color:var(--tg-ink-3)}
.need:hover{border-color:var(--tg-brand)}
.need:hover .need-t b{color:var(--tg-brand-ink)}
@media(min-width:1024px){.need{flex-direction:column;align-items:stretch;text-align:center;gap:6px;padding:8px}
  .need-im{width:auto;height:auto;aspect-ratio:1/1;flex:0 0 auto}}

/* ---- N. liên kết quanh trang danh mục + gợi ý tìm kiếm ---- */
.chiprow-wrap{flex-wrap:wrap;overflow:visible;padding-right:0}
.kin{margin:0 0 var(--tg-s3)}
.gchip-up{color:var(--tg-ink-2)}
.kin-more .sec-head{margin-bottom:var(--tg-s2)}
.shome{display:grid;gap:var(--tg-s5);margin:var(--tg-s5) 0}
@media(min-width:860px){.shome{grid-template-columns:repeat(3,minmax(0,1fr))}}
.shome-sec h2{font-size:var(--tg-fs-lg);margin-bottom:var(--tg-s2)}
.shome-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.shome-list a{display:flex;justify-content:space-between;align-items:center;gap:var(--tg-s3);min-height:44px;padding:0 var(--tg-s2);
  border-bottom:1px solid var(--tg-line-2);text-decoration:none;color:var(--tg-ink);font-weight:500;font-size:var(--tg-fs-sm)}
.shome-list a:hover{color:var(--tg-brand-ink)}
/* 12px counters use --tg-ink-2 (7.1:1), not ink-3: Lighthouse a11y flagged the footer copy at 3.7:1 when it
   inherited + opacity .7. No opacity on text anywhere in this block. */
.fnum{font-size:var(--tg-fs-2xs);color:var(--tg-ink-2);font-weight:400;font-variant-numeric:tabular-nums}
.ftr .fnum{color:inherit}
.mega-n,.msub-n,.menu-panel .msub-list a .msub-n,.hub-t span,.hub-subs a span,.need-t span{color:var(--tg-ink-2)}
/* home, phones only: the winter shelf shows 8 of its 12 cards (links stay in the HTML, same as .grid-more) */
@media(max-width:719px){.grid-home .card:nth-child(n+9){display:none}}

/* ============================================================================================
   ĐỢT 2 — 17/09/2026. Bố cục trang chủ và trang sản phẩm. Cùng token, cùng font, cùng logo,
   cùng bảng màu "Đá vôi". KHÔNG đổi: URL, taxonomy, nguồn tồn kho, schema, cơ chế publish,
   đích Zalo/Gọi/Chỉ đường, freshness-guard, nhãn trạng thái hàng.
   Đặt ở cuối file, sau mọi khối khác, để duyệt hoặc gỡ bỏ độc lập — cùng quy ước các đợt trước.

   Đo trên bản dựng từ d470045 trước khi viết dòng nào (qa/dot2/measure_truoc.json):
     · trang chủ 390px: hai khối điều hướng dính nhau y=591→1145; hai lưới sản phẩm gần giống hệt
       nhau cộng lại 2.319px; "Ba cửa hàng" không ảnh, nút liên hệ cao 32px;
     · PDP 1440px: cột ảnh cao 858px, cột thông tin chạy tới 1793px → nửa trái trống ~830px,
       trong khi khối liên hệ 665px bị nhồi vào cột phải 513px và chỉ xếp được 2 cột.
   ============================================================================================ */

/* ---- O. trang chủ ----------------------------------------------------------------------------- */

/* O1. "The Gate bán gì": 4 ô LỚN có ảnh = cấp 1. Trước đây 4 ô hub và 4 ô loại cùng cỡ (.needs) nên
   "Đồ nữ 441 mẫu" đứng ngang "Đồ bơi nữ 48 mẫu". Ô lớn + chip nhỏ tách hẳn hai cấp. */
.segs{display:grid;gap:var(--tg-s3);grid-template-columns:repeat(2,minmax(0,1fr));margin:0 0 var(--tg-s5)}
@media(min-width:720px){.segs{grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--tg-s4)}}
.seg{display:flex;flex-direction:column;text-decoration:none;color:var(--tg-ink);background:var(--tg-surface);
  border:1px solid var(--tg-line);border-radius:var(--tg-radius);overflow:hidden}
.seg-im{display:block;aspect-ratio:4/3;background:var(--tg-surface-2);border-bottom:1px solid var(--tg-line-2);overflow:hidden}
.seg-im img{width:100%;height:100%;object-fit:contain;padding:8px;box-sizing:border-box}
.seg-im .noimg{display:block;height:100%;background:var(--tg-surface-2) url('/brand/the-gate-mark.svg') no-repeat center/32% auto;opacity:.45}
.seg-t{display:flex;flex-direction:column;gap:2px;padding:10px 12px 12px;min-height:56px;box-sizing:border-box}
.seg-t b{font-size:var(--tg-fs-md);font-weight:700;line-height:1.25}
.seg-t span{font-size:var(--tg-fs-2xs);color:var(--tg-ink-2);font-variant-numeric:tabular-nums}
@media(hover:hover){.seg:hover{border-color:var(--ke-dam)}.seg:hover .seg-t b{color:var(--tg-brand-ink)}}
.seg:focus-visible{outline:3px solid var(--nhan-chu);outline-offset:2px}

/* O2. nhãn của hàng chip lối tắt = cấp 2. Cỡ chữ phụ, không phải <h2>, nên cấp bậc tiêu đề của
   trang không đổi (h1 → h2 mỗi khối, không chèn h3 giả). */
.sec-sub{margin:0 0 var(--tg-s2);font-size:var(--tg-fs-sm);font-weight:600;color:var(--tg-ink-2)}

/* O3. thẻ cửa hàng trang chủ: ảnh mặt tiền thật + ba hành động ≥44px (trước là 32px).
   .storegrid-home giới hạn phạm vi — .storegrid ở /cua-hang/ và /ve-chung-toi/ không đổi. */
.storegrid-home .stile2{padding:0;gap:0;overflow:hidden;border-color:var(--ke)}
.stile2 .stile-main{gap:0}
.stile-im{display:block;aspect-ratio:16/9;background:var(--tg-surface-2);border-bottom:1px solid var(--tg-line-2);overflow:hidden}
.stile-im img{width:100%;height:100%;object-fit:cover;display:block}
.stile2 .stile-b{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:var(--tg-s3) var(--tg-s4) var(--tg-s2)}
.stile2 .stile-b b{font-size:var(--tg-fs-md)}
.stile2 .stile-a{font-size:13px;color:var(--tg-ink-2);line-height:1.4}
.stile2 .stile-acts{margin:0;padding:0 var(--tg-s4) var(--tg-s3);gap:var(--tg-s2);flex-wrap:wrap}
/* ngưỡng chạm: 44px cao, cách nhau ≥8px (--tg-s2). Vẫn là liên kết chữ, không phải nút đặc — đây là
   khối giới thiệu cửa hàng, hành động chính của trang chủ vẫn là xem mẫu. */
.stile2 .stile-acts a{min-height:var(--tg-touch);display:inline-flex;align-items:center;padding:0 var(--tg-s3);
  border:1px solid var(--ke-dam);border-radius:var(--tg-radius);font-size:13px;font-weight:600;
  color:var(--tg-link);text-decoration:none;background:var(--tg-surface)}
.stile2 .stile-acts a:hover{background:var(--nhan-mo);border-color:var(--nhan-chu);text-decoration:none}
@media(hover:hover){.storegrid-home .stile2:hover{border-color:var(--ke-dam)}}

/* O4. dải "hàng VNXK là gì": chữ giải thích, không phải khối hành động — nền phụ, kẻ trái mực,
   KHÔNG dùng cam (cam chỉ dành cho thứ bấm được; ba liên kết bên trong mới là cam). */
.vnxk{background:var(--nen-2);border:1px solid var(--ke);border-left:3px solid var(--muc-2);
  border-radius:var(--tg-radius);padding:var(--tg-s4) var(--tg-s5)}
.vnxk h2{font-size:var(--tg-fs-lg);margin-bottom:var(--tg-s2)}
.vnxk p{max-width:70ch;font-size:var(--tg-fs-sm);color:var(--tg-ink-2);margin-bottom:var(--tg-s3)}
.vnxk-links{display:flex;flex-wrap:wrap;gap:var(--tg-s2) var(--tg-s5);margin:0}
.vnxk-links a{display:inline-flex;align-items:center;min-height:var(--tg-touch);
  font-size:var(--tg-fs-sm);font-weight:700;color:var(--tg-link);text-decoration:none}
.vnxk-links a:hover{text-decoration:underline}

/* ---- P. PDP: khối liên hệ thành băng rộng cả trang ------------------------------------------- */

/* P1. Lưới mới ở ≥860px.
     "gal head"   ảnh trái, tên+giá phải
     "gal top"    ảnh trái, size + có tại cửa hàng phải
     "gal free"   hàng RỖNG cỡ 1fr — nó nuốt phần cao thừa của cột ảnh, nhờ vậy "head" và "top"
                  dính liền nhau ở đỉnh cột phải. Không có hàng này thì grid chia đều chỗ thừa cho
                  hai hàng auto và đẩy khối size xuống ~240px dưới giá (đo khi thử).
     "cont cont"  NHẮN HOẶC GỌI CỬA HÀNG — rộng cả trang, ba thẻ dàn ngang
     "rest rest"  mua online + thông số + cam kết — rộng cả trang, hai cột
   Thứ tự DOM không đổi so với trước, nên thứ tự đọc trên mobile, thứ tự Tab và thứ tự của trình
   đọc màn hình vẫn là: tên → giá → ảnh → size → cửa hàng → liên hệ → thông số. */
@media(min-width:860px){
  .pdp{grid-template-columns:minmax(0,1.05fr) minmax(340px,.95fr);
    grid-template-areas:"gal head" "gal top" "gal free" "cont cont" "rest rest";
    grid-template-rows:auto auto 1fr auto auto;
    gap:var(--tg-s3) var(--tg-s7);align-content:stretch}
  .gal{grid-area:gal;align-self:start}
  .info-head{grid-area:head}
  .info-top{grid-area:top}
  .scontact{grid-area:cont}
  .info-rest{grid-area:rest}
}

/* P2. Ba thẻ liên hệ dàn ngang. Ở băng rộng cả trang thì auto-fit của bản sửa 17/09 tự cho ra 3 cột;
   giữ nguyên auto-fit (không quay lại repeat(3,1fr)) để nếu khung hẹp lại vì bất kỳ lý do gì thì số
   cột vẫn co theo chỗ THẬT SỰ có, chứ không tràn như lỗi đã sửa. */
.scontact{margin-top:var(--tg-s6)}
@media(min-width:860px){
  .scontact{margin-top:var(--tg-s5);border-top:1px solid var(--tg-line);padding-top:var(--tg-s5)}
  .scontact-list{gap:var(--tg-s4)}
}

/* P3. Dòng trạng thái theo size trên từng thẻ liên hệ.
   Phân biệt bằng HÌNH DẠNG + chữ, không bằng riêng màu (tokens.css "Hình dạng"):
   còn hàng = đĩa tròn đặc · còn ít = ô vuông bo nhẹ · hết/chưa rõ = vòng rỗng. Nhãn chữ do
   freshness-guard ghi vào, nên nó luôn khớp với ô "Có tại cửa hàng" phía trên. */
.scard-st{display:flex;align-items:center;gap:6px;margin-top:var(--tg-s2);padding:5px 8px;
  border:1px solid var(--ke);border-radius:var(--tg-radius);background:var(--nen-2);
  font-size:var(--tg-fs-sm);font-weight:700;color:var(--tg-ink-2);width:fit-content}
.scard-st .dot{width:10px;height:10px;flex:0 0 auto;box-sizing:border-box}
.scard-st:has(.scard-stt[data-tg-avail="IN_STOCK"]){background:var(--con-hang-mo);border-color:var(--con-hang-ke)}
.scard-stt[data-tg-avail="IN_STOCK"]{color:var(--con-hang)}
.scard-st:has(.scard-stt[data-tg-avail="LOW"]){background:var(--sap-het-mo);border-color:var(--sap-het-ke)}
.scard-stt[data-tg-avail="LOW"]{color:var(--sap-het)}
.scard-st:has(.scard-stt[data-tg-avail="OUT"]),.scard-st:has(.scard-stt[data-tg-avail="UNKNOWN"]){
  background:transparent;border-color:var(--ke)}
.scard-stt[data-tg-avail="OUT"],.scard-stt[data-tg-avail="UNKNOWN"]{color:var(--het)}
/* nhãn "tình trạng dưới đây là của …" — chữ phụ, đổi khi khách chạm một size */
.scontact-scope{margin:0 0 var(--tg-s3);font-size:var(--tg-fs-xs);color:var(--tg-ink-2)}
.scontact-scope b{color:var(--tg-ink);font-weight:700}

/* P4. Nút trong thẻ liên hệ.
   ≥860px thẻ giờ rộng ~370px (băng cả trang chia 3) thay vì ~218px (cột hẹp chia 2), nên ba nút xếp
   được hai hàng gọn: Zalo full, rồi Gọi + Chỉ đường cùng hàng. Trước đó mỗi nút chiếm trọn một hàng
   (.scard-acts .btn{flex-basis:100%} ở ≥860px) → thẻ cao 3 hàng nút. */
@media(min-width:860px){
  .scard-acts .btn{flex-basis:auto;flex:1 1 44%}
  .scard-acts .btn-primary{flex-basis:100%}
}

/* P5. Băng "mua online + thông số + cam kết": hai cột ở ≥860px, dùng đúng phần chỗ trống mà cột ảnh
   để lại. Liên kết mua online trải hết bề rộng ở trên — nó là một lối đi khác, không phải một thông số. */
@media(min-width:860px){
  .info-rest{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--tg-s7);
    align-items:start;border-top:1px solid var(--tg-line);padding-top:var(--tg-s4);margin-top:var(--tg-s2)}
  .info-rest .tjo-link{grid-column:1 / -1;margin-top:0;margin-bottom:var(--tg-s4)}
  .info-rest .attrs{grid-column:1;margin:0}
  .info-rest .trust{grid-column:2;margin:0}
}

/* P6. Thanh dính đáy mobile: nút chính rộng hơn nút phụ. Hai nút nay có hai đích khác nhau
   (#lien-he ↔ /cua-hang/), nên nút chính được ưu tiên bề ngang. */
@media(max-width:859px){.has-bar .sticky .btn-primary{flex:1.6}}

/* P7. Khung ảnh chính theo tỉ lệ thật của sản phẩm (--gal-ar do [slug].astro tính lúc dựng, kẹp
   trong [0,8 ; 1,6]). Khung 4:5 cố định để lại dải xám trên–dưới cho ~77% ảnh trong kho (820/1.445
   ảnh vuông + 296 ảnh ngang) và làm cột ảnh cao 858px ở 1440px trong khi cột quyết định chỉ ~620px.
   Khung vẫn CỐ ĐỊNH cho cả trang nên đổi ảnh trong gallery không làm nhảy bố cục; ảnh vẫn
   object-fit:contain nên không sản phẩm nào bị cắt. Mặc định 4/5 giữ nguyên nếu thiếu --gal-ar. */
.gal>img,.gal .gal-open>img{aspect-ratio:var(--gal-ar,4/5)}

/* P8. Ba thẻ liên hệ thẳng hàng nhau ở băng rộng.
   · hàng nút đẩy xuống đáy thẻ (margin-top:auto) nên ba thẻ có cùng đường nút, dù địa chỉ dài ngắn
     khác nhau và chip "Đang mở" của Tôn Thất Thiệp phải xuống dòng;
   · min-width:max-content cho hai nút viền: khi hết chỗ chúng XUỐNG HÀNG chứ không ngắt chữ, nên
     "Gọi 0942.326.993" không bao giờ bị vỡ làm hai dòng trong nút. */
.scard{display:flex;flex-direction:column}
.scard-acts{margin-top:auto}
@media(min-width:860px){
  .scard-acts .btn-outline{flex:1 1 auto;min-width:max-content}
}

/* P9. Thanh "nhắn / gọi cửa hàng" hiện lại ở desktop, nằm trong cột quyết định.
   Đợt 3 ẩn nó ở ≥860px với lý do "ba thẻ liên hệ vốn đã ở trên màn hình". Sau đợt 2 khối liên hệ là
   băng nằm DƯỚI cột ảnh: ở 1440×900 nó bắt đầu ở y=859, tức vừa khuất mép dưới. Nên đưa lại một
   NEO (#lien-he) ngay dưới khối "Có tại cửa hàng" — vừa là đường tắt sau khi chọn size, vừa lấp
   đúng khoảng trống mà cột ảnh cao hơn cột chữ để lại. Đây không phải kênh liên hệ thứ hai:
   nút vẫn dẫn tới ba thẻ có tên cửa hàng, vẫn không đoán cơ sở thay khách. */
@media(min-width:860px){
  .pdp{grid-template-areas:"gal head" "gal top" "gal bar" "cont cont" "rest rest"}
  .pdp .sticky{display:flex;grid-area:bar;align-self:start;max-width:420px;margin-top:var(--tg-s4)}
  .pdp .sticky .btn{flex:1 1 auto;min-width:max-content;font-size:var(--tg-fs-sm)}
}

/* P10. Máy tính bảng dọc (720–859px): cột ảnh không kéo hết bề rộng trang.
   Ở dải này PDP vẫn một cột, nên .gal rộng 788px ở 820px, trong khi `.gal>img{max-height:360px}`
   (luật cho điện thoại, đợt 1) vẫn có hiệu lực → khung ảnh thành 788×360, tỉ lệ 2,19 và **55–70%
   khung là nền trống** (đo bằng qa/dot2/cases.mjs trên 10 ca, trước lẫn sau đều vậy — đây là chỗ
   lãng phí có sẵn, không phải do đợt 2 sinh ra).
   Bỏ trần 360px ở dải này và giới hạn BỀ RỘNG cả cột ảnh rồi căn giữa: ảnh giữ đúng tỉ lệ --gal-ar,
   dải ảnh nhỏ nằm ngay dưới, không còn dải trống hai đầu. */
@media(min-width:720px) and (max-width:859px){
  /* `width:100%` KHÔNG thừa. .gal là ô lưới của .pdp; `margin-inline:auto` tắt `justify-self:stretch`,
     nên nếu không có bề rộng tường minh thì ô co theo bề rộng nội tại của nội dung. Lúc gallery.js
     tráo ảnh, <img> mới có naturalWidth = 0 trong vài chục tới vài trăm mili-giây → bề rộng nội tại
     tụt → cả cột ảnh và chiều cao trang co lại rồi bật về. Đo trên bản xem thử 18/09, dải này, cache
     lạnh: 8/150 lần đổi ảnh bị co, nặng nhất 560→384px và trang ngắn đi 212px trong 910ms; thêm
     width:100% thì 0/150, bố cục nền không đổi (0/150). Bỏ margin-inline:auto cũng hết co nhưng mất
     luôn việc căn giữa; đổi sang justify-self:center thì VẪN co, vì nó cũng tắt stretch. */
  .gal{width:100%;max-width:560px;margin-inline:auto}
  .gal>img,.gal .gal-open>img{max-height:none}
}

/* P11. GHI CHÚ DỌN DẸP — chưa làm ở đợt này, có chủ ý.
   Khối M ("ô mua theo nhu cầu": .needs / .need / .need-im / .need-t, ~20 dòng ở phần ĐỢT 1) nay
   KHÔNG trang nào dùng nữa: trang chủ đã thay bằng .segs + .chiprow. Tôi CỐ Ý không xoá khối M ở
   đây, vì quy ước của repo là mỗi đợt nằm gọn trong khối của nó để duyệt hoặc gỡ độc lập — xoá
   khối M nghĩa là gỡ đợt 2 sẽ phải khôi phục cả nó. Tốn ~1 KB thô (~0,3 KB nén).
   Nếu Thắng duyệt đợt 2: xoá khối M là việc dọn dẹp một dòng, làm sau khi gộp. */
