/* ══════════════════════════════════════════════════════════════════════════════
   TRANG ĐÍCH /bom-nhu-dong — CSS VIẾT TAY TOÀN BỘ

   Vì sao không dùng utility Tailwind cho trang này?
   public/css/app.css là bản ĐÃ BUILD (Tailwind v4) nhưng package.json ghim v3 →
   không rebuild được. Mọi class Tailwind chưa có trong bản build sẽ IM LẶNG mất
   tác dụng. Một trang đích sống bằng chuyển động thì không thể chấp nhận rủi ro đó,
   nên toàn bộ giao diện + kỹ xảo ở đây viết tay bằng class riêng tiền tố `pp-`
   (peristaltic pump), chỉ mượn lại các biến màu --color-* của theme.

   NGUYÊN TẮC CHUYỂN ĐỘNG (giống cách các trang đích hàng đầu chạy):
   1. Mỗi chuyển động phải MANG THÔNG TIN. Ống dày lên vì lưu lượng lớn hơn, rotor
      quay vì người đọc đang cuộn, chất lỏng chảy nhanh hơn vì tốc độ vòng cao hơn.
   2. Easing dài và chậm ở cuối (--ease) chứ không "ease" mặc định — đây là thứ
      tách một trang cao cấp khỏi một trang gắn hiệu ứng cho có.
   3. Không có gì bị ẩn vô điều kiện. Mọi trạng thái ẩn đều nằm dưới `.js-reveal`
      (class chỉ được thêm khi JS chạy) → tắt JS / JS lỗi vẫn đọc được đủ nội dung.
   4. Tôn trọng prefers-reduced-motion: tắt hết, giữ nguyên bố cục.
   ══════════════════════════════════════════════════════════════════════════════ */

.pp {
    /* `overflow-x: clip` chứ KHÔNG phải `hidden`. Cần chặn tràn ngang vì các hiệu
       ứng hiện-dần có dịch chuyển ngang (và bóng/quầng sáng tràn mép) sẽ nong
       scrollWidth của cả tài liệu ra và sinh thanh cuộn ngang. Nhưng `hidden` biến
       phần tử thành scroll container → mọi `position: sticky` bên trong (cảnh hình
       cắt tua bằng cuộn) chết lặng. `clip` cắt mà không tạo scroll container. */
    overflow-x: clip;
    /* Easing chung: bung nhanh rồi hãm rất mềm ở cuối (expo-out). */
    --ease: cubic-bezier(.16, 1, .3, 1);
    --ease-io: cubic-bezier(.65, 0, .35, 1);
    --cyan: #38bdf8;
    --cyan-soft: #7dd3fc;
    --navy: #071228;
    --gap: clamp(28px, 5vw, 56px);
    background: #fff;
}

.pp-wrap { max-width: 1152px; margin-inline: auto; padding-inline: 16px }
.pp-sec { padding: clamp(56px, 8vw, 104px) 0 }
.pp-sec-tight { padding: clamp(40px, 5vw, 64px) 0 }

/* ── Chữ ───────────────────────────────────────────────────────────────────── */
.pp-kicker {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 11px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase;
    color: var(--color-brand);
}
.pp-kicker::before {
    content: ''; width: 22px; height: 2px; border-radius: 2px; background: currentColor; opacity: .55;
    transform-origin: 0 50%; transition: transform 1s var(--ease) .12s;
}
/* Gạch kéo dài ra cùng lúc nhãn hiện. Trạng thái ẩn phải viết theo kiểu :not(.is-in)
   để khi KHÔNG có JS thì gạch mặc định đã đủ dài (không cần class nào cả). */
.js-reveal .pp-kicker[data-rv]:not(.is-in)::before { transform: scaleX(0) }
.pp-h2 {
    margin: 14px 0 0; font-size: clamp(26px, 3.6vw, 42px); font-weight: 800;
    letter-spacing: -.028em; line-height: 1.08; color: var(--color-ink);
}
.pp-h3 { margin: 0; font-size: clamp(19px, 2vw, 23px); font-weight: 800; letter-spacing: -.02em; color: var(--color-ink) }
.pp-lead { margin: 18px 0 0; max-width: 68ch; font-size: 16.5px; line-height: 1.75; color: var(--color-muted) }
.pp-lead b, .pp-p b { color: var(--color-ink); font-weight: 700 }
.pp-p { margin: 12px 0 0; max-width: 68ch; font-size: 15.5px; line-height: 1.75; color: var(--color-muted) }
.pp-narrow { max-width: 760px }

/* ── Nút ───────────────────────────────────────────────────────────────────── */
.pp-btn, .pp-btn-2 {
    position: relative; overflow: hidden; display: inline-flex; align-items: center; gap: 9px;
    border-radius: 14px; padding: 15px 26px; font-size: 15px; font-weight: 700;
    text-decoration: none; border: 0; cursor: pointer;
    transform: translate3d(var(--mgx, 0px), var(--mgy, 0px), 0);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease), background-color .25s;
}
.pp-btn { background: #fff; color: #0b2f6b; box-shadow: 0 18px 38px -16px rgba(2, 8, 24, .75) }
.pp-btn:hover { box-shadow: 0 26px 50px -18px rgba(2, 8, 24, .85) }
.pp-btn-2 { color: #fff; border: 1px solid rgba(255, 255, 255, .32); background: rgba(255, 255, 255, .06) }
.pp-btn-2:hover { background: rgba(255, 255, 255, .14) }
/* Dải sáng quét qua nút khi hover — chi tiết nhỏ nhưng là dấu hiệu của trang cao cấp. */
.pp-btn::after, .pp-btn-2::after {
    content: ''; position: absolute; top: 0; bottom: 0; left: -60%; width: 42%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .75), transparent);
    transform: skewX(-18deg); opacity: 0; transition: none;
}
.pp-btn-2::after { background: linear-gradient(100deg, transparent, rgba(125, 211, 252, .45), transparent) }
.pp-btn:hover::after, .pp-btn-2:hover::after { animation: ppShine .85s var(--ease-io) forwards }
@keyframes ppShine { from { left: -60%; opacity: .9 } to { left: 120%; opacity: 0 } }

.pp-btn-solid {
    display: inline-flex; align-items: center; gap: 8px; border-radius: 13px; padding: 14px 24px;
    font-size: 15px; font-weight: 700; text-decoration: none; color: #fff;
    background: linear-gradient(135deg, var(--color-brand), #0b3f8f);
    box-shadow: 0 16px 34px -14px rgba(20, 102, 214, .75);
    transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.pp-btn-solid:hover { transform: translateY(-2px); box-shadow: 0 24px 44px -14px rgba(20, 102, 214, .85) }
.pp-btn-line {
    display: inline-flex; align-items: center; gap: 8px; border-radius: 13px; padding: 14px 24px;
    font-size: 15px; font-weight: 700; text-decoration: none; color: var(--color-ink);
    border: 1px solid var(--color-line); background: #fff;
    transition: border-color .25s, color .25s, transform .35s var(--ease);
}
.pp-btn-line:hover { border-color: var(--color-brand); color: var(--color-brand); transform: translateY(-2px) }

/* ══ 1. HỆ THỐNG HIỆN DẦN KHI CUỘN ═════════════════════════════════════════
   Chỉ có tác dụng khi <html> có .js-reveal → không JS thì nội dung hiện bình thường. */
.js-reveal [data-rv] {
    opacity: 0; will-change: opacity, transform;
    transition: opacity .8s var(--ease), transform 1.05s var(--ease),
                clip-path 1s var(--ease), filter .8s var(--ease);
    transition-delay: var(--rvd, 0ms);
}
/* Nhấc lên + nở rất nhẹ: chỉ dịch thẳng đứng thì khối "nhảy" vào, thêm 1,5% scale
   là mắt đọc thành "trôi vào" — đây là chỗ tạo cảm giác mềm. */
.js-reveal [data-rv="up"]    { transform: translate3d(0, 34px, 0) scale(.985) }
.js-reveal [data-rv="soft"]  { transform: translate3d(0, 22px, 0); filter: blur(6px) }
.js-reveal [data-rv="mask"]  { clip-path: inset(0 0 100% 0); transform: translate3d(0, 24px, 0) }
.js-reveal [data-rv="left"]  { transform: translate3d(-28px, 0, 0) }
.js-reveal [data-rv="right"] { transform: translate3d(28px, 0, 0) }
.js-reveal [data-rv="scale"] { transform: scale(.93); filter: blur(8px) }
/* Hàng bảng cũng hiện dần được: <tr> nhận transform bình thường. */
.js-reveal tr[data-rv] { transform: translate3d(0, 14px, 0) }
.js-reveal [data-rv].is-in { opacity: 1; transform: none; filter: none; will-change: auto }
/* Trạng thái cuối của kiểu "mask" phải nới ra ngoài hộp, KHÔNG dùng inset(0):
   inset(0) vẫn là một clip đang bật vĩnh viễn và sẽ cắt mọi thứ tràn ra ngoài
   (nhãn chỉ dẫn, bóng đổ, đồng hồ số) — lỗi này rất khó thấy vì trông như "mất phần tử". */
.js-reveal [data-rv="mask"].is-in { clip-path: inset(-30% -30% -30% -30%) }

/* Chữ động theo từng từ (JS bọc mỗi từ trong .pp-w > i). Chữ trồi lên từ dưới
   khe cắt — hiệu ứng "kinetic type" của các trang đích hàng đầu. */
.pp-w { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .06em }
.pp-w > i {
    display: inline-block; font-style: inherit; font-weight: inherit;
    transform: translate3d(0, 108%, 0);
    transition: transform 1.05s var(--ease); transition-delay: var(--d, 0ms);
}
.js-reveal [data-split].is-in .pp-w > i, html:not(.js-reveal) .pp-w > i { transform: none }

/* ══ 2. THANH TIẾN ĐỘ CUỘN ═════════════════════════════════════════════════ */
.pp-progress {
    position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 70; pointer-events: none;
    background: transparent;
}
.pp-progress i {
    display: block; height: 100%; width: 100%; transform: scaleX(var(--sp, 0)); transform-origin: 0 50%;
    background: linear-gradient(90deg, var(--color-brand), var(--cyan) 55%, #14b8a6);
    box-shadow: 0 0 14px rgba(56, 189, 248, .8);
}

/* ══ 3. HERO — SÂN KHẤU ĐIỆN ẢNH ═══════════════════════════════════════════ */
.pp-hero {
    position: relative; overflow: hidden; color: #fff; isolation: isolate;
    min-height: clamp(620px, 92vh, 940px); display: flex; align-items: center;
    padding: 116px 0 clamp(56px, 8vh, 96px);
    background: radial-gradient(120% 130% at 78% 8%, #12325e 0%, #0a2350 32%, #061228 62%, #04070f 100%);
}
/* L0 — quầng sáng cực quang trôi rất chậm. Đây là lớp làm nền "sống" mà không ồn. */
.pp-aurora { position: absolute; inset: -20%; z-index: 0; pointer-events: none; filter: blur(70px); opacity: .82 }
.pp-aurora i { position: absolute; border-radius: 50%; will-change: transform }
.pp-aurora i:nth-child(1) {
    left: 52%; top: 2%; width: 46%; height: 58%;
    background: radial-gradient(circle, rgba(56, 189, 248, .55), transparent 68%);
    animation: ppDrift1 26s var(--ease-io) infinite;
}
.pp-aurora i:nth-child(2) {
    left: 4%; top: 34%; width: 42%; height: 52%;
    background: radial-gradient(circle, rgba(20, 102, 214, .6), transparent 70%);
    animation: ppDrift2 32s var(--ease-io) infinite;
}
.pp-aurora i:nth-child(3) {
    left: 30%; top: 58%; width: 44%; height: 46%;
    background: radial-gradient(circle, rgba(13, 148, 136, .42), transparent 70%);
    animation: ppDrift3 38s var(--ease-io) infinite;
}
@keyframes ppDrift1 { 0%, 100% { transform: translate3d(0, 0, 0) scale(1) } 50% { transform: translate3d(-7%, 6%, 0) scale(1.14) } }
@keyframes ppDrift2 { 0%, 100% { transform: translate3d(0, 0, 0) scale(1.05) } 50% { transform: translate3d(9%, -5%, 0) scale(.92) } }
@keyframes ppDrift3 { 0%, 100% { transform: translate3d(0, 0, 0) scale(.96) } 50% { transform: translate3d(-6%, -8%, 0) scale(1.1) } }

/* L1 — sàn lưới phối cảnh chạy về phía người xem: cho mắt một trục Z rõ ràng. */
.pp-floor {
    position: absolute; left: -30%; right: -30%; bottom: -6%; height: 62%; z-index: 0;
    pointer-events: none; transform: perspective(520px) rotateX(74deg);
    transform-origin: 50% 100%;
    background-image:
        repeating-linear-gradient(90deg, rgba(125, 211, 252, .18) 0 1px, transparent 1px 88px),
        repeating-linear-gradient(0deg, rgba(125, 211, 252, .16) 0 1px, transparent 1px 88px);
    mask-image: linear-gradient(to top, rgba(0, 0, 0, .9), transparent 72%);
    -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, .9), transparent 72%);
    animation: ppFloor 5.2s linear infinite;
}
@keyframes ppFloor { to { background-position: 0 88px, 0 88px } }

/* L2 — hai chùm sáng chéo mờ, đảo nhẹ độ sáng như đèn sân khấu thật. */
.pp-beam { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden }
.pp-beam i {
    position: absolute; top: -40%; height: 190%; width: 24%;
    background: linear-gradient(to bottom, rgba(125, 211, 252, .16), transparent 72%);
    filter: blur(18px); transform: rotate(16deg);
}
.pp-beam i:nth-child(1) { left: 58%; animation: ppBeam 9s ease-in-out infinite }
.pp-beam i:nth-child(2) { left: 76%; width: 14%; animation: ppBeam 11s ease-in-out infinite reverse }
@keyframes ppBeam { 0%, 100% { opacity: .35 } 50% { opacity: .85 } }

/* L3 — đèn theo con trỏ + hạt phim + tối bốn góc. Ba lớp phẳng, đặt trên cùng. */
.pp-spot {
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background: radial-gradient(38% 44% at var(--mx, 70%) var(--my, 30%), rgba(125, 211, 252, .22), transparent 70%);
    transition: background-position .2s linear;
}
.pp-grain {
    position: absolute; inset: -60%; z-index: 3; pointer-events: none; opacity: .06; mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.6'/></svg>");
}
.pp-vig {
    position: absolute; inset: 0; z-index: 2; pointer-events: none;
    background: radial-gradient(78% 78% at 50% 42%, transparent 42%, rgba(2, 5, 14, .72) 100%);
}

.pp-hero-grid {
    position: relative; z-index: 4; display: grid; gap: clamp(30px, 4vw, 54px);
    grid-template-columns: 1fr; align-items: center;
}
@media (min-width: 1000px) { .pp-hero-grid { grid-template-columns: 1.04fr .96fr } }

/* Vụn nội dung hero: đường dẫn, tem đại lý, H1, thông số, CTA. */
.pp-crumb { font-size: 12.5px; color: rgba(186, 230, 253, .8) }
.pp-crumb a { color: inherit; text-decoration: none }
.pp-crumb a:hover { color: #fff }
.pp-crumb span { margin: 0 7px; opacity: .55 }
.pp-crumb b { color: #fff; font-weight: 600 }

.pp-badge {
    display: inline-flex; align-items: center; gap: 9px; margin-top: 18px;
    border: 1px solid rgba(255, 255, 255, .22); border-radius: 999px;
    background: rgba(255, 255, 255, .06); backdrop-filter: blur(6px);
    padding: 9px 16px; font-size: 11px; font-weight: 800;
    letter-spacing: .13em; text-transform: uppercase; color: #e0f2fe;
}
.pp-dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: #2dd4bf; flex: none }
.pp-dot::after {
    content: ''; position: absolute; inset: -4px; border-radius: 50%;
    border: 1px solid rgba(45, 212, 191, .8); animation: ppPing 2.4s var(--ease-io) infinite;
}
@keyframes ppPing { 0% { transform: scale(.6); opacity: .9 } 100% { transform: scale(1.9); opacity: 0 } }

.pp-h1 {
    margin: 20px 0 0; font-size: clamp(40px, 6.6vw, 76px); font-weight: 800;
    letter-spacing: -.04em; line-height: .98; color: #fff;
}
/* Gradient chữ đặt trong @supports để trình duyệt không hỗ trợ vẫn còn chữ TRẮNG
   (không có fallback thì color:transparent làm H1 biến mất trắng trơn).
   Phải áp cho CẢ .pp-w > i: mỗi từ được JS bọc thành inline-block có transform,
   mà phần tử đã transform thì không nhận được nền đã clip của cha nữa. */
@supports (-webkit-background-clip: text) or (background-clip: text) {
    .pp-h1, .pp-h1 .pp-w > i {
        background-image: linear-gradient(180deg, #fff 32%, #b6dcff);
        -webkit-background-clip: text; background-clip: text;
        color: transparent; -webkit-text-fill-color: transparent;
    }
}
.pp-h1-sub {
    display: block; margin-top: 10px; font-size: clamp(15px, 1.8vw, 20px); font-weight: 600;
    letter-spacing: .01em; color: var(--cyan-soft); -webkit-text-fill-color: var(--cyan-soft);
}
.pp-hero-p { margin: 20px 0 0; max-width: 54ch; font-size: 17px; line-height: 1.7; color: rgba(226, 240, 255, .88) }
.pp-hero-p b { color: #fff; font-weight: 700 }
.pp-hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px }

.pp-stats {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
    margin: 34px 0 0; padding-top: 22px; max-width: 520px;
    border-top: 1px solid rgba(255, 255, 255, .14);
}
.pp-stats div { text-align: center }
.pp-stats dt, .pp-stats dd { margin: 0 } /* <dd> mặc định có margin-inline-start 40px */
.pp-stats dt {
    font-size: clamp(24px, 3vw, 32px); font-weight: 800; letter-spacing: -.02em;
    font-variant-numeric: tabular-nums; color: #fff;
}
.pp-stats dt b { font: inherit; color: inherit } /* hậu tố "+" nằm ngoài <b> nên phải cùng cỡ */
.pp-stats i {
    display: block; margin-top: 4px; font-style: normal; font-size: 10.5px; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase; color: rgba(186, 230, 253, .8);
}

/* Thị sai khi rời hero (--heroP do JS ghi, 0 → 1 trong khoảng cuộn qua hero):
   chữ nhấc lên chậm, khối 3D lùi và mờ nhanh hơn → hai lớp TÁCH nhau ra. Cả khối
   trôi cùng tốc độ thì mắt không đọc ra chiều sâu, và đó là lỗi hay gặp nhất. */
.pp-hero-copy { transform: translate3d(0, calc(var(--heroP, 0) * 40px), 0); opacity: calc(1 - var(--heroP, 0) * .88) }
.pp-stage {
    transform: translate3d(0, calc(var(--heroP, 0) * -30px), 0) scale(calc(1 - var(--heroP, 0) * .09));
    opacity: calc(1 - var(--heroP, 0) * .95);
}

/* Gợi ý cuộn dưới hero. */
.pp-cue {
    opacity: calc(1 - var(--heroP, 0) * 2.4);
    position: relative; z-index: 4; display: flex; align-items: center; justify-content: center; gap: 10px;
    margin-top: clamp(26px, 4vh, 48px); font-size: 12px; letter-spacing: .06em;
    color: rgba(186, 230, 253, .7);
}
.pp-cue svg { animation: ppCue 2.1s var(--ease-io) infinite }
@keyframes ppCue { 0%, 100% { transform: translateY(-3px); opacity: .5 } 50% { transform: translateY(4px); opacity: 1 } }

/* ══ 4. ĐẦU BƠM 3D — VẬT THỂ CHÍNH CỦA HERO ════════════════════════════════
   Toàn bộ kích thước bên trong tính bằng `em`, và .pp-rig đặt font-size = chiều
   rộng khối → đổi một con số là scale cả cụm, không phải sửa 30 chỗ.            */
.pp-stage { position: relative; perspective: 1400px; perspective-origin: 50% 44% }
/* line-height: 0 là BẮT BUỘC khi font-size dùng làm đơn vị kích thước: các
   khoảng trắng giữa các thẻ con sẽ tạo line box cao 430px và phá bố cục. Mọi
   thẻ có chữ bên trong phải tự khai lại font-size + line-height. */
.pp-rig {
    position: relative; margin-inline: auto; font-size: min(430px, 82vw); line-height: 0;
    width: 1em; height: 1em; transform-style: preserve-3d;
    /* Hai lớp góc: --rx/--ry do con trỏ (JS, có quán tính), --ix/--iy là dao động
       nền để vật vẫn "sống" khi không ai chạm chuột. */
    transform: rotateX(calc(var(--rx, 13deg) + var(--ix, 0deg))) rotateY(calc(var(--ry, -15deg) + var(--iy, 0deg)));
    animation: ppIdle 12s ease-in-out infinite;
}
@keyframes ppIdle {
    0%, 100% { --ix: 0deg; --iy: 0deg }
    33%      { --ix: 2.4deg; --iy: 3.4deg }
    66%      { --ix: -2deg; --iy: -3deg }
}
@property --ix { syntax: '<angle>'; inherits: true; initial-value: 0deg }
@property --iy { syntax: '<angle>'; inherits: true; initial-value: 0deg }

/* Hào quang sau vật — lùi hẳn trục Z nên là chiều sâu thật, không phải bóng phẳng. */
.pp-halo {
    position: absolute; inset: -18%; border-radius: 50%; transform: translateZ(-150px);
    background: radial-gradient(circle at 50% 46%, rgba(56, 189, 248, .6), rgba(20, 102, 214, .3) 46%, transparent 74%);
    filter: blur(30px); animation: ppHalo 6.5s ease-in-out infinite;
}
@keyframes ppHalo { 0%, 100% { opacity: .78; transform: translateZ(-150px) scale(1) } 50% { opacity: 1; transform: translateZ(-150px) scale(1.07) } }

/* Hai vòng quỹ đạo nằm trong mặt phẳng khác → mắt đọc ra không gian 3D ngay lập tức. */
.pp-orbit {
    position: absolute; inset: -7%; border-radius: 50%; transform-style: preserve-3d;
    border: 1px solid rgba(125, 211, 252, .28);
}
/* Mỗi vòng có keyframes RIÊNG với from/to cùng dạng transform. Nếu dùng chung một
   @keyframes chỉ khai `to`, trình duyệt phải nội suy giữa hai chuỗi transform khác
   dạng → rơi về nội suy matrix và vòng bị méo thay vì quay đều. */
.pp-orbit-1 { transform: rotateX(76deg); animation: ppOrbit1 16s linear infinite }
@keyframes ppOrbit1 { from { transform: rotateX(76deg) rotateZ(0) } to { transform: rotateX(76deg) rotateZ(360deg) } }
.pp-orbit-2 { inset: -14%; border-style: dashed; border-color: rgba(125, 211, 252, .2);
    transform: rotateX(70deg); animation: ppOrbit2 24s linear infinite reverse }
@keyframes ppOrbit2 { from { transform: rotateX(70deg) rotateZ(0) } to { transform: rotateX(70deg) rotateZ(360deg) } }
/* Hạt sáng chạy trên vòng quỹ đạo. */
.pp-orbit i {
    position: absolute; top: -4px; left: 50%; width: 8px; height: 8px; margin-left: -4px; border-radius: 50%;
    background: #e0f2fe; box-shadow: 0 0 16px 3px rgba(125, 211, 252, .9);
}

/* Vỏ bơm: conic-gradient giả ánh kim, viền sáng trên và gờ tối dưới. */
.pp-casing {
    position: absolute; inset: 0; border-radius: 50%; transform: translateZ(0);
    background:
        conic-gradient(from 202deg, #fdfeff, #e6edf5 20%, #b9c6d6 46%, #f2f6fa 68%, #fdfeff 88%, #dde5ee);
    box-shadow:
        0 42px 80px -26px rgba(4, 12, 32, .78),
        0 0 0 1px rgba(255, 255, 255, .5),
        inset 0 4px 10px rgba(255, 255, 255, .95),
        inset 0 -18px 34px rgba(15, 23, 42, .2);
}
/* Vòng bu-lông — chi tiết nhỏ nhưng là thứ khiến mắt tin đây là phần cứng thật. */
.pp-bolts { position: absolute; inset: 0; transform: translateZ(2px) }
.pp-bolts i {
    position: absolute; left: 50%; top: 50%; width: .034em; height: .034em; margin: -.017em 0 0 -.017em;
    border-radius: 50%; transform: rotate(var(--a)) translateY(-.452em);
    background: radial-gradient(circle at 34% 30%, #fff, #94a3b8 70%, #64748b);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .5), inset 0 -1px 1px rgba(15, 23, 42, .4);
}
/* Lòng vỏ nơi ống tì vào. */
.pp-bore {
    position: absolute; inset: 8%; border-radius: 50%; transform: translateZ(5px);
    background: radial-gradient(circle at 50% 26%, #f4f7fb, #cdd7e3 74%, #97a5b8);
    box-shadow: inset 0 10px 24px rgba(15, 23, 42, .3), inset 0 -4px 8px rgba(255, 255, 255, .75);
}
/* Ống silicon: vòng kính trong, ánh xanh. Bề dày --tw để cảnh khác dùng lại được. */
.pp-tube {
    position: absolute; inset: 13.5%; border-radius: 50%; transform: translateZ(9px);
    border: var(--tw, .048em) solid rgba(224, 242, 254, .26);
    box-shadow:
        inset 0 0 0 1px rgba(2, 132, 199, .5),
        0 0 0 1px rgba(2, 132, 199, .32),
        inset 0 0 30px rgba(2, 132, 199, .38),
        0 10px 24px -8px rgba(2, 132, 199, .5);
}
/* Chất lỏng TRONG ống: một vòng conic được cắt mặt nạ thành dải hẹp đúng vị trí ống,
   quay cùng nhịp rotor → mắt đọc thành các khoang chất lỏng bị con lăn đẩy đi.
   Cách này đúng bản chất hơn mấy hạt tròn chạy vòng: chất lỏng là KHỐI liên tục. */
.pp-fluid {
    position: absolute; inset: 13.5%; border-radius: 50%; transform: translateZ(10px);
    /* `from -90deg` đưa mốc 0% của conic về vị trí 3 giờ — đúng nơi con lăn --a:0deg
       đứng. Nhờ vậy ba KHE HỞ của gradient (quanh 0%, 33,3%, 66,7%) nằm đúng dưới ba
       con lăn: mắt đọc ra "con lăn chặn ống, chia chất lỏng thành từng khoang".
       Để lệch thì chất lỏng chảy xuyên qua con lăn và cả hiệu ứng mất ý nghĩa. */
    background: conic-gradient(from -90deg,
        transparent 0 3.4%, #38bdf8 6.5% 27%, transparent 30% 36.7%,
        #22d3ee 39.8% 60.4%, transparent 63.3% 70%, #38bdf8 73.2% 93.7%, transparent 96.6%);
    mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 86%, #000 88% 100%);
    -webkit-mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 86%, #000 88% 100%);
    filter: blur(1.2px) saturate(1.25); opacity: .95;
    animation: ppSpin var(--spin, 7s) linear infinite;
}
/* Rotor: translateZ phải có ở CẢ base VÀ keyframes — nếu chỉ đặt trong keyframes thì
   khi animation bị tắt (reduced motion) rotor tụt xuống dưới ống và bị phủ mất. */
.pp-rotor {
    position: absolute; inset: 0; transform-style: preserve-3d; transform: translateZ(15px) rotate(var(--ang, 0deg));
    animation: ppSpin var(--spin, 7s) linear infinite;
}
@keyframes ppSpin { from { transform: translateZ(15px) rotate(0) } to { transform: translateZ(15px) rotate(360deg) } }
/* Vòng chất lỏng dùng CÙNG keyframes nhưng không cần translateZ → tách riêng. */
.pp-fluid { animation-name: ppSpinFlat }
@keyframes ppSpinFlat { from { transform: translateZ(10px) rotate(0) } to { transform: translateZ(10px) rotate(360deg) } }

/* Bản đế rotor hình TAM GIÁC ba đỉnh trùng ba cánh — đúng hình dáng rotor 3 con
   lăn thật. Ban đầu tôi làm cái đĩa tròn: nó to hơn cả trục, che mất phần gốc cánh
   và biến khối cơ khí thành một cái mâm phẳng. Tam giác đặt SAU cánh (đầu DOM) thì
   cánh vẫn nổi lên trên và mắt đọc ra một khối liền. */
.pp-rotor-body {
    position: absolute; left: 50%; top: 50%; width: .26em; height: .26em; margin: -.13em 0 0 -.13em;
    clip-path: polygon(100% 50%, 25% 93.3%, 25% 6.7%);
    background: linear-gradient(150deg, #dee6ef, #aab7c7 55%, #7d8b9d);
}
.pp-arm {
    position: absolute; left: 50%; top: calc(50% - .024em); width: .35em; height: .048em;
    transform-origin: 0 50%; transform: rotate(var(--a)); border-radius: 999px;
    background: linear-gradient(180deg, #fff 6%, #e3e9f1 30%, #9daabb 62%, #4c5a70);
    box-shadow: 0 .01em .024em rgba(15, 23, 42, .42), inset 0 .004em 0 rgba(255, 255, 255, .9);
}
/* Con lăn đặt bằng `left` chứ không bằng `right`: tâm con lăn phải trùng đúng bán
   kính giữa dải ống (.3475em) để trông như đang tì vào ống, lệch ra là hở. */
.pp-roller {
    position: absolute; left: .295em; top: 50%; width: .105em; height: .105em; margin-top: -.0525em;
    border-radius: 50%;
    background: radial-gradient(circle at 30% 24%, #fff, #dbe3ec 34%, #8695a9 74%, #4e5c72);
    box-shadow: 0 .016em .034em rgba(15, 23, 42, .55), inset 0 -.008em .014em rgba(15, 23, 42, .4);
}
/* Vệt ép: con lăn nào cũng để lại một vết dẹt tối trên ống — đây là chi tiết
   giải thích nguyên lý, không phải trang trí. */
.pp-pinch {
    position: absolute; left: .30em; top: 50%; width: .095em; height: .15em; margin-top: -.075em;
    border-radius: 50%; background: radial-gradient(ellipse at 50% 50%, rgba(2, 60, 110, .55), transparent 72%);
    filter: blur(3px);
}
/* Trục giữa: kim loại phay bằng conic-gradient nhiều chặng. */
.pp-hub {
    position: absolute; left: 50%; top: 50%; width: .21em; height: .21em; margin: -.105em 0 0 -.105em;
    border-radius: 50%; transform: translateZ(24px);
    background: conic-gradient(from 0deg, #fff, #c7d2e0 12%, #fff 25%, #b9c5d5 38%, #fff 50%,
        #c7d2e0 62%, #fff 75%, #b9c5d5 88%, #fff);
    box-shadow: 0 .03em .06em rgba(15, 23, 42, .5), inset 0 .004em .01em rgba(255, 255, 255, .9);
}
.pp-hub::after {
    content: ''; position: absolute; inset: 26%; border-radius: 50%;
    background: linear-gradient(145deg, var(--color-brand), #0a3576);
    box-shadow: inset 0 .004em .01em rgba(255, 255, 255, .45), 0 .006em .014em rgba(2, 12, 32, .5);
}
/* Cổng vào / cổng ra: có chất lỏng chạy trong ống nhờ gradient lặp trôi liên tục. */
/* Z ÂM: cổng phải nằm sau mặt vỏ, phần chồng lên vỏ bị vỏ che → đọc ra "ống cắm
   vào thân bơm". Để Z dương thì hai cổng lơ lửng phía trước như hai cái ăng-ten. */
.pp-port {
    position: absolute; top: -.1em; width: .062em; height: .3em; border-radius: .031em;
    transform-origin: 50% 100%; transform: translateZ(-7px) rotate(var(--pr, 0deg));
    background: linear-gradient(180deg, rgba(186, 230, 253, .8), rgba(2, 132, 199, .42));
    box-shadow: 0 .012em .03em -.006em rgba(2, 132, 199, .7), inset 0 0 .016em rgba(255, 255, 255, .6);
    overflow: hidden;
}
.pp-port i {
    position: absolute; inset: 12% 22%; border-radius: 999px;
    background: repeating-linear-gradient(180deg, rgba(224, 242, 254, .95) 0 22%, rgba(56, 189, 248, .25) 22% 50%);
    background-size: 100% .11em; animation: ppPortFlow 1.5s linear infinite;
}
.pp-port::after {
    content: ''; position: absolute; left: -30%; right: -30%; bottom: .055em; height: .022em;
    border-radius: .011em; background: linear-gradient(180deg, #eef4fa, #9fb0c4);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .35);
}
.pp-port-in { left: 24%; --pr: -11deg } .pp-port-out { right: 24%; --pr: 11deg }
.pp-port-out i { animation-direction: reverse }
@keyframes ppPortFlow { to { background-position: 0 .11em } }

/* Vệt sáng specular quét quanh vỏ — nguồn sáng "di chuyển" làm bề mặt có chất kim loại. */
.pp-spec {
    position: absolute; inset: -1%; border-radius: 50%; transform: translateZ(30px); pointer-events: none;
    background: conic-gradient(from 0deg, transparent 0 62%, rgba(255, 255, 255, .5) 76%, rgba(255, 255, 255, .06) 84%, transparent 90%);
    mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 62%, #000 70%, #000 99%, transparent 100%);
    -webkit-mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 62%, #000 70%, #000 99%, transparent 100%);
    opacity: .8; animation: ppSpecSweep 9s linear infinite;
}
@keyframes ppSpecSweep { from { transform: translateZ(30px) rotate(0) } to { transform: translateZ(30px) rotate(360deg) } }
/* Ánh kính phủ toàn vật, đứng yên — đây là thứ khóa "hướng nguồn sáng" cho cả khối. */
.pp-gloss {
    position: absolute; inset: 0; border-radius: 50%; transform: translateZ(34px); pointer-events: none;
    background: linear-gradient(142deg, rgba(255, 255, 255, .34) 0%, rgba(255, 255, 255, .06) 26%, transparent 40%);
}

/* Thẻ thông số bay phía trước, mỗi thẻ một mức Z + nhân hệ số thị sai riêng. */
.pp-chip {
    position: absolute; white-space: nowrap; border-radius: 999px; padding: 9px 15px;
    font-size: 12px; line-height: 1.35; font-weight: 700; letter-spacing: .01em; color: #06203f;
    background: rgba(255, 255, 255, .94); backdrop-filter: blur(4px);
    box-shadow: 0 18px 34px -12px rgba(4, 12, 32, .7), inset 0 1px 0 #fff;
    transform: translate3d(calc(var(--px, 0px) * var(--k, 1)), calc(var(--py, 0px) * var(--k, 1)), var(--z));
    transition: transform .5s var(--ease);
}
.pp-chip b { color: var(--color-brand) }
.pp-chip-1 { left: -9%;  top: 10%;    --z: 110px; --k: 1.5 }
.pp-chip-2 { right: -11%; top: 43%;   --z: 130px; --k: 1.9 }
.pp-chip-3 { left: -3%;  bottom: 9%;  --z: 96px;  --k: 1.2 }
.pp-rig-note { margin: 18px 0 0; text-align: center; font-size: 11.5px; color: rgba(186, 230, 253, .65) }

/* ══ 5. CẢNH GHIM: HÌNH CẮT ĐẦU BƠM, CUỘN ĐỂ QUAY ══════════════════════════
   Không JS → .pp-mech-outer cao auto, không ghim, 3 khối chữ xếp dọc và đọc được
   hết. Có JS (.js-reveal) mới bật chế độ ghim + tua timeline bằng cuộn.          */
/* KHÔNG được đặt overflow:hidden lên .pp-mech (hay bất kỳ tổ tiên nào): nó biến
   phần tử thành scrollport và position:sticky bên trong sẽ chết lặng. */
.pp-mech { background: #f7f9fc; border-block: 1px solid var(--color-line); position: relative }
.pp-mech-sticky::before {
    content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: .5;
    background-image:
        repeating-linear-gradient(0deg, rgba(20, 102, 214, .07) 0 1px, transparent 1px 32px),
        repeating-linear-gradient(90deg, rgba(20, 102, 214, .07) 0 1px, transparent 1px 32px);
    mask-image: radial-gradient(120% 90% at 50% 40%, #000, transparent 78%);
    -webkit-mask-image: radial-gradient(120% 90% at 50% 40%, #000, transparent 78%);
}
.pp-mech-outer { position: relative; z-index: 1 }
.pp-mech-sticky { position: relative; padding: 8px 0 clamp(40px, 6vw, 72px) }
.js-reveal .pp-mech-outer { height: 330vh }
.js-reveal .pp-mech-sticky {
    position: sticky; top: 0; height: 100vh; padding: 0;
    display: flex; align-items: center; overflow: hidden;
}
.pp-mech-grid { display: grid; gap: clamp(24px, 3.5vw, 48px); grid-template-columns: 1fr; align-items: center; width: 100% }
@media (min-width: 900px) { .pp-mech-grid { grid-template-columns: .92fr 1.08fr } }

/* — Hình cắt kiểu bản vẽ kỹ thuật — */
.cx { position: relative; justify-self: center }
/* --bob: hình cắt nhấp nhô rất nhẹ (5px, 7s) cho cảnh ghim còn "thở" khi người đọc
   dừng cuộn. Phải cộng vào CÙNG một transform với --zoom — đặt animation riêng lên
   transform sẽ ghi đè mất --zoom. @property để --bob nội suy mượt (nếu trình duyệt
   không hỗ trợ thì đơn giản là không nhấp nhô, không lỗi gì). */
@property --bob { syntax: '<length>'; inherits: false; initial-value: 0px }
.cx-rig {
    position: relative; font-size: min(440px, 76vw); line-height: 0; width: 1em; height: 1em;
    transform: translateY(var(--bob, 0px)) scale(var(--zoom, 1));
    transition: transform .1s linear;
    animation: cxBob 7s ease-in-out infinite;
}
@keyframes cxBob { 0%, 100% { --bob: 0px } 50% { --bob: -5px } }
.cx-shell {
    position: absolute; inset: 0; border-radius: 50%; background: #fff;
    border: 2px solid rgba(15, 23, 42, .78);
    box-shadow: 0 30px 60px -30px rgba(8, 20, 45, .45), inset 0 0 0 6px rgba(15, 23, 42, .04);
}
.cx-bore { position: absolute; inset: 7%; border-radius: 50%; border: 1.5px dashed rgba(15, 23, 42, .22) }
/* Ống: bề dày cố định, màu cyan mờ; vệt ép do con lăn nằm trong .cx-rotor. */
.cx-tube {
    position: absolute; inset: 12%; border-radius: 50%;
    border: .052em solid rgba(56, 189, 248, .3);
    box-shadow: inset 0 0 0 1px rgba(2, 132, 199, .35), 0 0 0 1px rgba(2, 132, 199, .35);
}
.cx-fluid {
    position: absolute; inset: 12%; border-radius: 50%; transform: rotate(var(--ang, 0deg));
    background: conic-gradient(from -90deg,
        transparent 0 3.4%, #0ea5e9 6.5% 27%, transparent 30% 36.7%,
        #06b6d4 39.8% 60.4%, transparent 63.3% 70%, #0ea5e9 73.2% 93.7%, transparent 96.6%);
    mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 85%, #000 87.5% 100%);
    -webkit-mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 85%, #000 87.5% 100%);
    opacity: .9;
}
.cx-rotor { position: absolute; inset: 0; transform: rotate(var(--ang, 0deg)) }
.cx-arm {
    position: absolute; left: 50%; top: calc(50% - .014em); width: .345em; height: .028em;
    transform-origin: 0 50%; transform: rotate(var(--a)); border-radius: 999px;
    background: linear-gradient(180deg, #e8eef6, #94a3b8);
    border: 1px solid rgba(15, 23, 42, .5); box-sizing: border-box;
}
.cx-roller {
    position: absolute; left: .306em; top: 50%; width: .096em; height: .096em; margin-top: -.048em;
    border-radius: 50%; background: radial-gradient(circle at 32% 28%, #fff, #cbd5e1 55%, #7c8ba0);
    border: 1.5px solid rgba(15, 23, 42, .7); box-sizing: border-box;
}
/* Vết ép ống: dẹt lại đúng chỗ con lăn tì vào. */
.cx-pinch {
    position: absolute; left: .311em; top: 50%; width: .086em; height: .145em; margin-top: -.0725em;
    border-radius: 50%; background: rgba(2, 132, 199, .5); filter: blur(3px);
}
.cx-hub {
    position: absolute; left: 50%; top: 50%; width: .13em; height: .13em; margin: -.065em 0 0 -.065em;
    border-radius: 50%; background: radial-gradient(circle at 34% 28%, #fff, #cbd5e1 60%, #64748b);
    border: 2px solid rgba(15, 23, 42, .78); box-sizing: border-box;
}
.cx-hub::after {
    content: ''; position: absolute; inset: 30%; border-radius: 50%; background: var(--color-brand);
}
/* Cổng vào/ra + mũi tên dòng chảy. Mũi tên vào sáng ở nhịp "Hồi", ra sáng ở nhịp "Đẩy". */
.cx-port { position: absolute; top: -.09em; width: .058em; height: .3em; border-radius: .029em;
    background: #fff; border: 2px solid rgba(15, 23, 42, .72); box-sizing: border-box; overflow: hidden }
.cx-port i { position: absolute; inset: 8% 18%; border-radius: 999px;
    background: repeating-linear-gradient(180deg, rgba(14, 165, 233, .95) 0 24%, rgba(14, 165, 233, .15) 24% 50%);
    background-size: 100% .12em; animation: cxPortFlow 1.4s linear infinite }
.cx-port-in { left: 24% } .cx-port-out { right: 24% }
.cx-port-out i { animation-direction: reverse }
@keyframes cxPortFlow { to { background-position: 0 .12em } }
.cx-port-tag {
    position: absolute; top: -.16em; font-size: 11px; line-height: 1.2; font-weight: 800; letter-spacing: .08em;
    text-transform: uppercase; color: var(--color-brand); white-space: nowrap;
}
.cx-tag-in { left: 12% } .cx-tag-out { right: 12%; text-align: right }
/* Cường độ dòng vào/ra ăn theo nhịp đang chạy → nhìn là biết đang hút hay đang đẩy. */
.cx-port-in  { box-shadow: 0 0 0 calc(var(--o3, 0) * 6px) rgba(56, 189, 248, .28) }
.cx-port-out { box-shadow: 0 0 0 calc(var(--o2, 0) * 6px) rgba(20, 184, 166, .3) }

/* Khung bản vẽ: 4 dấu góc + tem bản vẽ + đồng hồ thể tích đã bơm. */
.cx-frame { position: absolute; inset: -6%; pointer-events: none }
.cx-frame i { position: absolute; width: 18px; height: 18px; border: 2px solid rgba(20, 102, 214, .45) }
.cx-frame i:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0 }
.cx-frame i:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0 }
.cx-frame i:nth-child(3) { left: 0; bottom: 0; border-right: 0; border-top: 0 }
.cx-frame i:nth-child(4) { right: 0; bottom: 0; border-left: 0; border-top: 0 }
.cx-meta {
    position: absolute; left: -6%; bottom: -11%; font-size: 10.5px; line-height: 1.35; font-weight: 700;
    letter-spacing: .1em; text-transform: uppercase; color: rgba(15, 23, 42, .42);
}
.cx-read {
    position: absolute; right: -6%; bottom: -13%; text-align: right; font-size: 12px; line-height: 1.35;
    font-variant-numeric: tabular-nums;
}
.cx-read b { display: block; font-size: 22px; font-weight: 800; color: var(--color-ink); letter-spacing: -.02em }
.cx-read > span { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: rgba(15, 23, 42, .42) }

/* Nhãn chỉ dẫn: chỉ MỘT nhãn hiện tại mỗi thời điểm (opacity ăn theo nhịp), đặt ở
   ba GÓC của hộp vuông chứa hình tròn — đó là chỗ trống duy nhất còn lại quanh
   đường tròn. Đặt cạnh trái/phải như thẻ to sẽ đè lên chính chỗ đang cần xem,
   hoặc tràn sang cột chữ ở màn hẹp. Phần diễn giải dài đã nằm ở cột bên phải. */
.cx-lab {
    position: absolute; max-width: 132px; border-radius: 11px; padding: 8px 11px; background: #fff;
    border: 1px solid rgba(20, 102, 214, .26); box-shadow: 0 14px 30px -18px rgba(8, 20, 45, .55);
    font-size: 11.5px; line-height: 1.42; color: var(--color-ink);
    opacity: var(--o, 1); transform: translateY(calc((1 - var(--o, 1)) * 8px)); transition: opacity .22s linear;
}
.cx-lab b { display: block; font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--color-brand); margin-bottom: 2px }
.cx-lab-1 { left: -7%; bottom: 6%;  --o: var(--o1, 1) }   /* Ép   — góc dưới-trái */
.cx-lab-2 { right: -7%; top: 4%;    --o: var(--o2, 1) }   /* Đẩy  — cạnh cổng RA */
.cx-lab-3 { left: -7%; top: 4%;     --o: var(--o3, 1) }   /* Hồi  — cạnh cổng VÀO */
/* 900–1199px: hình phải nhỏ lại, nếu không nhãn ở góc sẽ đẩy ra ngoài mép trang. */
@media (min-width: 900px) and (max-width: 1199px) {
    .cx-rig { font-size: min(350px, 33vw) }
    .cx-lab { max-width: 108px; font-size: 10.5px; padding: 6px 9px }
}

/* — Cột chữ 3 nhịp — */
.pp-beats { position: relative }
.pp-rail { display: flex; gap: 8px; margin-bottom: 22px }
.pp-rail button {
    flex: 1; text-align: left; font: inherit; cursor: pointer; background: transparent; border: 0; padding: 0;
    color: rgba(15, 23, 42, .45);
}
.pp-rail span {
    display: block; height: 3px; border-radius: 3px; background: rgba(15, 23, 42, .12); overflow: hidden;
}
.pp-rail span::after {
    content: ''; display: block; height: 100%; width: 100%; transform-origin: 0 50%;
    transform: scaleX(var(--f, 0)); background: linear-gradient(90deg, var(--color-brand), var(--cyan));
}
.pp-rail b { display: block; margin-top: 9px; font-size: 12px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase }
.pp-rail .on { color: var(--color-brand) }

.pp-beat-stack { position: relative }
.js-reveal .pp-beat-stack { min-height: 300px }
.pp-beat { }
.js-reveal .pp-beat {
    position: absolute; inset: 0; opacity: var(--o, 0); pointer-events: none;
    transform: translateY(calc((1 - var(--o, 0)) * 26px));
    filter: blur(calc((1 - var(--o, 0)) * 5px));
    transition: opacity .2s linear, transform .2s linear;
}
.js-reveal .pp-beat[data-on] { pointer-events: auto }
html:not(.js-reveal) .pp-beat + .pp-beat { margin-top: 28px }
/* Không JS: cảnh không được ghim, cuộn không tua gì cả → hai thứ chỉ có nghĩa khi
   đang tua (gợi ý "cuộn tiếp" và đồng hồ số vòng) phải ẩn, kẻo chúng nói sai. */
html:not(.js-reveal) .pp-scrollhint,
html:not(.js-reveal) .cx-read { display: none }
.pp-beat-1 { --o: var(--o1, 1) } .pp-beat-2 { --o: var(--o2, 0) } .pp-beat-3 { --o: var(--o3, 0) }
.pp-beat-n {
    display: inline-flex; align-items: center; justify-content: center; width: 42px; height: 42px;
    border-radius: 13px; font-size: 17px; font-weight: 800; color: #fff;
    background: linear-gradient(140deg, var(--color-brand), #0a3576);
    box-shadow: 0 14px 28px -12px rgba(20, 102, 214, .8);
}
.pp-beat h3 { margin: 16px 0 0; font-size: clamp(22px, 2.6vw, 30px); font-weight: 800; letter-spacing: -.025em; color: var(--color-ink) }
.pp-beat p { margin: 12px 0 0; max-width: 56ch; font-size: 15.5px; line-height: 1.75; color: var(--color-muted) }
.pp-beat p b { color: var(--color-ink) }
.pp-scrollhint { margin-top: 22px; font-size: 12px; font-weight: 700; letter-spacing: .07em; color: rgba(15, 23, 42, .38) }

/* ══ 6. BỘ CHỌN BƠM THEO LƯU LƯỢNG ═════════════════════════════════════════
   Kéo thanh → dòng bơm đổi, máy đổi sang model thật trong kho, ống dày lên,
   chất lỏng chảy nhanh hơn. Mỗi chuyển động mang một thông tin.               */
.pp-sel {
    position: relative; overflow: hidden; border-radius: 26px; margin-top: clamp(26px, 3.5vw, 40px);
    background: radial-gradient(120% 95% at 20% 0%, #143665, #071228 56%, #04070f);
    box-shadow: 0 40px 80px -40px rgba(8, 20, 45, .8);
    --tw: 12px; --pulse: 2.2s; --lvl: 0;
}
.pp-sel-grid { display: grid; grid-template-columns: 1fr }
@media (min-width: 940px) { .pp-sel-grid { grid-template-columns: 1.06fr .94fr } }

/* ══ SÂN KHẤU SÁNG ══
   Ảnh sản phẩm trong kho là ảnh nền TRẮNG. Muốn đặt lên nền tối thì phải tách nền,
   mà bản tách nền có sẵn (uploads/demo3d) bị rỗ viền — khách phản hồi đúng: "ảnh vỡ".
   Cách sạch hơn và không cần sửa ảnh: sân khấu SÁNG + `mix-blend-mode: multiply`.
   Nền trắng của ảnh nhân với nền sáng → TAN hẳn vào sân khấu, còn viền thì mịn đúng
   như ảnh gốc. Đổi lại: vòng ống không được đi qua sau ảnh (multiply sẽ cho vòng ống
   hiện xuyên qua thân máy), nên bán kính vòng luôn lớn hơn hộp ảnh — xem số đo bên dưới. */
.pp-sel-stage {
    position: relative; min-height: clamp(320px, 44vw, 470px); overflow: hidden;
    display: flex; align-items: center; justify-content: center; padding: 30px 20px 44px;
    background: radial-gradient(120% 96% at 50% 26%, #fff 0%, #f1f6fc 46%, #dfe9f5 100%);
}
.pp-sel-stage::before {
    content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .55;
    background-image:
        repeating-linear-gradient(0deg, rgba(20, 102, 214, .07) 0 1px, transparent 1px 30px),
        repeating-linear-gradient(90deg, rgba(20, 102, 214, .07) 0 1px, transparent 1px 30px);
    mask-image: radial-gradient(92% 82% at 50% 45%, #000, transparent 82%);
    -webkit-mask-image: radial-gradient(92% 82% at 50% 45%, #000, transparent 82%);
}
.pp-sel-glow {
    position: absolute; left: 50%; top: 50%; width: 86%; aspect-ratio: 1; translate: -50% -50%;
    border-radius: 50%; filter: blur(40px);
    background: radial-gradient(circle, rgba(56, 189, 248, calc(.1 + var(--lvl) * .26)), transparent 66%);
}
/* Vòng ống: BỀ DÀY ăn theo lưu lượng đang chọn → thấy được "ống to hơn" nghĩa là gì. */
.pp-sel-ring {
    position: absolute; left: 50%; top: 50%; width: min(430px, 78%); aspect-ratio: 1; translate: -50% -50%;
    border-radius: 50%; border: var(--tw) solid rgba(2, 132, 199, .18);
    box-shadow: inset 0 0 30px rgba(2, 132, 199, .12), 0 0 0 1px rgba(2, 132, 199, .16);
    transition: border-width .45s var(--ease);
}
/* Chất lỏng trong ống: CHU KỲ ăn theo lưu lượng → lưu lượng cao thì chảy nhanh hơn. */
.pp-sel-fluid {
    position: absolute; left: 50%; top: 50%; width: min(430px, 78%); aspect-ratio: 1; translate: -50% -50%;
    border-radius: 50%; animation: ppSpinPlain var(--pulse) linear infinite;
    background: conic-gradient(from -90deg,
        transparent 0 3.4%, #0ea5e9 6.5% 27%, transparent 30% 36.7%,
        #06b6d4 39.8% 60.4%, transparent 63.3% 70%, #0ea5e9 73.2% 93.7%, transparent 96.6%);
    mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 85%, #000 88% 100%);
    -webkit-mask-image: radial-gradient(closest-side at 50% 50%, transparent 0 85%, #000 88% 100%);
    filter: blur(1.2px); opacity: .95;
}
@keyframes ppSpinPlain { to { rotate: 360deg } }

/* Ảnh + nhãn là MỘT khối, để sân khấu (flex) tự căn giữa.
   TUYỆT ĐỐI không đặt transform/translate/opacity/filter/z-index lên khối này: bất kỳ
   thứ nào trong đó cũng tạo stacking context, mà stacking context thì CẮT nền phía sau
   khỏi phép hoà trộn → `mix-blend-mode: multiply` của ảnh hết tác dụng và nền trắng của
   ảnh hiện nguyên thành một khung trắng. Tôi đã mắc đúng lỗi này ở bản trước.
   Thứ tự trong DOM (đặt sau vòng ống) là cái quyết định nó nằm trên. */
.pp-sel-piece { position: relative; width: min(300px, 62%); text-align: center }
/* Ảnh máy: KHÔNG khai width/height cứng (mỗi model một tỉ lệ), và chặn trên bằng px
   để không bao giờ giãn to hơn ảnh thật → không rạn trên màn retina.
   mix-blend-mode: multiply làm nền trắng của ảnh tan vào sân khấu sáng. */
.pp-sel-img {
    display: block; margin: 0 auto; max-width: 100%; max-height: min(224px, 30vw);
    width: auto; height: auto;
    mix-blend-mode: multiply; opacity: 0; transition: opacity .4s var(--ease);
}
.pp-sel-img.on { opacity: 1 }
/* Nhãn ngay dưới ảnh: đang xem model nào, lưu lượng tối đa bao nhiêu. */
.pp-sel-cap {
    margin-top: 14px; font-size: 12.5px; line-height: 1.5; color: rgba(15, 23, 42, .55);
}
.pp-sel-cap b { display: block; font-size: 15px; font-weight: 800; color: var(--color-ink); letter-spacing: -.01em }
.pp-sel-badges { position: absolute; left: 18px; top: 18px; display: flex; gap: 7px; z-index: 2 }
.pp-sel-badge {
    width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; cursor: pointer;
    font: inherit; font-size: 15px; font-weight: 800; color: #7b8ca4;
    border: 1px solid rgba(15, 23, 42, .12); background: rgba(255, 255, 255, .85);
    transition: color .3s, background .3s, transform .4s var(--ease), box-shadow .3s;
}
.pp-sel-badge:hover { color: var(--color-brand); border-color: rgba(20, 102, 214, .4) }
.pp-sel-badge.on {
    color: #fff; border-color: transparent; transform: scale(1.1);
    background: linear-gradient(140deg, var(--color-brand), #0b3f8f);
    box-shadow: 0 12px 26px -10px rgba(20, 102, 214, .8);
}
.pp-sel-tag {
    position: absolute; right: 18px; bottom: 14px; z-index: 2; max-width: 84%; text-align: right;
    font-size: 10.5px; font-weight: 700;
    letter-spacing: .07em; text-transform: uppercase; color: rgba(15, 23, 42, .38);
}

.pp-sel-panel { padding: clamp(22px, 3vw, 32px); color: #e2e8f0; display: flex; flex-direction: column; gap: 18px }
.pp-sel-read { display: flex; align-items: baseline; gap: 9px; margin-top: 8px }
.pp-sel-read b { font-size: clamp(34px, 5vw, 50px); font-weight: 800; letter-spacing: -.035em; line-height: 1; font-variant-numeric: tabular-nums }
.pp-sel-read span { font-size: 15px; color: rgba(226, 232, 240, .62) }
.pp-sel-kicker { font-size: 11px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--cyan-soft) }

.pp-range { -webkit-appearance: none; appearance: none; width: 100%; height: 32px; background: transparent; cursor: grab; display: block }
.pp-range:active { cursor: grabbing }
.pp-range:focus-visible { outline: 2px solid var(--cyan); outline-offset: 6px; border-radius: 8px }
.pp-range::-webkit-slider-runnable-track {
    height: 6px; border-radius: 999px;
    background: linear-gradient(90deg, #38bdf8, #22d3ee 38%, #14b8a6 68%, #f59e0b);
}
.pp-range::-webkit-slider-thumb {
    -webkit-appearance: none; width: 26px; height: 26px; border-radius: 50%; background: #fff;
    border: 3px solid var(--color-brand); margin-top: -10px; box-shadow: 0 8px 20px -4px rgba(0, 0, 0, .8);
}
.pp-range::-moz-range-track { height: 6px; border-radius: 999px; background: linear-gradient(90deg, #38bdf8, #22d3ee 38%, #14b8a6 68%, #f59e0b) }
.pp-range::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: #fff; border: 3px solid var(--color-brand) }
.pp-sel-scale { display: flex; justify-content: space-between; margin-top: -8px; font-size: 10px; letter-spacing: .04em; color: rgba(226, 232, 240, .42) }
.pp-sel-hint { margin: 10px 0 0; font-size: 11.5px; line-height: 1.55; color: rgba(226, 232, 240, .45) }
.pp-sel-jump { display: flex; gap: 7px; flex-wrap: wrap }
.pp-sel-jump button {
    font: inherit; font-size: 12px; font-weight: 700; cursor: pointer; color: #cbd5e1;
    background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .14);
    border-radius: 10px; padding: 8px 13px; transition: background .22s, border-color .22s, color .22s, transform .3s var(--ease);
}
.pp-sel-jump button:hover { background: rgba(56, 189, 248, .18); border-color: rgba(125, 211, 252, .5); color: #fff; transform: translateY(-1px) }
.pp-sel-jump button.on {
    color: #fff; border-color: transparent;
    background: linear-gradient(140deg, var(--color-brand), #0b3f8f);
    box-shadow: 0 10px 22px -10px rgba(20, 102, 214, .9);
}
.pp-sel-card { border: 1px solid rgba(125, 211, 252, .2); background: rgba(8, 26, 50, .5); border-radius: 18px; padding: 18px 20px }
.pp-sel-card .n { font-size: 16.5px; font-weight: 800; color: #fff }
.pp-sel-card .note { margin-top: 5px; font-size: 13px; line-height: 1.55; color: rgba(226, 232, 240, .62) }
.pp-sel-rows { display: flex; gap: 20px; flex-wrap: wrap; margin-top: 16px }
.pp-sel-rows div { min-width: 84px }
.pp-sel-rows i { display: block; font-style: normal; font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: rgba(226, 232, 240, .45) }
.pp-sel-rows b { display: block; margin-top: 4px; font-size: 15px; color: #fff; font-variant-numeric: tabular-nums }
.pp-sel-link { display: inline-block; margin-top: 14px; font-size: 14px; font-weight: 700; color: var(--cyan-soft); text-decoration: none }
.pp-sel-link:hover { text-decoration: underline }
.pp-sel-why { font-size: 12.5px; line-height: 1.65; color: rgba(226, 232, 240, .5) }
.pp-sel-over {
    display: none; margin-top: 12px; border-radius: 12px; padding: 11px 14px;
    border: 1px solid rgba(245, 158, 11, .45); background: rgba(120, 53, 15, .28);
    font-size: 12.5px; line-height: 1.6; color: #fde68a;
}
.pp-sel.is-over .pp-sel-over { display: block }
.pp-sel-basis { font-size: 11.5px; line-height: 1.6; color: rgba(226, 232, 240, .38) }
.pp-sel-why b { color: #cbd5e1 }

/* ══ 7. THẺ NGHIÊNG 3D + VỆT SÁNG THEO CON TRỎ ═════════════════════════════ */
.pp-tilt {
    position: relative; transform-style: preserve-3d;
    transform: perspective(1000px) rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg)) translateY(var(--tz, 0px));
    transition: transform .5s var(--ease), box-shadow .5s var(--ease), border-color .3s;
}
/* Vệt sáng đi theo con trỏ — thứ làm thẻ có cảm giác bề mặt bóng thật.
   Không dùng mix-blend-mode: nó tạo stacking context và làm phẳng lớp 3D bên trong thẻ. */
.pp-tilt::after {
    content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
    background: radial-gradient(300px circle at var(--gx, 50%) var(--gy, 50%), rgba(20, 102, 214, .12), rgba(56, 189, 248, .05) 45%, transparent 66%);
    transition: opacity .35s var(--ease);
}
.pp-tilt.is-hot::after { opacity: 1 }

.pp-cards { display: grid; gap: 18px; grid-template-columns: 1fr; margin-top: clamp(26px, 3.5vw, 40px) }
@media (min-width: 640px) { .pp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)) } }
@media (min-width: 1000px) { .pp-cards-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) } }
@media (min-width: 1000px) { .pp-cards-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) } }

.pp-card {
    border: 1px solid var(--color-line); border-radius: 20px; background: #fff; padding: 24px;
    box-shadow: 0 2px 4px -2px rgba(8, 20, 45, .06);
}
.pp-card.is-hot { border-color: rgba(20, 102, 214, .32); box-shadow: 0 34px 60px -26px rgba(8, 20, 45, .38) }
.pp-card-ico {
    display: grid; place-items: center; width: 46px; height: 46px; border-radius: 14px;
    background: linear-gradient(140deg, rgba(20, 102, 214, .12), rgba(56, 189, 248, .16));
    color: var(--color-brand); transform: translateZ(30px);
}
.pp-card-ico svg { width: 23px; height: 23px }
.pp-card-ico { transition: transform .5s var(--ease), background .4s }
.pp-card.is-hot .pp-card-ico { transform: translateZ(30px) translateY(-3px) scale(1.06) }
.pp-card h3 { margin: 16px 0 0; font-size: 16.5px; font-weight: 800; letter-spacing: -.01em; color: var(--color-ink); transform: translateZ(22px) }
.pp-card p { margin: 8px 0 0; font-size: 14px; line-height: 1.68; color: var(--color-muted); transform: translateZ(14px) }

/* Thẻ dòng bơm (S/O/L/X) */
.pp-serie { display: block; text-decoration: none; color: inherit }
.pp-serie-top { display: flex; align-items: flex-start; justify-content: space-between; transform: translateZ(26px) }
.pp-serie-code {
    display: grid; place-items: center; width: 52px; height: 52px; border-radius: 16px;
    font-size: 21px; font-weight: 800; color: #fff;
    background: linear-gradient(140deg, var(--color-brand), #2b8ef0);
    box-shadow: 0 16px 30px -12px rgba(20, 102, 214, .8);
}
.pp-pill {
    border-radius: 999px; background: var(--color-brand-soft); color: var(--color-brand);
    padding: 5px 11px; font-size: 11px; font-weight: 800;
}
.pp-serie-range { margin: 18px 0 0; font-size: 18.5px; font-weight: 800; letter-spacing: -.02em; color: var(--color-ink); font-variant-numeric: tabular-nums; transform: translateZ(18px) }
.pp-serie-note { margin: 7px 0 0; font-size: 14px; line-height: 1.6; color: var(--color-muted) }
.pp-serie-rep { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--color-line) }
.pp-serie-rep i { display: block; font-style: normal; font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #94a3b8 }
.pp-serie-rep b { display: block; margin-top: 3px; font-size: 14.5px; color: var(--color-brand) }
.pp-serie-rep span { font-size: 12.5px; color: var(--color-muted) }
.pp-serie-go { margin-top: 16px; font-size: 14px; font-weight: 700; color: var(--color-brand); opacity: .72; transition: opacity .3s, gap .3s; display: inline-flex; gap: 6px }
.pp-serie:hover .pp-serie-go { opacity: 1; gap: 11px }

/* Bảng so sánh */
.pp-tablewrap { margin-top: clamp(24px, 3vw, 36px); border: 1px solid var(--color-line); border-radius: 20px; background: #fff; overflow: hidden }
.pp-tablescroll { overflow-x: auto }
.pp-table { width: 100%; min-width: 660px; border-collapse: collapse; font-size: 14px }
.pp-table caption { text-align: left; padding: 18px 20px; border-bottom: 1px solid var(--color-line) }
.pp-table caption b { display: block; font-size: 15.5px; font-weight: 800; color: var(--color-ink) }
.pp-table caption span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--color-muted) }
.pp-table th {
    text-align: left; padding: 12px 20px; font-size: 11px; font-weight: 800; letter-spacing: .08em;
    text-transform: uppercase; color: var(--color-brand); background: var(--color-brand-soft);
}
.pp-table td { padding: 14px 20px; border-top: 1px solid var(--color-line); color: var(--color-muted); font-variant-numeric: tabular-nums }
.pp-table tbody tr { transition: background .25s }
.pp-table tbody tr:hover { background: rgba(244, 248, 252, .8) }
.pp-table td:first-child { font-weight: 800; color: var(--color-brand) }
.pp-table a { color: var(--color-ink); font-weight: 700; text-decoration: none }
.pp-table a:hover { color: var(--color-brand); text-decoration: underline }

/* Cảnh báo giới hạn (nói cả nhược điểm) */
.pp-warn {
    margin-top: 22px; border: 1px solid #fcd9a4; border-radius: 20px; padding: 22px 24px;
    background: linear-gradient(120deg, rgba(255, 251, 235, .9), rgba(254, 243, 199, .55));
}
.pp-warn b.t { display: flex; align-items: center; gap: 9px; font-size: 15.5px; font-weight: 800; color: #7c2d12 }
.pp-warn p { margin: 10px 0 0; font-size: 14.5px; line-height: 1.75; color: rgba(120, 53, 15, .88) }
.pp-warn p b { color: #7c2d12 }

/* Nhóm chuyên dụng — chip có vệt sáng khi hover */
.pp-chips { display: flex; flex-wrap: wrap; gap: 11px; margin-top: clamp(24px, 3vw, 34px) }
.pp-chip-link {
    position: relative; overflow: hidden; display: inline-flex; align-items: center; gap: 10px;
    border: 1px solid var(--color-line); border-radius: 14px; background: #fff;
    padding: 13px 18px; text-decoration: none; color: var(--color-ink); font-size: 14.5px; font-weight: 700;
    transition: transform .4s var(--ease), border-color .3s, box-shadow .4s var(--ease), color .3s;
}
.pp-chip-link:hover { transform: translateY(-3px); border-color: var(--color-brand); color: var(--color-brand); box-shadow: 0 20px 36px -18px rgba(20, 102, 214, .55) }
.pp-chip-link .pp-pill { font-size: 10.5px }

/* Ứng dụng */
.pp-apps { display: grid; gap: 12px; margin-top: 22px }
.pp-app {
    position: relative; display: flex; gap: 14px; align-items: flex-start;
    border: 1px solid var(--color-line); border-radius: 16px; background: #fff; padding: 16px 18px;
    transition: transform .4s var(--ease), border-color .3s, box-shadow .4s var(--ease);
}
.pp-app::before {
    content: ''; position: absolute; left: 0; top: 14px; bottom: 14px; width: 3px; border-radius: 3px;
    background: linear-gradient(180deg, var(--color-brand), var(--cyan));
    transform: scaleY(0); transform-origin: 50% 0; transition: transform .45s var(--ease);
}
.pp-app:hover { transform: translateX(4px); border-color: rgba(20, 102, 214, .3); box-shadow: 0 18px 34px -22px rgba(8, 20, 45, .45) }
.pp-app:hover::before { transform: scaleY(1) }
.pp-app-ico { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 11px; background: var(--color-brand-soft); color: var(--color-brand) }
.pp-app-ico svg { width: 19px; height: 19px }
.pp-app b { display: block; font-size: 14.5px; font-weight: 700; color: var(--color-ink) }
.pp-app p { margin: 4px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--color-muted) }

.pp-split { display: grid; gap: clamp(30px, 4.5vw, 56px); grid-template-columns: 1fr }
@media (min-width: 940px) {
    .pp-split { grid-template-columns: 1fr 1fr }
    /* Cột trái ngắn hơn cột phải (6 thẻ ứng dụng) nên khi cuộn xuống sẽ để lại một
       vùng trắng lớn. Ghim nó lại: nội dung "chọn ống" đi cùng suốt danh sách ứng
       dụng — vừa lấp chỗ trống, vừa giữ hai nút CTA trong khung nhìn lâu hơn. */
    .pp-split-sticky { position: sticky; top: 92px; align-self: start }
}

/* ══ 8. SẢN PHẨM TIÊU BIỂU ═════════════════════════════════════════════════ */
.pp-soft { background: linear-gradient(180deg, #f7f9fc, #fff); border-block: 1px solid var(--color-line) }
.pp-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 18px }
.pp-link { font-size: 14px; font-weight: 700; color: var(--color-brand); text-decoration: none; display: inline-flex; gap: 6px; transition: gap .3s var(--ease) }
.pp-link:hover { gap: 11px; text-decoration: underline }

.pp-prod { display: block; overflow: hidden; border: 1px solid var(--color-line); border-radius: 20px; background: #fff; text-decoration: none; color: inherit }
.pp-prod.is-hot { border-color: rgba(20, 102, 214, .3); box-shadow: 0 36px 62px -28px rgba(8, 20, 45, .4) }
/* CHIỀU CAO CỐ ĐỊNH, không dùng aspect-ratio.
   Bẫy đã mắc: `aspect-ratio: 16/10` + `display:grid` + ảnh `height:100%` tạo vòng lặp
   phần trăm-chiều-cao → chiều cao rơi về auto, hàng grid phình theo ảnh và ô ảnh thành
   HÌNH VUÔNG 359px. Ảnh sản phẩm trong DB chỉ 304–324px nên bị PHÓNG 2,2 lần trên màn
   retina → nhìn rạn, nhòe. Đây đúng là hiện tượng khách báo "ảnh bị vỡ".

   Cách chắc chắn: ô ảnh cao cố định, còn ảnh dùng max-width/max-height + width:auto
   → ảnh CHỈ có thể bị thu nhỏ, không bao giờ bị kéo to hơn kích thước thật. */
/* FLEX, không phải grid. Với grid + hàng `auto`, chiều cao của ảnh lại quyết định
   chiều cao hàng, nên `max-height: 100%` của ảnh không có mốc để quy chiếu và ảnh vẫn
   nở ra bằng kích thước thật rồi bị overflow cắt. Trong flex container có chiều cao
   XÁC ĐỊNH, `max-height: 100%` của con quy chiếu đúng vào chiều cao đó. */
.pp-prod-img {
    position: relative; height: clamp(184px, 16.5vw, 220px);
    display: flex; align-items: center; justify-content: center;
    padding: 14px; overflow: hidden; background: #fff;
}
.pp-prod-img img {
    max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain;
    transition: transform .7s var(--ease), filter .5s;
}
.pp-prod.is-hot .pp-prod-img img { transform: translateZ(30px) scale(1.03) }
/* Dải sáng quét qua ảnh một lần khi hover. */
.pp-prod-img::after {
    content: ''; position: absolute; top: 0; bottom: 0; left: -70%; width: 45%; opacity: 0;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .85), transparent);
    transform: skewX(-16deg);
}
.pp-prod.is-hot .pp-prod-img::after { animation: ppShine 1s var(--ease-io) forwards }
.pp-prod-body { padding: 18px 20px 20px; transform: translateZ(18px) }
.pp-prod-cat { font-size: 10.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--color-brand) }
.pp-prod-name {
    margin-top: 7px; font-size: 15.5px; font-weight: 700; line-height: 1.4; color: var(--color-ink);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pp-prod.is-hot .pp-prod-name { color: var(--color-brand) }
.pp-prod-sum { margin-top: 8px; font-size: 13.5px; line-height: 1.6; color: var(--color-muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden }
.pp-prod-go { margin-top: 12px; font-size: 13.5px; font-weight: 700; color: var(--color-brand) }

/* Tin liên quan */
.pp-news { display: block; overflow: hidden; border: 1px solid var(--color-line); border-radius: 18px; background: #fff; text-decoration: none; color: inherit; transition: transform .45s var(--ease), box-shadow .45s var(--ease), border-color .3s }
.pp-news:hover { transform: translateY(-4px); border-color: rgba(20, 102, 214, .28); box-shadow: 0 26px 46px -24px rgba(8, 20, 45, .45) }
/* Cùng lý do như trên: chiều cao cố định thay vì aspect-ratio. Ảnh bìa bài viết nhập
   từ nguồn có bản chỉ rộng 238px, nên khung càng thấp thì càng ít bị phóng. */
/* Ảnh bìa bài viết nhập từ nguồn có bản chỉ rộng 238–291px. Nếu để `object-fit: cover`
   lấp kín khung thì ảnh bị phóng ~2,5 lần trên màn retina → nhòe.
   Cách xử lý: chính ảnh hiển thị ĐÚNG kích thước thật (contain, không phóng), phần
   khung còn lại lấp bằng chính ảnh đó ở dạng nền MỜ. Khung vẫn kín, ảnh vẫn nét. */
.pp-news-img {
    position: relative; height: clamp(150px, 13.5vw, 176px); overflow: hidden; background: #eef2f7;
    display: flex; align-items: center; justify-content: center;
}
.pp-news-img::before {
    content: ''; position: absolute; inset: -10%;
    background-image: var(--cover); background-size: cover; background-position: 50% 45%;
    filter: blur(16px) saturate(1.15); opacity: .5;
}
.pp-news-img img {
    position: relative; max-width: 100%; max-height: 100%; width: auto; height: auto;
    object-fit: contain; transition: transform .8s var(--ease);
}
.pp-news:hover .pp-news-img img { transform: scale(1.04) }
.pp-news-t { padding: 15px 17px; font-size: 14.5px; font-weight: 700; line-height: 1.45; color: var(--color-ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden }
.pp-news:hover .pp-news-t { color: var(--color-brand) }

/* ══ 9. FAQ — mở/đóng có chuyển động thật (JS đo chiều cao) ═════════════════ */
.pp-faq { margin-top: clamp(24px, 3vw, 36px); border: 1px solid var(--color-line); border-radius: 20px; background: #fff; overflow: hidden }
.pp-q { border-top: 1px solid var(--color-line) }
.pp-q:first-child { border-top: 0 }
.pp-q > summary {
    display: flex; align-items: center; justify-content: space-between; gap: 18px; cursor: pointer;
    padding: 19px 22px; font-size: 15.5px; font-weight: 700; color: var(--color-ink);
    list-style: none; transition: color .25s, background .25s;
}
.pp-q > summary::-webkit-details-marker { display: none }
.pp-q > summary:hover { color: var(--color-brand); background: rgba(244, 248, 252, .7) }
.pp-q-ico { position: relative; flex: none; width: 26px; height: 26px; border-radius: 9px; background: var(--color-brand-soft) }
.pp-q-ico::before, .pp-q-ico::after {
    content: ''; position: absolute; left: 50%; top: 50%; background: var(--color-brand); border-radius: 2px;
    transition: transform .45s var(--ease);
}
.pp-q-ico::before { width: 12px; height: 2px; margin: -1px 0 0 -6px }
.pp-q-ico::after { width: 2px; height: 12px; margin: -6px 0 0 -1px }
.pp-q[open] .pp-q-ico::after { transform: rotate(90deg) scaleX(.1) }
.pp-q[open] > summary { color: var(--color-brand) }
.pp-q-body { overflow: hidden }
.pp-q-body > div { padding: 0 22px 20px; font-size: 14.5px; line-height: 1.78; color: var(--color-muted) }
/* Có JS: chiều cao được JS gán → chuyển mượt. Không JS: <details> mặc định vẫn mở/đóng. */
.js-reveal .pp-q-body { transition: height .45s var(--ease) }

/* ══ 10. CTA CUỐI — lưới gradient chuyển động ══════════════════════════════ */
.pp-cta { position: relative; overflow: hidden; color: #fff; padding: clamp(60px, 8vw, 104px) 0; isolation: isolate }
.pp-cta-bg { position: absolute; inset: 0; z-index: 0; background: linear-gradient(118deg, #0b2f6b, #1466d6 58%, #0d9488) }
.pp-cta-mesh { position: absolute; inset: -25%; z-index: 0; filter: blur(58px); opacity: .8 }
.pp-cta-mesh i { position: absolute; width: 48%; height: 62%; border-radius: 50% }
.pp-cta-mesh i:nth-child(1) { left: -4%; top: -8%; background: radial-gradient(circle, rgba(56, 189, 248, .75), transparent 66%); animation: ppDrift1 22s var(--ease-io) infinite }
.pp-cta-mesh i:nth-child(2) { right: -6%; top: 12%; background: radial-gradient(circle, rgba(13, 148, 136, .7), transparent 68%); animation: ppDrift2 28s var(--ease-io) infinite }
.pp-cta-mesh i:nth-child(3) { left: 32%; bottom: -18%; background: radial-gradient(circle, rgba(20, 102, 214, .8), transparent 70%); animation: ppDrift3 34s var(--ease-io) infinite }
.pp-cta-inner { position: relative; z-index: 2; max-width: 760px; margin-inline: auto; text-align: center }
.pp-cta h2 { margin: 0; font-size: clamp(27px, 4vw, 44px); font-weight: 800; letter-spacing: -.03em; line-height: 1.1 }
.pp-cta p { margin: 18px auto 0; max-width: 56ch; font-size: 16.5px; line-height: 1.72; color: rgba(255, 255, 255, .9) }
.pp-cta-row { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin-top: 32px }
.pp-cta-mini { display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: center; margin-top: 28px; font-size: 13px; color: rgba(224, 242, 254, .85) }
.pp-cta-mini span { display: inline-flex; align-items: center; gap: 7px }
.pp-cta-mini svg { width: 16px; height: 16px; color: #5eead4 }

/* ══ 11. ĐIỆN THOẠI + GIẢM CHUYỂN ĐỘNG ════════════════════════════════════ */
@media (max-width: 899px) {
    /* Không ghim cảnh hình cắt trên điện thoại: cuộn dọc dài trên màn nhỏ dễ gây mệt,
       nên rotor quay theo tiến độ mục đi qua khung nhìn thay vì bị ghim lại. */
    .js-reveal .pp-mech-outer { height: auto }
    .js-reveal .pp-mech-sticky { position: static; height: auto; padding: 8px 0 clamp(36px, 6vw, 56px) }
    .js-reveal .pp-beat-stack { min-height: 0 }
    .js-reveal .pp-beat { position: static; opacity: 1; transform: none; filter: none; pointer-events: auto }
    .js-reveal .pp-beat + .pp-beat { margin-top: 26px }
    .pp-rail { display: none }
    .cx-lab { display: none }
    /* Dòng chú thích trên sân khấu bộ chọn xuống 2 dòng và đè lên mép sân khấu ở màn
       hẹp. Đoạn .pp-sel-why ngay dưới đã nói đúng nội dung đó nên ẩn hẳn, không nhắc hai lần. */
    .pp-sel-tag { display: none }
    /* Vòng ống phải rộng hơn hộp ảnh: multiply mà vòng đi qua sau ảnh thì vòng hiện
       xuyên qua thân máy. Số đo: vòng 88% (bán kính trong ~144px) > góc hộp ảnh ~139px. */
    .pp-sel-ring, .pp-sel-fluid { width: min(430px, 88%) }
    .pp-sel-piece { width: min(230px, 64%) }
    .pp-sel-img { max-height: min(158px, 40vw) }
    .pp-scrollhint { display: none } /* 3 nhịp đã xếp dọc, không còn gì để 'cuộn tiếp' */
    .cx-read { position: static; text-align: left; margin-top: 26px }
    .cx-meta { position: static; margin-top: 6px }
    .cx-frame { display: none }
    /* Hạt phim + sàn lưới là hai thứ tốn nhiều fill-rate nhất trên máy yếu. */
    .pp-grain { display: none }
    .pp-floor { opacity: .5; animation: none }
    .pp-hero { min-height: 0; padding-top: 96px }
    /* Z nhỏ lại: translateZ đẩy thẻ về phía người xem nên nó CŨNG bị đẩy ra xa
       tâm phối cảnh — để 110px như desktop là thẻ trái tràn khỏi mép màn hình. */
    .pp-chip-1 { left: 2%; top: 6%; --z: 52px } .pp-chip-2 { right: 0; top: 44%; --z: 56px }
    .pp-chip-3 { left: 3%; bottom: 5%; --z: 48px }
    .pp-chip { font-size: 11px; padding: 7px 12px }
}
@media (max-width: 520px) {
    .pp-chip-2 { display: none }
    .pp-stats { gap: 6px }
}

@media (prefers-reduced-motion: reduce) {
    .cx-rig, .pp-rig, .pp-fluid, .pp-rotor, .pp-spec, .pp-halo, .pp-orbit-1, .pp-orbit-2,
    .pp-aurora i, .pp-beam i, .pp-floor, .pp-port i, .cx-port i, .pp-sel-fluid,
    .pp-cta-mesh i, .pp-dot::after, .pp-cue svg { animation: none !important }
    .js-reveal [data-rv] { opacity: 1 !important; transform: none !important; clip-path: none !important; filter: none !important }
    .pp-w > i { transform: none !important }
    .pp-tilt, .pp-chip, .pp-sel-img, .pp-sel-ring, .pp-sel-badge { transition: none !important }
    .pp-hero-copy, .pp-stage, .pp-cue { transform: none !important; opacity: 1 !important }
    .pp-kicker::before, .pp-card-ico { transition: none !important; transform: none !important }
    .js-reveal .pp-mech-outer { height: auto }
    .js-reveal .pp-mech-sticky { position: static; height: auto; padding: 8px 0 56px }
    .js-reveal .pp-beat { position: static; opacity: 1; transform: none; filter: none }
    .js-reveal .pp-beat + .pp-beat { margin-top: 26px }
    .js-reveal .pp-beat-stack { min-height: 0 }
    .pp-rail, .pp-scrollhint { display: none }
    .pp-progress { display: none }
}
